LCOV - code coverage report
Current view: top level - lib_lc3plus/fft - fft_generic.h (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 396 0.0 %
Date: 2025-05-23 08:37:30 Functions: 0 12 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.5.1                               *
       3             : *              Low Complexity Communication Codec Plus (LC3plus)              *
       4             : *                                                                             *
       5             : * Copyright licence is solely granted through ETSI Intellectual Property      *
       6             : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
       7             : * estoppel or otherwise.                                                      *
       8             : ******************************************************************************/
       9             : 
      10             : /* guard against unindended includes */
      11             : #ifndef INCLUDED_FROM_IISFFT_C
      12             : #error "this file must not be included"
      13             : #endif
      14             : 
      15             : #define FFT_INTERNAL_TRIG_PREC double
      16             : #define BORDER_FOR_SECOND_SCRATCH 100
      17             : 
      18             : static const LC3_INT primeFactors[] = {2,   3,   5,   7,   11,  13,  17,  19,  23,  29,  31,  37,  41,  43,  47,  53,
      19             :                                        59,  61,  67,  71,  73,  79,  83,  89,  97,  101, 103, 107, 109, 113, 127, 131,
      20             :                                        137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
      21             :                                        227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 0};
      22             : 
      23             : /* fft, returns 1 if length is supported and fft was applied */
      24           0 : static LC3_INT fft_n(LC3_FLOAT* x, LC3_INT length)
      25             : {
      26           0 :     switch (length) {
      27           0 :     case 2:
      28           0 :         fft2(x);
      29           0 :         return 1;
      30           0 :     case 3:
      31           0 :         fft3(x);
      32           0 :         return 1;
      33           0 :     case 4:
      34           0 :         fft4(x);
      35           0 :         return 1;
      36           0 :     case 5:
      37           0 :         fft5(x);
      38           0 :         return 1;
      39           0 :     case 8:
      40           0 :         fft8(x);
      41           0 :         return 1;
      42           0 :     case 9:
      43           0 :         fft9(x);
      44           0 :         return 1;
      45           0 :     case 15:
      46           0 :         fft15(x);
      47           0 :         return 1;
      48           0 :     case 16:
      49           0 :         fft16(x);
      50           0 :         return 1;
      51           0 :     case 32:
      52           0 :         fft32(x);
      53           0 :         return 1;
      54           0 :     case 60:
      55           0 :         fft60(x);
      56           0 :         return 1;
      57           0 :     case 64:
      58           0 :         fft64(x);
      59           0 :         return 1;
      60           0 :     case 128:
      61           0 :         fft128(x);
      62           0 :         return 1;
      63           0 :     case 240:
      64           0 :         fft240(x);
      65           0 :         return 1;
      66           0 :     case 256:
      67           0 :         LC3_cfft(x, x + 1, 256, 2, -1);
      68           0 :         return 1;
      69           0 :     case 384:
      70           0 :         fft384(x);
      71           0 :         return 1;
      72           0 :     case 480:
      73           0 :         fft480(x);
      74           0 :         return 1;
      75           0 :     case 512:
      76           0 :         LC3_cfft(x, x + 1, 512, 2, -1);
      77           0 :         return 1;
      78           0 :     case 1024:
      79           0 :         LC3_cfft(x, x + 1, 1024, 2, -1);
      80           0 :         return 1;
      81           0 :     default:
      82           0 :         return 0;
      83             :     }
      84             : }
      85             : 
      86             : 
      87             : /* returns 1 on success or 0 if IISFFT_MAXFACTORS is too small */
      88           0 : static LC3_INT factorize(LC3_INT length, LC3_INT* restrict numFactors, LC3_INT* restrict factor,
      89             :                          LC3_INT* restrict isPrime)
      90             : {
      91           0 :     LC3_INT remainder = length;
      92           0 :     LC3_INT idx = 0, cnt = 0;
      93           0 :     LC3_INT actFac = primeFactors[idx];
      94           0 :     LC3_INT inc    = 0;
      95             : 
      96           0 :     *numFactors = 0;
      97             : 
      98           0 :     while (remainder > 1 && actFac != 0) {
      99           0 :         if (remainder % actFac == 0) {
     100           0 :             if (inc == 0) {
     101           0 :                 inc = 1;
     102           0 :                 (*numFactors)++;
     103             :             }
     104           0 :             remainder /= actFac;
     105             :         } else {
     106           0 :             actFac = primeFactors[++idx];
     107           0 :             inc    = 0;
     108             :         }
     109             :     }
     110           0 :     if (remainder > 1) {
     111           0 :         (*numFactors)++;
     112             :     }
     113             : 
     114           0 :     if (*numFactors > IISFFT_MAXFACTORS)
     115           0 :         return 0;
     116             : 
     117           0 :     idx = 0, cnt = 0, inc = 0;
     118           0 :     remainder     = length;
     119           0 :     actFac        = primeFactors[idx];
     120           0 :     (factor)[cnt] = 1;
     121           0 :     while (remainder > 1 && actFac != 0) {
     122           0 :         if (remainder % actFac == 0) {
     123           0 :             (factor)[cnt] *= actFac;
     124           0 :             remainder /= actFac;
     125           0 :             inc = 1;
     126           0 :             if (factor[cnt] == actFac) { /* first appearance of the factor */
     127           0 :                 isPrime[cnt] = 1;
     128             :             } else {
     129           0 :                 isPrime[cnt] = 0;
     130             :             }
     131             :         } else {
     132           0 :             actFac = primeFactors[++idx];
     133           0 :             if (inc == 1) {
     134           0 :                 cnt++;
     135             :             }
     136           0 :             inc           = 0;
     137           0 :             (factor)[cnt] = 1;
     138             :         }
     139             :     }
     140           0 :     if (remainder > 1) {
     141           0 :         factor[cnt] = remainder;
     142             :     }
     143           0 :     return 1;
     144             : }
     145             : 
     146           0 : static void oddFFT(LC3_FLOAT* restrict x, LC3_INT length, LC3_FLOAT* restrict scratch)
     147             : {
     148             :     LC3_INT                i, k, n;
     149             :     LC3_FLOAT *            src1, *src2, *dest1, *dest2;
     150             :     FFT_INTERNAL_TRIG_PREC sinValOrg, cosValOrg;
     151             : 
     152           0 :     dest1 = scratch + 1;
     153           0 :     dest2 = scratch + length + 1;
     154           0 :     src1  = x + 2;
     155           0 :     src2  = x + 2 * length - 1;
     156             : 
     157           0 :     scratch[0]      = x[0];
     158           0 :     scratch[length] = x[1];
     159             : 
     160           0 :     for (i = 2; i < length; i += 2) {
     161             :         LC3_FLOAT tmp1R, tmp1I, tmp2R, tmp2I;
     162           0 :         tmp1R    = *src1++;
     163           0 :         tmp1I    = *src1++;
     164           0 :         tmp2I    = *src2--;
     165           0 :         tmp2R    = *src2--;
     166           0 :         *dest1++ = tmp1R + tmp2R;
     167           0 :         *dest1++ = tmp1R - tmp2R;
     168           0 :         *dest2++ = tmp1I + tmp2I;
     169           0 :         *dest2++ = tmp1I - tmp2I;
     170             : 
     171           0 :         x[0] += tmp1R + tmp2R;
     172           0 :         x[1] += tmp1I + tmp2I;
     173             :     }
     174             : 
     175           0 :     dest1 = x + 2;
     176           0 :     dest2 = x + 2 * length - 2;
     177           0 :     for (k = 2; k < length; k += 2) {
     178           0 :         FFT_INTERNAL_TRIG_PREC sinVal = 0, cosVal = 1;
     179           0 :         cosValOrg = LC3_COS(-M_PIl * k / length);
     180           0 :         sinValOrg = LC3_SIN(-M_PIl * k / length);
     181             : 
     182           0 :         *dest1 = *dest2 = scratch[0];
     183           0 :         *(dest1 + 1) = *(dest2 + 1) = scratch[length];
     184             : 
     185           0 :         src1 = scratch + 1;
     186           0 :         src2 = scratch + length + 1;
     187             : 
     188           0 :         for (n = 2; n < length; n += 2) {
     189             :             LC3_FLOAT rePre, reMre, imPim, imMim;
     190             :             /*
     191             :             cos(x+y)  = cox(x) cos(y) - sin(x) sin(y);
     192             :             sin(x+y)  = sin(x) cos(y) + cos(x) sin(y);
     193             :             */
     194           0 :             FFT_INTERNAL_TRIG_PREC tmp = cosVal * cosValOrg - sinVal * sinValOrg;
     195           0 :             sinVal                     = sinVal * cosValOrg + cosVal * sinValOrg;
     196           0 :             cosVal                     = tmp;
     197             : 
     198           0 :             rePre = *src1++;
     199           0 :             reMre = *src1++;
     200           0 :             imPim = *src2++;
     201           0 :             imMim = *src2++;
     202             : 
     203           0 :             *dest1 += (LC3_FLOAT)cosVal * rePre - (LC3_FLOAT)sinVal * imMim;
     204           0 :             *(dest1 + 1) += (LC3_FLOAT)sinVal * reMre + (LC3_FLOAT)cosVal * imPim;
     205           0 :             *dest2 += (LC3_FLOAT)cosVal * rePre + (LC3_FLOAT)sinVal * imMim;
     206           0 :             *(dest2 + 1) += (LC3_FLOAT)-sinVal * reMre + (LC3_FLOAT)cosVal * imPim;
     207             :         }
     208           0 :         dest1 += 2;
     209           0 :         dest2 -= 2;
     210             :     }
     211           0 : }
     212             : 
     213           0 : static LC3_INT findInverse(LC3_INT a, LC3_INT b)
     214             : {
     215           0 :     LC3_INT b0 = b, t, q;
     216           0 :     LC3_INT x0 = 0, x1 = 1;
     217             : 
     218           0 :     if (b == 1) {
     219           0 :         return 1;
     220             :     }
     221             : 
     222           0 :     while (a > 1) {
     223           0 :         q = a / b;
     224           0 :         t = b, b = a % b, a = t;
     225           0 :         t = x0, x0 = x1 - q * x0, x1 = t;
     226             :     }
     227             : 
     228           0 :     if (x1 < 0) {
     229           0 :         x1 += b0;
     230             :     }
     231             : 
     232           0 :     return x1;
     233             : }
     234             : 
     235           0 : static LC3_INT getGeneratorStupid(LC3_INT groupLength)
     236             : {
     237           0 :     LC3_INT generator = 2; /* start value */
     238           0 :     LC3_INT count = 1, number = generator;
     239             : 
     240           0 :     while (generator < 100) { /* hopefully the generator is smaller than 100 */
     241           0 :         while (number != 1) {
     242           0 :             number = (number * generator) % groupLength;
     243           0 :             count++;
     244             :         }
     245           0 :         if (count == groupLength - 1) {
     246           0 :             return generator;
     247             :         } else {
     248           0 :             generator++;
     249           0 :             count  = 1;
     250           0 :             number = generator;
     251             :         }
     252             :     }
     253             : 
     254           0 :     return -1;
     255             : }
     256             : 
     257           0 : static LC3_INT getGenerator(LC3_INT groupLength)
     258             : {
     259           0 :     LC3_INT generator = 2; /* start value */
     260             :     LC3_INT count, number, factorCount, found, count2;
     261           0 :     LC3_INT factors[16] = {0};
     262             : 
     263             :     /* factorize: only for a group length with factors < 300 */
     264           0 :     factorCount = 0;
     265           0 :     number      = groupLength - 1;
     266           0 :     found       = 0;
     267           0 :     count       = 0;
     268           0 :     while (number != 1) {
     269           0 :         if (primeFactors[count] == 0) {
     270             :             /* Not all factors listed */
     271           0 :             return getGeneratorStupid(groupLength);
     272             :         }
     273           0 :         if (number % primeFactors[count] == 0) {
     274           0 :             number /= primeFactors[count];
     275           0 :             if (found == 0) {
     276           0 :                 factors[factorCount++] = primeFactors[count];
     277           0 :                 found                  = 1;
     278             :             }
     279             :         } else {
     280           0 :             count++;
     281           0 :             found = 0;
     282             :         }
     283             :     }
     284             : 
     285           0 :     for (count = 0; factors[count] != 0; count++) {
     286           0 :         factors[count] = (groupLength - 1) / factors[count];
     287             :     }
     288             : 
     289             :     /* calculate generator */
     290           0 :     number = generator;
     291           0 :     count  = 0;
     292           0 :     while (factors[count] != 0) {
     293           0 :         for (count2 = 0; count2 < factors[count] - 1; count2++) {
     294           0 :             number = (number * generator) % groupLength;
     295             :         }
     296           0 :         if (number != 1) {
     297           0 :             count++;
     298           0 :             number = generator;
     299           0 :             if (factors[count] == 0) {
     300           0 :                 return generator;
     301             :             }
     302             :         } else {
     303           0 :             count = 0;
     304           0 :             generator++;
     305           0 :             number = generator;
     306             :         }
     307             :     }
     308             : 
     309           0 :     return -1;
     310             : }
     311             : 
     312           0 : static void primeFFT(LC3_FLOAT* restrict x, LC3_INT length, LC3_FLOAT* restrict scratch, LC3_INT* restrict scratch2)
     313             : {
     314           0 :     LC3_INT    i, k, middle = (length - 1) / 2;
     315             :     LC3_FLOAT *src1, *src2, *dest1, *dest2;
     316             :     LC3_INT *  mapping, *map;
     317             :     LC3_INT    generator;
     318             : 
     319           0 :     LC3_INT mappingTable[25][97] = {
     320             :         {0, 2},
     321             :         {0, 2, 4},
     322             :         {0, 2, 4, 8, 6},
     323             :         {0, 2, 6, 4, 12, 8, 10},
     324             :         {0, 2, 4, 8, 16, 10, 20, 18, 14, 6, 12},
     325             :         {0, 2, 4, 8, 16, 6, 12, 24, 22, 18, 10, 20, 14},
     326             :         {0, 2, 6, 18, 20, 26, 10, 30, 22, 32, 28, 16, 14, 8, 24, 4, 12},
     327             :         {0, 2, 4, 8, 16, 32, 26, 14, 28, 18, 36, 34, 30, 22, 6, 12, 24, 10, 20},
     328             :         {0, 2, 10, 4, 20, 8, 40, 16, 34, 32, 22, 18, 44, 36, 42, 26, 38, 6, 30, 12, 14, 24, 28},
     329             :         {0, 2, 4, 8, 16, 32, 6, 12, 24, 48, 38, 18, 36, 14, 28, 56, 54, 50, 42, 26, 52, 46, 34, 10, 20, 40, 22, 44, 30},
     330             :         {0,  2,  6,  18, 54, 38, 52, 32, 34, 40, 58, 50, 26, 16, 48, 20,
     331             :          60, 56, 44, 8,  24, 10, 30, 28, 22, 4,  12, 36, 46, 14, 42},
     332             :         {0,  2,  4,  8,  16, 32, 64, 54, 34, 68, 62, 50, 26, 52, 30, 60, 46, 18, 36,
     333             :          72, 70, 66, 58, 42, 10, 20, 40, 6,  12, 24, 48, 22, 44, 14, 28, 56, 38},
     334             :         {0,  2,  12, 72, 22, 50, 54, 78, 58, 20, 38, 64, 56, 8,  48, 42, 6,  36, 52, 66, 68,
     335             :          80, 70, 10, 60, 32, 28, 4,  24, 62, 44, 18, 26, 74, 34, 40, 76, 46, 30, 16, 14},
     336             :         {0,  2,  6,  18, 54, 76, 56, 82, 74, 50, 64, 20, 60, 8,  24, 72, 44, 46, 52, 70, 38, 28,
     337             :          84, 80, 68, 32, 10, 30, 4,  12, 36, 22, 66, 26, 78, 62, 14, 42, 40, 34, 16, 48, 58},
     338             :         {0,  2,  10, 50, 62, 28, 46, 42, 22, 16, 80, 24, 26, 36, 86, 54, 82, 34, 76, 4,  20, 6,  30, 56,
     339             :          92, 84, 44, 32, 66, 48, 52, 72, 78, 14, 70, 68, 58, 8,  40, 12, 60, 18, 90, 74, 88, 64, 38},
     340             :         {0,   2,   4,  8,  16, 32, 64, 22, 44, 88, 70, 34, 68, 30, 60, 14, 28, 56,  6,  12, 24, 48, 96, 86, 66, 26, 52,
     341             :          104, 102, 98, 90, 74, 42, 84, 62, 18, 36, 72, 38, 76, 46, 92, 78, 50, 100, 94, 82, 58, 10, 20, 40, 80, 54},
     342             :         {0,  2,  4,   8,   16, 32, 64, 10, 20,  40, 80,  42,  84,  50,  100, 82, 46,  92, 66, 14,
     343             :          28, 56, 112, 106, 94, 70, 22, 44, 88,  58, 116, 114, 110, 102, 86,  54, 108, 98, 78, 38,
     344             :          76, 34, 68,  18,  36, 72, 26, 52, 104, 90, 62,  6,   12,  24,  48,  96, 74,  30, 60},
     345             :         {0,  2,   4,  8,  16,  32, 64, 6,  12, 24, 48,  96,  70,  18,  36, 72, 22,  44,  88, 54, 108,
     346             :          94, 66,  10, 20, 40,  80, 38, 76, 30, 60, 120, 118, 114, 106, 90, 58, 116, 110, 98, 74, 26,
     347             :          52, 104, 86, 50, 100, 78, 34, 68, 14, 28, 56,  112, 102, 82,  42, 84, 46,  92,  62},
     348             :         {0,   2,  4,  8,   16,  32, 64, 128, 122, 110, 86, 38,  76,  18,  36,  72,  10, 20, 40, 80, 26, 52, 104,
     349             :          74,  14, 28, 56,  112, 90, 46, 92,  50,  100, 66, 132, 130, 126, 118, 102, 70, 6,  12, 24, 48, 96, 58,
     350             :          116, 98, 62, 124, 114, 94, 54, 108, 82,  30,  60, 120, 106, 78,  22,  44,  88, 42, 84, 34, 68},
     351             :         {0,   2,  14, 98, 118, 116, 102, 4,  28, 54, 94, 90, 62,  8,   56,  108, 46,  38, 124, 16,  112, 74, 92, 76,
     352             :          106, 32, 82, 6,  42,  10,  70,  64, 22, 12, 84, 20, 140, 128, 44,  24,  26,  40, 138, 114, 88,  48, 52, 80,
     353             :          134, 86, 34, 96, 104, 18,  126, 30, 68, 50, 66, 36, 110, 60,  136, 100, 132, 72, 78,  120, 130, 58, 122},
     354             :         {0,   2,   10,  50, 104, 82,  118, 6,   30,  4,   20, 100, 62,  18,  90, 12,  60,  8,  40,
     355             :          54,  124, 36,  34, 24,  120, 16,  80,  108, 102, 72, 68,  48,  94,  32, 14,  70,  58, 144,
     356             :          136, 96,  42,  64, 28,  140, 116, 142, 126, 46,  84, 128, 56,  134, 86, 138, 106, 92, 22,
     357             :          110, 112, 122, 26, 130, 66,  38,  44,  74,  78,  98, 52,  114, 132, 76, 88},
     358             :         {0,   2,   6,   18,  54,  4,   12,  36, 108, 8,   24,  72,  58,  16,  48,  144, 116, 32, 96, 130,
     359             :          74,  64,  34,  102, 148, 128, 68,  46, 138, 98,  136, 92,  118, 38,  114, 26,  78,  76, 70, 52,
     360             :          156, 152, 140, 104, 154, 146, 122, 50, 150, 134, 86,  100, 142, 110, 14,  42,  126, 62, 28, 84,
     361             :          94,  124, 56,  10,  30,  90,  112, 20, 60,  22,  66,  40,  120, 44,  132, 80,  82,  88, 106},
     362             :         {0,   2,   4,   8,   16,  32,  64,  128, 90,  14,  28,  56,  112, 58,  116, 66, 132, 98,  30,  60,  120,
     363             :          74,  148, 130, 94,  22,  44,  88,  10,  20,  40,  80,  160, 154, 142, 118, 70, 140, 114, 62,  124, 82,
     364             :          164, 162, 158, 150, 134, 102, 38,  76,  152, 138, 110, 54,  108, 50,  100, 34, 68,  136, 106, 46,  92,
     365             :          18,  36,  72,  144, 122, 78,  156, 146, 126, 86,  6,   12,  24,  48,  96,  26, 52,  104, 42,  84},
     366             :         {0,   2,   6,   18,  54,  162, 130, 34,  102, 128, 28,  84,  74,  44,  132, 40,  120, 4,
     367             :          12,  36,  108, 146, 82,  68,  26,  78,  56,  168, 148, 88,  86,  80,  62,  8,   24,  72,
     368             :          38,  114, 164, 136, 52,  156, 112, 158, 118, 176, 172, 160, 124, 16,  48,  144, 76,  50,
     369             :          150, 94,  104, 134, 46,  138, 58,  174, 166, 142, 70,  32,  96,  110, 152, 100, 122, 10,
     370             :          30,  90,  92,  98,  116, 170, 154, 106, 140, 64,  14,  42,  126, 22,  66,  20,  60},
     371             :         {0,   2,   10,  50,  56,  86,  42, 16,  80,  12,  60,  106, 142, 128, 58,  96,  92,  72,  166, 54,
     372             :          76,  186, 154, 188, 164, 44,  26, 130, 68,  146, 148, 158, 14,  70,  156, 4,   20,  100, 112, 172,
     373             :          84,  32,  160, 24,  120, 18,  90, 62,  116, 192, 184, 144, 138, 108, 152, 178, 114, 182, 134, 88,
     374             :          52,  66,  136, 98,  102, 122, 28, 140, 118, 8,   40,  6,   30,  150, 168, 64,  126, 48,  46,  36,
     375             :          180, 124, 38,  190, 174, 94,  82, 22,  110, 162, 34,  170, 74,  176, 104, 132, 78}};
     376             : 
     377           0 :     if (length < BORDER_FOR_SECOND_SCRATCH) {
     378           0 :         for (i = 1;; i++) {
     379           0 :             if (primeFactors[i] == length) {
     380           0 :                 mapping = mappingTable[i];
     381           0 :                 break;
     382             :             }
     383           0 :             assert(primeFactors[i] != 0);
     384             :         }
     385             :     } else {
     386           0 :         mapping = scratch2;
     387             : 
     388             :         /* get primitive root */
     389           0 :         generator = getGenerator(length);
     390           0 :         assert(generator != -1);
     391             : 
     392             :         /* init mapping */
     393           0 :         mapping[0] = 0;
     394           0 :         mapping[1] = 1;
     395           0 :         for (i = 2; i < length; i++) {
     396           0 :             mapping[i] = mapping[i - 1] * generator;
     397           0 :             if (mapping[i] > length - 1) {
     398           0 :                 mapping[i] = (mapping[i] % length - 1) + 1;
     399             :             }
     400             :         }
     401             : 
     402             :         /* double mapping value */
     403           0 :         for (i = 1; i < length; i++) {
     404           0 :             mapping[i] *= 2;
     405             :         }
     406             :     }
     407             : 
     408             :     /* remap input to scratch */
     409           0 :     scratch[0] = x[0];
     410           0 :     scratch[1] = x[1];
     411           0 :     scratch[2] = x[2];
     412           0 :     scratch[3] = x[3];
     413           0 :     map        = mapping + length - 1;
     414           0 :     for (i = 4; i < 2 * length; map--) {
     415           0 :         scratch[i++] = x[(*map)];
     416           0 :         scratch[i++] = x[(*map) + 1];
     417             :     }
     418             : 
     419             :     /* print sums and diffs into scratch by using symmetry */
     420           0 :     x[length] = x[1]; /* imaginary und real part */
     421           0 :     dest1     = x + 1;
     422           0 :     dest2     = x + length + 1;
     423           0 :     src1      = scratch + 2;
     424           0 :     src2      = scratch + length + 1;
     425             : 
     426           0 :     for (i = 2; i < length; i += 2) {
     427             :         LC3_FLOAT tmp1R, tmp1I, tmp2R, tmp2I;
     428           0 :         tmp1R    = *src1++;
     429           0 :         tmp1I    = *src1++;
     430           0 :         tmp2R    = *src2++;
     431           0 :         tmp2I    = *src2++;
     432           0 :         *dest1++ = tmp1R + tmp2R;
     433           0 :         *dest1++ = tmp1R - tmp2R;
     434           0 :         *dest2++ = tmp1I + tmp2I;
     435           0 :         *dest2++ = tmp1I - tmp2I;
     436             : 
     437           0 :         scratch[0] += tmp1R + tmp2R;
     438           0 :         scratch[1] += tmp1I + tmp2I;
     439             :     }
     440             : 
     441             :     /* init with values from the first column */
     442           0 :     dest1 = scratch + 2;
     443           0 :     for (i = 1; i < length; i++) {
     444           0 :         *dest1++ = x[0];      /* add real part of x(0)(factor = 1) */
     445           0 :         *dest1++ = x[length]; /* add imaginary part of x(0)(factor = 1) */
     446             :     }
     447             : 
     448           0 :     for (k = 1; k <= middle; k++) {
     449             :         /* loop through all cos/sin values */
     450             :         LC3_FLOAT sinVal, cosVal;
     451             :         LC3_INT   length1, length2;
     452             :         LC3_FLOAT rePre, reMre, imPim, imMim;
     453             : 
     454           0 :         cosVal = (LC3_FLOAT)LC3_COS(-M_PIl * mapping[k] / length);
     455           0 :         sinVal = (LC3_FLOAT)LC3_SIN(-M_PIl * mapping[k] / length);
     456             : 
     457             :         /* compute in two parts (length1, length2) to avoid if() in for loop */
     458           0 :         length1 = middle - k + 1;
     459           0 :         length2 = middle - length1;
     460           0 :         src1    = x + 1;
     461           0 :         src2    = x + length + 1;
     462           0 :         dest1   = scratch + 2 * k;
     463           0 :         dest2   = scratch + 2 * (middle + k);
     464             : 
     465           0 :         for (i = 0; i < length1; i++) {
     466           0 :             rePre = *src1++;
     467           0 :             reMre = *src1++;
     468           0 :             imPim = *src2++;
     469           0 :             imMim = *src2++;
     470             : 
     471           0 :             *dest1++ += cosVal * rePre - sinVal * imMim;
     472           0 :             *dest1++ += cosVal * imPim + sinVal * reMre;
     473             : 
     474           0 :             *dest2++ += cosVal * rePre + sinVal * imMim;
     475           0 :             *dest2++ += cosVal * imPim - sinVal * reMre;
     476             :         }
     477           0 :         if (dest2 == scratch + 2 * length) {
     478           0 :             dest2 = scratch + 2;
     479             :         }
     480           0 :         for (i = 0; i < length2; i++) {
     481           0 :             rePre = *src1++;
     482           0 :             reMre = *src1++;
     483           0 :             imPim = *src2++;
     484           0 :             imMim = *src2++;
     485             : 
     486           0 :             *dest1++ += cosVal * rePre - sinVal * imMim;
     487           0 :             *dest1++ += cosVal * imPim + sinVal * reMre;
     488             : 
     489           0 :             *dest2++ += cosVal * rePre + sinVal * imMim;
     490           0 :             *dest2++ += cosVal * imPim - sinVal * reMre;
     491             :         }
     492             :     }
     493             : 
     494             :     /* remap output to x */
     495           0 :     x[0] = scratch[0];
     496           0 :     x[1] = scratch[1];
     497           0 :     map  = mapping + 1;
     498           0 :     for (i = 2; i < 2 * length; map++) {
     499           0 :         x[(*map)]     = scratch[i++];
     500           0 :         x[(*map) + 1] = scratch[i++];
     501             :     }
     502           0 : }
     503             : 
     504           0 : static void nextFFT(LC3_FLOAT* x, LC3_INT length, LC3_FLOAT* scratch)
     505             : {
     506           0 :     if (fft_n(x, length)) /* have function for length */
     507           0 :         return;
     508             : 
     509           0 :     assert(length % 2 != 0);
     510           0 :     oddFFT(x, length, scratch);
     511             : }
     512             : 
     513           0 : static inline LC3_INT findFactor(const LC3_INT length)
     514             : {
     515             :     static const LC3_INT factors[] = {16, 9, 8, 7, 5, 4, 3, 2, 0};
     516           0 :     LC3_INT              i = 0, factor = 0;
     517           0 :     for (i = 0; factors[i] != 0; i++) {
     518           0 :         if (length % factors[i] == 0) {
     519           0 :             factor = factors[i];
     520           0 :             break;
     521             :         }
     522             :     }
     523           0 :     return factor;
     524             : }
     525             : 
     526           0 : static inline void twiddle(LC3_FLOAT* x, const LC3_INT length, const LC3_INT n1, const LC3_INT n2)
     527             : {
     528             :     LC3_INT                i, ii;
     529             :     FFT_INTERNAL_TRIG_PREC sinValOrg, cosValOrg;
     530           0 :     FFT_INTERNAL_TRIG_PREC sinVal = 0, cosVal = 1;
     531           0 :     FFT_INTERNAL_TRIG_PREC twReal = 0, twImag = 1;
     532             : 
     533           0 :     cosValOrg = LC3_COS(-2 * (LC3_FLOAT)M_PIl / length);
     534           0 :     sinValOrg = LC3_SIN(-2 * (LC3_FLOAT)M_PIl / length);
     535             : 
     536           0 :     for (i = 1; i < n1; i++) {
     537           0 :         FFT_INTERNAL_TRIG_PREC tmp = 0.;
     538           0 :         twReal                     = 1;
     539           0 :         twImag                     = 0;
     540             : 
     541           0 :         tmp    = cosVal * cosValOrg - sinVal * sinValOrg;
     542           0 :         sinVal = sinVal * cosValOrg + cosVal * sinValOrg;
     543           0 :         cosVal = tmp;
     544             : 
     545           0 :         for (ii = 1; ii < n2; ii++) {
     546             :             LC3_FLOAT              xRe, xIm;
     547             :             FFT_INTERNAL_TRIG_PREC tmpReal;
     548             : 
     549           0 :             tmpReal = twReal * cosVal - twImag * sinVal;
     550           0 :             twImag  = twImag * cosVal + sinVal * twReal;
     551           0 :             twReal  = tmpReal;
     552             : 
     553           0 :             xRe = x[2 * (i * n2 + ii)];
     554           0 :             xIm = x[2 * (i * n2 + ii) + 1];
     555             : 
     556           0 :             x[2 * (i * n2 + ii)]     = (LC3_FLOAT)twReal * xRe - (LC3_FLOAT)twImag * xIm;
     557           0 :             x[2 * (i * n2 + ii) + 1] = (LC3_FLOAT)twImag * xRe + (LC3_FLOAT)twReal * xIm;
     558             :         }
     559             :     }
     560           0 : }
     561             : 
     562           0 : static void cooleyTukeyFFT(LC3_FLOAT* restrict x, const LC3_INT length, LC3_FLOAT* restrict scratch,
     563             :                            LC3_INT* restrict scratch2, LC3_INT isPrime)
     564             : {
     565             :     LC3_INT    factor;
     566             :     LC3_INT    i, ii;
     567             :     LC3_INT    n1, n2;
     568           0 :     LC3_INT    cnt = 0;
     569             :     LC3_FLOAT *src, *dest;
     570             : 
     571           0 :     if (fft_n(x, length))
     572           0 :         return;
     573             : 
     574           0 :     factor = findFactor(length);
     575           0 :     if (factor > 0 && (length / factor > 1)) {
     576           0 :         n1 = factor;
     577           0 :         n2 = length / factor;
     578             : 
     579             :         /* DATA Resorting for stage1 */
     580           0 :         dest = scratch;
     581           0 :         for (i = 0; i < 2 * n1; i += 2) {
     582           0 :             src = x + i;
     583           0 :             for (ii = 0; ii < n2; ii++) {
     584             :                 /* *dest++ = x[2*(i+ii*n1)]; */
     585             :                 /* *dest++ = x[2*(i+ii*n1)+1]; */
     586           0 :                 *dest++ = *src;
     587           0 :                 *dest++ = *(src + 1);
     588           0 :                 src += 2 * n1;
     589             :             }
     590             :         }
     591           0 :         src  = scratch;
     592           0 :         dest = x;
     593           0 :         for (i = 0; i < length; i++) {
     594           0 :             *dest++ = *src++;
     595           0 :             *dest++ = *src++;
     596             :         }
     597             :         /* perform n1 ffts of length n2 */
     598           0 :         for (i = 0; i < n1; i++) {
     599           0 :             cooleyTukeyFFT(x + 2 * i * n2, n2, scratch + 2 * i * n2, scratch2, isPrime);
     600             :         }
     601             :         /*data twiddeling */
     602           0 :         twiddle(x, length, n1, n2);
     603             :         /* DATA Resorting for stage2 */
     604           0 :         cnt = 0;
     605           0 :         for (i = 0; i < n2; i++) {
     606           0 :             for (ii = 0; ii < n1; ii++) {
     607           0 :                 scratch[2 * cnt]     = x[2 * (i + ii * n2)];
     608           0 :                 scratch[2 * cnt + 1] = x[2 * (i + ii * n2) + 1];
     609           0 :                 cnt++;
     610             :             }
     611             :         }
     612             :         /* perform n2 ffts of length n1 */
     613           0 :         for (i = 0; i < n2; i++) {
     614           0 :             nextFFT(scratch + 2 * i * n1, n1, x + 2 * i * n1);
     615             :         }
     616           0 :         cnt = 0;
     617           0 :         for (i = 0; i < n1; i++) {
     618           0 :             for (ii = 0; ii < n2; ii++) {
     619           0 :                 x[2 * cnt]     = scratch[2 * (i + ii * n1)];
     620           0 :                 x[2 * cnt + 1] = scratch[2 * (i + ii * n1) + 1];
     621           0 :                 cnt++;
     622             :             }
     623             :         }
     624             :     } else {
     625           0 :         if (isPrime == 1 && length > 23) {
     626           0 :             primeFFT(x, length, scratch, scratch2);
     627             :         } else {
     628           0 :             oddFFT(x, length, scratch);
     629             :         }
     630             :     }
     631             : }
     632             : 
     633           0 : static void pfaDFT(LC3_FLOAT* restrict x, const LC3_INT length, LC3_FLOAT* restrict scratch1, const LC3_INT numFactors,
     634             :                    const LC3_INT* const factor, LC3_INT* restrict scratch2, const LC3_INT* const isPrime)
     635             : {
     636           0 :     LC3_FLOAT* tmp = scratch1;
     637             :     LC3_INT    i, ii, n1, n2, idx, incr, cnt;
     638           0 :     LC3_INT    n1_inv = 1;
     639             : 
     640           0 :     if (numFactors <= 1) {
     641           0 :         cooleyTukeyFFT(x, length, scratch1, scratch2, isPrime[0]);
     642           0 :         return;
     643             :     }
     644             : 
     645           0 :     n2 = factor[0];
     646           0 :     n1 = length / n2;
     647             : 
     648           0 :     n1_inv = findInverse(n1, n2);
     649             : 
     650           0 :     idx  = 0;
     651           0 :     incr = n1 * n1_inv;
     652           0 :     cnt  = 0;
     653           0 :     for (i = 0; i < n1; i++) {
     654           0 :         for (ii = 0; ii < n2 - 1; ii++) {
     655           0 :             tmp[cnt++] = x[2 * idx];
     656           0 :             tmp[cnt++] = x[2 * idx + 1];
     657             : 
     658           0 :             idx += incr;
     659           0 :             if (idx > length) {
     660           0 :                 idx -= length;
     661             :             }
     662             :         }
     663           0 :         tmp[cnt++] = x[2 * idx];
     664           0 :         tmp[cnt++] = x[2 * idx + 1];
     665           0 :         idx++;
     666             :     }
     667             : 
     668           0 :     for (cnt = 0; cnt < length; cnt += n2) {
     669           0 :         cooleyTukeyFFT(tmp + 2 * cnt, n2, x + 2 * cnt, scratch2, isPrime[0]);
     670             :     }
     671           0 :     for (cnt = 0; cnt < n1; cnt++) {
     672           0 :         for (i = 0; i < n2; i++) {
     673           0 :             x[2 * (cnt + i * n1)]     = tmp[2 * (cnt * n2 + i)];
     674           0 :             x[2 * (cnt + i * n1) + 1] = tmp[2 * (cnt * n2 + i) + 1];
     675             :         }
     676             :     }
     677           0 :     for (cnt = 0; cnt < length; cnt += n1) {
     678           0 :         pfaDFT(x + 2 * cnt, n1, tmp, numFactors - 1, &factor[1], scratch2, &isPrime[1]);
     679             :     }
     680             : 
     681           0 :     cnt = 0;
     682           0 :     for (i = 0; i < n2; i++) {
     683           0 :         idx = i * n1;
     684           0 :         for (ii = 0; ii < n1; ii++) {
     685           0 :             tmp[2 * idx]     = x[cnt++];
     686           0 :             tmp[2 * idx + 1] = x[cnt++];
     687           0 :             idx += n2;
     688           0 :             if (idx > length) {
     689           0 :                 idx -= length;
     690             :             }
     691             :         }
     692             :     }
     693             : 
     694           0 :     for (cnt = 0; cnt < length; cnt++) {
     695           0 :         x[2 * cnt]     = tmp[2 * cnt];
     696           0 :         x[2 * cnt + 1] = tmp[2 * cnt + 1];
     697             :     }
     698             : }

Generated by: LCOV version 1.14