Annotation of embedaddon/strongswan/src/libstrongswan/math/libnttfft/ntt_fft.c, revision 1.1.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>