annotate src/fftw-3.3.8/libbench2/mp.c @ 169:223a55898ab9 tip default

Add null config files
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 02 Mar 2020 14:03:47 +0000
parents bd3cc4d1df30
children
rev   line source
cannam@167 1 #include "config.h"
cannam@167 2 #include "libbench2/bench.h"
cannam@167 3 #include <math.h>
cannam@167 4
cannam@167 5 #define DG unsigned short
cannam@167 6 #define ACC unsigned long
cannam@167 7 #define REAL bench_real
cannam@167 8 #define BITS_IN_REAL 53 /* mantissa */
cannam@167 9
cannam@167 10 #define SHFT 16
cannam@167 11 #define RADIX 65536L
cannam@167 12 #define IRADIX (1.0 / RADIX)
cannam@167 13 #define LO(x) ((x) & (RADIX - 1))
cannam@167 14 #define HI(x) ((x) >> SHFT)
cannam@167 15 #define HI_SIGNED(x) \
cannam@167 16 ((((x) + (ACC)(RADIX >> 1) * RADIX) >> SHFT) - (RADIX >> 1))
cannam@167 17 #define ZEROEXP (-32768)
cannam@167 18
cannam@167 19 #define LEN 10
cannam@167 20
cannam@167 21 typedef struct {
cannam@167 22 short sign;
cannam@167 23 short expt;
cannam@167 24 DG d[LEN];
cannam@167 25 } N[1];
cannam@167 26
cannam@167 27 #define EXA a->expt
cannam@167 28 #define EXB b->expt
cannam@167 29 #define EXC c->expt
cannam@167 30
cannam@167 31 #define AD a->d
cannam@167 32 #define BD b->d
cannam@167 33
cannam@167 34 #define SGNA a->sign
cannam@167 35 #define SGNB b->sign
cannam@167 36
cannam@167 37 static const N zero = {{ 1, ZEROEXP, {0} }};
cannam@167 38
cannam@167 39 static void cpy(const N a, N b)
cannam@167 40 {
cannam@167 41 *b = *a;
cannam@167 42 }
cannam@167 43
cannam@167 44 static void fromreal(REAL x, N a)
cannam@167 45 {
cannam@167 46 int i, e;
cannam@167 47
cannam@167 48 cpy(zero, a);
cannam@167 49 if (x == 0.0) return;
cannam@167 50
cannam@167 51 if (x >= 0) { SGNA = 1; }
cannam@167 52 else { SGNA = -1; x = -x; }
cannam@167 53
cannam@167 54 e = 0;
cannam@167 55 while (x >= 1.0) { x *= IRADIX; ++e; }
cannam@167 56 while (x < IRADIX) { x *= RADIX; --e; }
cannam@167 57 EXA = e;
cannam@167 58
cannam@167 59 for (i = LEN - 1; i >= 0 && x != 0.0; --i) {
cannam@167 60 REAL y;
cannam@167 61
cannam@167 62 x *= RADIX;
cannam@167 63 y = (REAL) ((int) x);
cannam@167 64 AD[i] = (DG)y;
cannam@167 65 x -= y;
cannam@167 66 }
cannam@167 67 }
cannam@167 68
cannam@167 69 static void fromshort(int x, N a)
cannam@167 70 {
cannam@167 71 cpy(zero, a);
cannam@167 72
cannam@167 73 if (x < 0) { x = -x; SGNA = -1; }
cannam@167 74 else { SGNA = 1; }
cannam@167 75 EXA = 1;
cannam@167 76 AD[LEN - 1] = x;
cannam@167 77 }
cannam@167 78
cannam@167 79 static void pack(DG *d, int e, int s, int l, N a)
cannam@167 80 {
cannam@167 81 int i, j;
cannam@167 82
cannam@167 83 for (i = l - 1; i >= 0; --i, --e)
cannam@167 84 if (d[i] != 0)
cannam@167 85 break;
cannam@167 86
cannam@167 87 if (i < 0) {
cannam@167 88 /* number is zero */
cannam@167 89 cpy(zero, a);
cannam@167 90 } else {
cannam@167 91 EXA = e;
cannam@167 92 SGNA = s;
cannam@167 93
cannam@167 94 if (i >= LEN - 1) {
cannam@167 95 for (j = LEN - 1; j >= 0; --i, --j)
cannam@167 96 AD[j] = d[i];
cannam@167 97 } else {
cannam@167 98 for (j = LEN - 1; i >= 0; --i, --j)
cannam@167 99 AD[j] = d[i];
cannam@167 100 for ( ; j >= 0; --j)
cannam@167 101 AD[j] = 0;
cannam@167 102 }
cannam@167 103 }
cannam@167 104 }
cannam@167 105
cannam@167 106
cannam@167 107 /* compare absolute values */
cannam@167 108 static int abscmp(const N a, const N b)
cannam@167 109 {
cannam@167 110 int i;
cannam@167 111 if (EXA > EXB) return 1;
cannam@167 112 if (EXA < EXB) return -1;
cannam@167 113 for (i = LEN - 1; i >= 0; --i) {
cannam@167 114 if (AD[i] > BD[i])
cannam@167 115 return 1;
cannam@167 116 if (AD[i] < BD[i])
cannam@167 117 return -1;
cannam@167 118 }
cannam@167 119 return 0;
cannam@167 120 }
cannam@167 121
cannam@167 122 static int eq(const N a, const N b)
cannam@167 123 {
cannam@167 124 return (SGNA == SGNB) && (abscmp(a, b) == 0);
cannam@167 125 }
cannam@167 126
cannam@167 127 /* add magnitudes, for |a| >= |b| */
cannam@167 128 static void addmag0(int s, const N a, const N b, N c)
cannam@167 129 {
cannam@167 130 int ia, ib;
cannam@167 131 ACC r = 0;
cannam@167 132 DG d[LEN + 1];
cannam@167 133
cannam@167 134 for (ia = 0, ib = EXA - EXB; ib < LEN; ++ia, ++ib) {
cannam@167 135 r += (ACC)AD[ia] + (ACC)BD[ib];
cannam@167 136 d[ia] = LO(r);
cannam@167 137 r = HI(r);
cannam@167 138 }
cannam@167 139 for (; ia < LEN; ++ia) {
cannam@167 140 r += (ACC)AD[ia];
cannam@167 141 d[ia] = LO(r);
cannam@167 142 r = HI(r);
cannam@167 143 }
cannam@167 144 d[ia] = LO(r);
cannam@167 145 pack(d, EXA + 1, s * SGNA, LEN + 1, c);
cannam@167 146 }
cannam@167 147
cannam@167 148 static void addmag(int s, const N a, const N b, N c)
cannam@167 149 {
cannam@167 150 if (abscmp(a, b) > 0) addmag0(1, a, b, c); else addmag0(s, b, a, c);
cannam@167 151 }
cannam@167 152
cannam@167 153 /* subtract magnitudes, for |a| >= |b| */
cannam@167 154 static void submag0(int s, const N a, const N b, N c)
cannam@167 155 {
cannam@167 156 int ia, ib;
cannam@167 157 ACC r = 0;
cannam@167 158 DG d[LEN];
cannam@167 159
cannam@167 160 for (ia = 0, ib = EXA - EXB; ib < LEN; ++ia, ++ib) {
cannam@167 161 r += (ACC)AD[ia] - (ACC)BD[ib];
cannam@167 162 d[ia] = LO(r);
cannam@167 163 r = HI_SIGNED(r);
cannam@167 164 }
cannam@167 165 for (; ia < LEN; ++ia) {
cannam@167 166 r += (ACC)AD[ia];
cannam@167 167 d[ia] = LO(r);
cannam@167 168 r = HI_SIGNED(r);
cannam@167 169 }
cannam@167 170
cannam@167 171 pack(d, EXA, s * SGNA, LEN, c);
cannam@167 172 }
cannam@167 173
cannam@167 174 static void submag(int s, const N a, const N b, N c)
cannam@167 175 {
cannam@167 176 if (abscmp(a, b) > 0) submag0(1, a, b, c); else submag0(s, b, a, c);
cannam@167 177 }
cannam@167 178
cannam@167 179 /* c = a + b */
cannam@167 180 static void add(const N a, const N b, N c)
cannam@167 181 {
cannam@167 182 if (SGNA == SGNB) addmag(1, a, b, c); else submag(1, a, b, c);
cannam@167 183 }
cannam@167 184
cannam@167 185 static void sub(const N a, const N b, N c)
cannam@167 186 {
cannam@167 187 if (SGNA == SGNB) submag(-1, a, b, c); else addmag(-1, a, b, c);
cannam@167 188 }
cannam@167 189
cannam@167 190 static void mul(const N a, const N b, N c)
cannam@167 191 {
cannam@167 192 DG d[2 * LEN];
cannam@167 193 int i, j, k;
cannam@167 194 ACC r;
cannam@167 195
cannam@167 196 for (i = 0; i < LEN; ++i)
cannam@167 197 d[2 * i] = d[2 * i + 1] = 0;
cannam@167 198
cannam@167 199 for (i = 0; i < LEN; ++i) {
cannam@167 200 ACC ai = AD[i];
cannam@167 201 if (ai) {
cannam@167 202 r = 0;
cannam@167 203 for (j = 0, k = i; j < LEN; ++j, ++k) {
cannam@167 204 r += ai * (ACC)BD[j] + (ACC)d[k];
cannam@167 205 d[k] = LO(r);
cannam@167 206 r = HI(r);
cannam@167 207 }
cannam@167 208 d[k] = LO(r);
cannam@167 209 }
cannam@167 210 }
cannam@167 211
cannam@167 212 pack(d, EXA + EXB, SGNA * SGNB, 2 * LEN, c);
cannam@167 213 }
cannam@167 214
cannam@167 215 static REAL toreal(const N a)
cannam@167 216 {
cannam@167 217 REAL h, l, f;
cannam@167 218 int i, bits;
cannam@167 219 ACC r;
cannam@167 220 DG sticky;
cannam@167 221
cannam@167 222 if (EXA != ZEROEXP) {
cannam@167 223 f = IRADIX;
cannam@167 224 i = LEN;
cannam@167 225
cannam@167 226 bits = 0;
cannam@167 227 h = (r = AD[--i]) * f; f *= IRADIX;
cannam@167 228 for (bits = 0; r > 0; ++bits)
cannam@167 229 r >>= 1;
cannam@167 230
cannam@167 231 /* first digit */
cannam@167 232 while (bits + SHFT <= BITS_IN_REAL) {
cannam@167 233 h += AD[--i] * f; f *= IRADIX; bits += SHFT;
cannam@167 234 }
cannam@167 235
cannam@167 236 /* guard digit (leave one bit for sticky bit, hence `<' instead
cannam@167 237 of `<=') */
cannam@167 238 bits = 0; l = 0.0;
cannam@167 239 while (bits + SHFT < BITS_IN_REAL) {
cannam@167 240 l += AD[--i] * f; f *= IRADIX; bits += SHFT;
cannam@167 241 }
cannam@167 242
cannam@167 243 /* sticky bit */
cannam@167 244 sticky = 0;
cannam@167 245 while (i > 0)
cannam@167 246 sticky |= AD[--i];
cannam@167 247
cannam@167 248 if (sticky)
cannam@167 249 l += (RADIX / 2) * f;
cannam@167 250
cannam@167 251 h += l;
cannam@167 252
cannam@167 253 for (i = 0; i < EXA; ++i) h *= (REAL)RADIX;
cannam@167 254 for (i = 0; i > EXA; --i) h *= IRADIX;
cannam@167 255 if (SGNA == -1) h = -h;
cannam@167 256 return h;
cannam@167 257 } else {
cannam@167 258 return 0.0;
cannam@167 259 }
cannam@167 260 }
cannam@167 261
cannam@167 262 static void neg(N a)
cannam@167 263 {
cannam@167 264 SGNA = -SGNA;
cannam@167 265 }
cannam@167 266
cannam@167 267 static void inv(const N a, N x)
cannam@167 268 {
cannam@167 269 N w, z, one, two;
cannam@167 270
cannam@167 271 fromreal(1.0 / toreal(a), x); /* initial guess */
cannam@167 272 fromshort(1, one);
cannam@167 273 fromshort(2, two);
cannam@167 274
cannam@167 275 for (;;) {
cannam@167 276 /* Newton */
cannam@167 277 mul(a, x, w);
cannam@167 278 sub(two, w, z);
cannam@167 279 if (eq(one, z)) break;
cannam@167 280 mul(x, z, x);
cannam@167 281 }
cannam@167 282 }
cannam@167 283
cannam@167 284
cannam@167 285 /* 2 pi */
cannam@167 286 static const N n2pi = {{
cannam@167 287 1, 1,
cannam@167 288 {18450, 59017, 1760, 5212, 9779, 4518, 2886, 54545, 18558, 6}
cannam@167 289 }};
cannam@167 290
cannam@167 291 /* 1 / 31! */
cannam@167 292 static const N i31fac = {{
cannam@167 293 1, -7,
cannam@167 294 {28087, 45433, 51357, 24545, 14291, 3954, 57879, 8109, 38716, 41382}
cannam@167 295 }};
cannam@167 296
cannam@167 297
cannam@167 298 /* 1 / 32! */
cannam@167 299 static const N i32fac = {{
cannam@167 300 1, -7,
cannam@167 301 {52078, 60811, 3652, 39679, 37310, 47227, 28432, 57597, 13497, 1293}
cannam@167 302 }};
cannam@167 303
cannam@167 304 static void msin(const N a, N b)
cannam@167 305 {
cannam@167 306 N a2, g, k;
cannam@167 307 int i;
cannam@167 308
cannam@167 309 cpy(i31fac, g);
cannam@167 310 cpy(g, b);
cannam@167 311 mul(a, a, a2);
cannam@167 312
cannam@167 313 /* Taylor */
cannam@167 314 for (i = 31; i > 1; i -= 2) {
cannam@167 315 fromshort(i * (i - 1), k);
cannam@167 316 mul(k, g, g);
cannam@167 317 mul(a2, b, k);
cannam@167 318 sub(g, k, b);
cannam@167 319 }
cannam@167 320 mul(a, b, b);
cannam@167 321 }
cannam@167 322
cannam@167 323 static void mcos(const N a, N b)
cannam@167 324 {
cannam@167 325 N a2, g, k;
cannam@167 326 int i;
cannam@167 327
cannam@167 328 cpy(i32fac, g);
cannam@167 329 cpy(g, b);
cannam@167 330 mul(a, a, a2);
cannam@167 331
cannam@167 332 /* Taylor */
cannam@167 333 for (i = 32; i > 0; i -= 2) {
cannam@167 334 fromshort(i * (i - 1), k);
cannam@167 335 mul(k, g, g);
cannam@167 336 mul(a2, b, k);
cannam@167 337 sub(g, k, b);
cannam@167 338 }
cannam@167 339 }
cannam@167 340
cannam@167 341 static void by2pi(REAL m, REAL n, N a)
cannam@167 342 {
cannam@167 343 N b;
cannam@167 344
cannam@167 345 fromreal(n, b);
cannam@167 346 inv(b, a);
cannam@167 347 fromreal(m, b);
cannam@167 348 mul(a, b, a);
cannam@167 349 mul(n2pi, a, a);
cannam@167 350 }
cannam@167 351
cannam@167 352 static void sin2pi(REAL m, REAL n, N a);
cannam@167 353 static void cos2pi(REAL m, REAL n, N a)
cannam@167 354 {
cannam@167 355 N b;
cannam@167 356 if (m < 0) cos2pi(-m, n, a);
cannam@167 357 else if (m > n * 0.5) cos2pi(n - m, n, a);
cannam@167 358 else if (m > n * 0.25) {sin2pi(m - n * 0.25, n, a); neg(a);}
cannam@167 359 else if (m > n * 0.125) sin2pi(n * 0.25 - m, n, a);
cannam@167 360 else { by2pi(m, n, b); mcos(b, a); }
cannam@167 361 }
cannam@167 362
cannam@167 363 static void sin2pi(REAL m, REAL n, N a)
cannam@167 364 {
cannam@167 365 N b;
cannam@167 366 if (m < 0) {sin2pi(-m, n, a); neg(a);}
cannam@167 367 else if (m > n * 0.5) {sin2pi(n - m, n, a); neg(a);}
cannam@167 368 else if (m > n * 0.25) {cos2pi(m - n * 0.25, n, a);}
cannam@167 369 else if (m > n * 0.125) {cos2pi(n * 0.25 - m, n, a);}
cannam@167 370 else {by2pi(m, n, b); msin(b, a);}
cannam@167 371 }
cannam@167 372
cannam@167 373 /*----------------------------------------------------------------------*/
cannam@167 374 /* FFT stuff */
cannam@167 375
cannam@167 376 /* (r0 + i i0)(r1 + i i1) */
cannam@167 377 static void cmul(N r0, N i0, N r1, N i1, N r2, N i2)
cannam@167 378 {
cannam@167 379 N s, t, q;
cannam@167 380 mul(r0, r1, s);
cannam@167 381 mul(i0, i1, t);
cannam@167 382 sub(s, t, q);
cannam@167 383 mul(r0, i1, s);
cannam@167 384 mul(i0, r1, t);
cannam@167 385 add(s, t, i2);
cannam@167 386 cpy(q, r2);
cannam@167 387 }
cannam@167 388
cannam@167 389 /* (r0 - i i0)(r1 + i i1) */
cannam@167 390 static void cmulj(N r0, N i0, N r1, N i1, N r2, N i2)
cannam@167 391 {
cannam@167 392 N s, t, q;
cannam@167 393 mul(r0, r1, s);
cannam@167 394 mul(i0, i1, t);
cannam@167 395 add(s, t, q);
cannam@167 396 mul(r0, i1, s);
cannam@167 397 mul(i0, r1, t);
cannam@167 398 sub(s, t, i2);
cannam@167 399 cpy(q, r2);
cannam@167 400 }
cannam@167 401
cannam@167 402 static void mcexp(int m, int n, N r, N i)
cannam@167 403 {
cannam@167 404 static int cached_n = -1;
cannam@167 405 static N w[64][2];
cannam@167 406 int k, j;
cannam@167 407 if (n != cached_n) {
cannam@167 408 for (j = 1, k = 0; j < n; j += j, ++k) {
cannam@167 409 cos2pi(j, n, w[k][0]);
cannam@167 410 sin2pi(j, n, w[k][1]);
cannam@167 411 }
cannam@167 412 cached_n = n;
cannam@167 413 }
cannam@167 414
cannam@167 415 fromshort(1, r);
cannam@167 416 fromshort(0, i);
cannam@167 417 if (m > 0) {
cannam@167 418 for (k = 0; m; ++k, m >>= 1)
cannam@167 419 if (m & 1)
cannam@167 420 cmul(w[k][0], w[k][1], r, i, r, i);
cannam@167 421 } else {
cannam@167 422 m = -m;
cannam@167 423 for (k = 0; m; ++k, m >>= 1)
cannam@167 424 if (m & 1)
cannam@167 425 cmulj(w[k][0], w[k][1], r, i, r, i);
cannam@167 426 }
cannam@167 427 }
cannam@167 428
cannam@167 429 static void bitrev(int n, N *a)
cannam@167 430 {
cannam@167 431 int i, j, m;
cannam@167 432 for (i = j = 0; i < n - 1; ++i) {
cannam@167 433 if (i < j) {
cannam@167 434 N t;
cannam@167 435 cpy(a[2*i], t); cpy(a[2*j], a[2*i]); cpy(t, a[2*j]);
cannam@167 436 cpy(a[2*i+1], t); cpy(a[2*j+1], a[2*i+1]); cpy(t, a[2*j+1]);
cannam@167 437 }
cannam@167 438
cannam@167 439 /* bit reversed counter */
cannam@167 440 m = n; do { m >>= 1; j ^= m; } while (!(j & m));
cannam@167 441 }
cannam@167 442 }
cannam@167 443
cannam@167 444 static void fft0(int n, N *a, int sign)
cannam@167 445 {
cannam@167 446 int i, j, k;
cannam@167 447
cannam@167 448 bitrev(n, a);
cannam@167 449 for (i = 1; i < n; i = 2 * i) {
cannam@167 450 for (j = 0; j < i; ++j) {
cannam@167 451 N wr, wi;
cannam@167 452 mcexp(sign * (int)j, 2 * i, wr, wi);
cannam@167 453 for (k = j; k < n; k += 2 * i) {
cannam@167 454 N *a0 = a + 2 * k;
cannam@167 455 N *a1 = a0 + 2 * i;
cannam@167 456 N r0, i0, r1, i1, t0, t1, xr, xi;
cannam@167 457 cpy(a0[0], r0); cpy(a0[1], i0);
cannam@167 458 cpy(a1[0], r1); cpy(a1[1], i1);
cannam@167 459 mul(r1, wr, t0); mul(i1, wi, t1); sub(t0, t1, xr);
cannam@167 460 mul(r1, wi, t0); mul(i1, wr, t1); add(t0, t1, xi);
cannam@167 461 add(r0, xr, a0[0]); add(i0, xi, a0[1]);
cannam@167 462 sub(r0, xr, a1[0]); sub(i0, xi, a1[1]);
cannam@167 463 }
cannam@167 464 }
cannam@167 465 }
cannam@167 466 }
cannam@167 467
cannam@167 468 /* a[2*k]+i*a[2*k+1] = exp(2*pi*i*k^2/(2*n)) */
cannam@167 469 static void bluestein_sequence(int n, N *a)
cannam@167 470 {
cannam@167 471 int k, ksq, n2 = 2 * n;
cannam@167 472
cannam@167 473 ksq = 1; /* (-1)^2 */
cannam@167 474 for (k = 0; k < n; ++k) {
cannam@167 475 /* careful with overflow */
cannam@167 476 ksq = ksq + 2*k - 1; while (ksq > n2) ksq -= n2;
cannam@167 477 mcexp(ksq, n2, a[2*k], a[2*k+1]);
cannam@167 478 }
cannam@167 479 }
cannam@167 480
cannam@167 481 static int pow2_atleast(int x)
cannam@167 482 {
cannam@167 483 int h;
cannam@167 484 for (h = 1; h < x; h = 2 * h)
cannam@167 485 ;
cannam@167 486 return h;
cannam@167 487 }
cannam@167 488
cannam@167 489 static N *cached_bluestein_w = 0;
cannam@167 490 static N *cached_bluestein_y = 0;
cannam@167 491 static int cached_bluestein_n = -1;
cannam@167 492
cannam@167 493 static void bluestein(int n, N *a)
cannam@167 494 {
cannam@167 495 int nb = pow2_atleast(2 * n);
cannam@167 496 N *b = (N *)bench_malloc(2 * nb * sizeof(N));
cannam@167 497 N *w = cached_bluestein_w;
cannam@167 498 N *y = cached_bluestein_y;
cannam@167 499 N nbinv;
cannam@167 500 int i;
cannam@167 501
cannam@167 502 fromreal(1.0 / nb, nbinv); /* exact because nb = 2^k */
cannam@167 503
cannam@167 504 if (cached_bluestein_n != n) {
cannam@167 505 if (w) bench_free(w);
cannam@167 506 if (y) bench_free(y);
cannam@167 507 w = (N *)bench_malloc(2 * n * sizeof(N));
cannam@167 508 y = (N *)bench_malloc(2 * nb * sizeof(N));
cannam@167 509 cached_bluestein_n = n;
cannam@167 510 cached_bluestein_w = w;
cannam@167 511 cached_bluestein_y = y;
cannam@167 512
cannam@167 513 bluestein_sequence(n, w);
cannam@167 514 for (i = 0; i < 2*nb; ++i) cpy(zero, y[i]);
cannam@167 515
cannam@167 516 for (i = 0; i < n; ++i) {
cannam@167 517 cpy(w[2*i], y[2*i]);
cannam@167 518 cpy(w[2*i+1], y[2*i+1]);
cannam@167 519 }
cannam@167 520 for (i = 1; i < n; ++i) {
cannam@167 521 cpy(w[2*i], y[2*(nb-i)]);
cannam@167 522 cpy(w[2*i+1], y[2*(nb-i)+1]);
cannam@167 523 }
cannam@167 524
cannam@167 525 fft0(nb, y, -1);
cannam@167 526 }
cannam@167 527
cannam@167 528 for (i = 0; i < 2*nb; ++i) cpy(zero, b[i]);
cannam@167 529
cannam@167 530 for (i = 0; i < n; ++i)
cannam@167 531 cmulj(w[2*i], w[2*i+1], a[2*i], a[2*i+1], b[2*i], b[2*i+1]);
cannam@167 532
cannam@167 533 /* scaled convolution b * y */
cannam@167 534 fft0(nb, b, -1);
cannam@167 535
cannam@167 536 for (i = 0; i < nb; ++i)
cannam@167 537 cmul(b[2*i], b[2*i+1], y[2*i], y[2*i+1], b[2*i], b[2*i+1]);
cannam@167 538 fft0(nb, b, 1);
cannam@167 539
cannam@167 540 for (i = 0; i < n; ++i) {
cannam@167 541 cmulj(w[2*i], w[2*i+1], b[2*i], b[2*i+1], a[2*i], a[2*i+1]);
cannam@167 542 mul(nbinv, a[2*i], a[2*i]);
cannam@167 543 mul(nbinv, a[2*i+1], a[2*i+1]);
cannam@167 544 }
cannam@167 545
cannam@167 546 bench_free(b);
cannam@167 547 }
cannam@167 548
cannam@167 549 static void swapri(int n, N *a)
cannam@167 550 {
cannam@167 551 int i;
cannam@167 552 for (i = 0; i < n; ++i) {
cannam@167 553 N t;
cannam@167 554 cpy(a[2 * i], t);
cannam@167 555 cpy(a[2 * i + 1], a[2 * i]);
cannam@167 556 cpy(t, a[2 * i + 1]);
cannam@167 557 }
cannam@167 558 }
cannam@167 559
cannam@167 560 static void fft1(int n, N *a, int sign)
cannam@167 561 {
cannam@167 562 if (power_of_two(n)) {
cannam@167 563 fft0(n, a, sign);
cannam@167 564 } else {
cannam@167 565 if (sign == 1) swapri(n, a);
cannam@167 566 bluestein(n, a);
cannam@167 567 if (sign == 1) swapri(n, a);
cannam@167 568 }
cannam@167 569 }
cannam@167 570
cannam@167 571 static void fromrealv(int n, bench_complex *a, N *b)
cannam@167 572 {
cannam@167 573 int i;
cannam@167 574
cannam@167 575 for (i = 0; i < n; ++i) {
cannam@167 576 fromreal(c_re(a[i]), b[2 * i]);
cannam@167 577 fromreal(c_im(a[i]), b[2 * i + 1]);
cannam@167 578 }
cannam@167 579 }
cannam@167 580
cannam@167 581 static void compare(int n, N *a, N *b, double *err)
cannam@167 582 {
cannam@167 583 int i;
cannam@167 584 double e1, e2, einf;
cannam@167 585 double n1, n2, ninf;
cannam@167 586
cannam@167 587 e1 = e2 = einf = 0.0;
cannam@167 588 n1 = n2 = ninf = 0.0;
cannam@167 589
cannam@167 590 # define DO(x1, x2, xinf, var) { \
cannam@167 591 double d = var; \
cannam@167 592 if (d < 0) d = -d; \
cannam@167 593 x1 += d; x2 += d * d; if (d > xinf) xinf = d; \
cannam@167 594 }
cannam@167 595
cannam@167 596 for (i = 0; i < 2 * n; ++i) {
cannam@167 597 N dd;
cannam@167 598 sub(a[i], b[i], dd);
cannam@167 599 DO(n1, n2, ninf, toreal(a[i]));
cannam@167 600 DO(e1, e2, einf, toreal(dd));
cannam@167 601 }
cannam@167 602
cannam@167 603 # undef DO
cannam@167 604 err[0] = e1 / n1;
cannam@167 605 err[1] = sqrt(e2 / n2);
cannam@167 606 err[2] = einf / ninf;
cannam@167 607 }
cannam@167 608
cannam@167 609 void fftaccuracy(int n, bench_complex *a, bench_complex *ffta,
cannam@167 610 int sign, double err[6])
cannam@167 611 {
cannam@167 612 N *b = (N *)bench_malloc(2 * n * sizeof(N));
cannam@167 613 N *fftb = (N *)bench_malloc(2 * n * sizeof(N));
cannam@167 614 N mn, ninv;
cannam@167 615 int i;
cannam@167 616
cannam@167 617 fromreal(n, mn); inv(mn, ninv);
cannam@167 618
cannam@167 619 /* forward error */
cannam@167 620 fromrealv(n, a, b); fromrealv(n, ffta, fftb);
cannam@167 621 fft1(n, b, sign);
cannam@167 622 compare(n, b, fftb, err);
cannam@167 623
cannam@167 624 /* backward error */
cannam@167 625 fromrealv(n, a, b); fromrealv(n, ffta, fftb);
cannam@167 626 for (i = 0; i < 2 * n; ++i) mul(fftb[i], ninv, fftb[i]);
cannam@167 627 fft1(n, fftb, -sign);
cannam@167 628 compare(n, b, fftb, err + 3);
cannam@167 629
cannam@167 630 bench_free(fftb);
cannam@167 631 bench_free(b);
cannam@167 632 }
cannam@167 633
cannam@167 634 void fftaccuracy_done(void)
cannam@167 635 {
cannam@167 636 if (cached_bluestein_w) bench_free(cached_bluestein_w);
cannam@167 637 if (cached_bluestein_y) bench_free(cached_bluestein_y);
cannam@167 638 cached_bluestein_w = 0;
cannam@167 639 cached_bluestein_y = 0;
cannam@167 640 cached_bluestein_n = -1;
cannam@167 641 }