arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/ext/neon_accel/macrof.h
poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/ext/neon_accel/macrof.hRaw
  1/*
  2 * This file is extracted from the implementation of the FFT on Arm64/Neon
  3 * available in https://github.com/cothan/Falcon-Arm (neon/macrof.h).
  4 * =============================================================================
  5 * Copyright (c) 2022 by Cryptographic Engineering Research Group (CERG)
  6 * ECE Department, George Mason University
  7 * Fairfax, VA, U.S.A.
  8 * @author: Duc Tri Nguyen dnguye69@gmu.edu, cothannguyen@gmail.com
  9 * Licensed under the Apache License, Version 2.0 (the "License");
 10 * =============================================================================
 11 *
 12 * This 64-bit Floating point NEON macro x1 has not been modified and is provided as is.
 13 */
 14
 15#ifndef MACROF_H
 16#define MACROF_H
 17
 18#include <arm_neon.h>
 19
 20// c <= addr x1
 21#define vload(c, addr) c = vld1q_f64(addr);
 22// c <= addr interleave 2
 23#define vload2(c, addr) c = vld2q_f64(addr);
 24// c <= addr interleave 4
 25#define vload4(c, addr) c = vld4q_f64(addr);
 26
 27#define vstore(addr, c) vst1q_f64(addr, c);
 28// addr <= c
 29#define vstore2(addr, c) vst2q_f64(addr, c);
 30// addr <= c
 31#define vstore4(addr, c) vst4q_f64(addr, c);
 32
 33// c <= addr x2
 34#define vloadx2(c, addr) c = vld1q_f64_x2(addr);
 35// c <= addr x3
 36#define vloadx3(c, addr) c = vld1q_f64_x3(addr);
 37
 38// addr <= c
 39#define vstorex2(addr, c) vst1q_f64_x2(addr, c);
 40
 41// c = a - b
 42#define vfsub(c, a, b) c = vsubq_f64(a, b);
 43
 44// c = a + b
 45#define vfadd(c, a, b) c = vaddq_f64(a, b);
 46
 47// c = a * b
 48#define vfmul(c, a, b) c = vmulq_f64(a, b);
 49
 50// c = a * n (n is constant)
 51#define vfmuln(c, a, n) c = vmulq_n_f64(a, n);
 52
 53// Swap from a|b to b|a
 54#define vswap(c, a) c = vextq_f64(a, a, 1);
 55
 56// c = a * b[i]
 57#define vfmul_lane(c, a, b, i) c = vmulq_laneq_f64(a, b, i);
 58
 59// c = 1/a
 60#define vfinv(c, a) c = vdivq_f64(vdupq_n_f64(1.0), a);
 61
 62// c = -a
 63#define vfneg(c, a) c = vnegq_f64(a);
 64
 65#define transpose_f64(a, b, t, ia, ib, it)      \
 66  t.val[it] = a.val[ia];                        \
 67  a.val[ia] = vzip1q_f64(a.val[ia], b.val[ib]); \
 68  b.val[ib] = vzip2q_f64(t.val[it], b.val[ib]);
 69
 70/*
 71 * c = a + jb
 72 * c[0] = a[0] - b[1]
 73 * c[1] = a[1] + b[0]
 74 */
 75#define vfcaddj(c, a, b) c = vcaddq_rot90_f64(a, b);
 76
 77/*
 78 * c = a - jb
 79 * c[0] = a[0] + b[1]
 80 * c[1] = a[1] - b[0]
 81 */
 82#define vfcsubj(c, a, b) c = vcaddq_rot270_f64(a, b);
 83
 84// c[0] = c[0] + b[0]*a[0], c[1] = c[1] + b[1]*a[0]
 85#define vfcmla(c, a, b) c = vcmlaq_f64(c, a, b);
 86
 87// c[0] = c[0] - b[1]*a[1], c[1] = c[1] + b[0]*a[1]
 88#define vfcmla_90(c, a, b) c = vcmlaq_rot90_f64(c, a, b);
 89
 90// c[0] = c[0] - b[0]*a[0], c[1] = c[1] - b[1]*a[0]
 91#define vfcmla_180(c, a, b) c = vcmlaq_rot180_f64(c, a, b);
 92
 93// c[0] = c[0] + b[1]*a[1], c[1] = c[1] - b[0]*a[1]
 94#define vfcmla_270(c, a, b) c = vcmlaq_rot270_f64(c, a, b);
 95
 96/*
 97 * Complex MUL: c = a*b
 98 * c[0] = a[0]*b[0] - a[1]*b[1]
 99 * c[1] = a[0]*b[1] + a[1]*b[0]
100 */
101#define FPC_CMUL(c, a, b)       \
102  c = vmulq_laneq_f64(b, a, 0); \
103  c = vcmlaq_rot90_f64(c, a, b);
104
105/*
106 * Complex MUL: c = a * conjugate(b) = a * (b[0], -b[1])
107 * c[0] =   b[0]*a[0] + b[1]*a[1]
108 * c[1] = + b[0]*a[1] - b[1]*a[0]
109 */
110#define FPC_CMUL_CONJ(c, a, b)  \
111  c = vmulq_laneq_f64(a, b, 0); \
112  c = vcmlaq_rot270_f64(c, b, a);
113
114#if FMA == 1
115// d = c + a *b
116#define vfmla(d, c, a, b) d = vfmaq_f64(c, a, b);
117// d = c - a * b
118#define vfmls(d, c, a, b) d = vfmsq_f64(c, a, b);
119// d = c + a * b[i]
120#define vfmla_lane(d, c, a, b, i) d = vfmaq_laneq_f64(c, a, b, i);
121// d = c - a * b[i]
122#define vfmls_lane(d, c, a, b, i) d = vfmsq_laneq_f64(c, a, b, i);
123
124#else
125// d = c + a *b
126#define vfmla(d, c, a, b) d = vaddq_f64(c, vmulq_f64(a, b));
127// d = c - a *b
128#define vfmls(d, c, a, b) d = vsubq_f64(c, vmulq_f64(a, b));
129// d = c + a * b[i]
130#define vfmla_lane(d, c, a, b, i) d = vaddq_f64(c, vmulq_laneq_f64(a, b, i));
131
132#define vfmls_lane(d, c, a, b, i) d = vsubq_f64(c, vmulq_laneq_f64(a, b, i));
133
134#endif
135
136#endif