Annotation of embedaddon/strongswan/src/libstrongswan/math/libnttfft/ntt_fft.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2014-2016 Andreas Steffen
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "ntt_fft.h"
! 17: #include "ntt_fft_reduce.h"
! 18:
! 19: /**
! 20: * Described in header.
! 21: */
! 22: void libnttfft_init(void)
! 23: {
! 24: /* empty */
! 25: }
! 26:
! 27: typedef struct private_ntt_fft_t private_ntt_fft_t;
! 28:
! 29: /**
! 30: * Private data structure for ntt_fft_t object
! 31: */
! 32: struct private_ntt_fft_t {
! 33:
! 34: /**
! 35: * Public interface.
! 36: */
! 37: ntt_fft_t public;
! 38:
! 39: /**
! 40: * FFT parameter set used as constants
! 41: */
! 42: const ntt_fft_params_t *p;
! 43:
! 44: };
! 45:
! 46: METHOD(ntt_fft_t, get_size, uint16_t,
! 47: private_ntt_fft_t *this)
! 48: {
! 49: return this->p->n;
! 50: }
! 51:
! 52: METHOD(ntt_fft_t, get_modulus, uint16_t,
! 53: private_ntt_fft_t *this)
! 54: {
! 55: return this->p->q;
! 56: }
! 57:
! 58: /**
! 59: * Do an FFT butterfly operation
! 60: *
! 61: * x[i1] ---|+|------- x[i1]
! 62: * \/
! 63: * /\ w[iw]
! 64: * x[i2] ---|-|--|*|-- x[i2]
! 65: *
! 66: */
! 67: static void butterfly(private_ntt_fft_t *this, uint32_t *x, int i1,int i2, int iw)
! 68: {
! 69: uint32_t xp, xm;
! 70:
! 71: xp = x[i1] + x[i2];
! 72: xm = x[i1] + (this->p->q - x[i2]);
! 73: if (xp >= this->p->q)
! 74: {
! 75: xp -= this->p->q;
! 76: }
! 77: x[i1] = xp;
! 78: x[i2] = ntt_fft_mreduce(xm * this->p->wr[iw], this->p);
! 79: }
! 80:
! 81: /**
! 82: * Trivial butterfly operation of last FFT stage
! 83: */
! 84: static void butterfly_last(private_ntt_fft_t *this, uint32_t *x, int i1)
! 85: {
! 86: uint32_t xp, xm;
! 87: int i2 = i1 + 1;
! 88:
! 89: xp = x[i1] + x[i2];
! 90: xm = x[i1] + (this->p->q - x[i2]);
! 91: if (xp >= this->p->q)
! 92: {
! 93: xp -= this->p->q;
! 94: }
! 95: if (xm >= this->p->q)
! 96: {
! 97: xm -= this->p->q;
! 98: }
! 99: x[i1] = xp;
! 100: x[i2] = xm;
! 101: }
! 102:
! 103: METHOD(ntt_fft_t, transform, void,
! 104: private_ntt_fft_t *this, uint32_t *a, uint32_t *b, bool inverse)
! 105: {
! 106: int stage, i, j, k, m, n, s, t, iw, i_rev;
! 107: uint32_t tmp;
! 108:
! 109: /* we are going to use the transform size n a lot */
! 110: n = this->p->n;
! 111: s = this->p->s;
! 112:
! 113: if (!inverse)
! 114: {
! 115: /* apply linear phase needed for negative wrapped convolution */
! 116: for (i = 0; i < n; i++)
! 117: {
! 118: b[i] = ntt_fft_mreduce(a[i] * this->p->wf[s*i], this->p);
! 119: }
! 120: }
! 121: else if (a != b)
! 122: {
! 123: /* copy if input and output array are not the same */
! 124: for (i = 0; i < n; i++)
! 125: {
! 126: b[i] = a[i];
! 127: }
! 128: }
! 129:
! 130: m = n;
! 131: k = 1;
! 132:
! 133: for (stage = this->p->stages; stage > 0; stage--)
! 134: {
! 135: m >>= 1;
! 136: t = 0;
! 137:
! 138: for (j = 0; j < k; j++)
! 139: {
! 140: if (stage == 1)
! 141: {
! 142: butterfly_last(this, b, t);
! 143: }
! 144: else
! 145: {
! 146: for (i = 0; i < m; i++)
! 147: {
! 148: iw = s * (inverse ? (n - i * k) : (i * k));
! 149: butterfly(this, b, t + i, t + i + m, iw);
! 150: }
! 151: }
! 152: t += 2*m;
! 153: }
! 154: k <<= 1;
! 155: }
! 156:
! 157: /* Sort output in bit-reverse order */
! 158: for (i = 0; i < n; i++)
! 159: {
! 160: i_rev = this->p->rev[i];
! 161:
! 162: if (i_rev > i)
! 163: {
! 164: tmp = b[i];
! 165: b[i] = b[i_rev];
! 166: b[i_rev] = tmp;
! 167: }
! 168: }
! 169:
! 170: /**
! 171: * Compensate the linear phase needed for negative wrapped convolution
! 172: * and normalize the output array with 1/n mod q after the inverse FFT.
! 173: */
! 174: if (inverse)
! 175: {
! 176: for (i = 0; i < n; i++)
! 177: {
! 178: b[i] = ntt_fft_mreduce(b[i] * this->p->wi[i], this->p);
! 179: }
! 180: }
! 181: }
! 182:
! 183: METHOD(ntt_fft_t, destroy, void,
! 184: private_ntt_fft_t *this)
! 185: {
! 186: free(this);
! 187: }
! 188:
! 189: /**
! 190: * See header.
! 191: */
! 192: ntt_fft_t *ntt_fft_create(const ntt_fft_params_t *params)
! 193: {
! 194: private_ntt_fft_t *this;
! 195:
! 196: INIT(this,
! 197: .public = {
! 198: .get_size = _get_size,
! 199: .get_modulus = _get_modulus,
! 200: .transform = _transform,
! 201: .destroy = _destroy,
! 202: },
! 203: .p = params,
! 204: );
! 205:
! 206: return &this->public;
! 207: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>