annotate src/fftw-3.3.5/libbench2/verify-lib.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 2cd0e3b3e1fd
children
rev   line source
Chris@42 1 /*
Chris@42 2 * Copyright (c) 2003, 2007-14 Matteo Frigo
Chris@42 3 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
Chris@42 4 *
Chris@42 5 * This program is free software; you can redistribute it and/or modify
Chris@42 6 * it under the terms of the GNU General Public License as published by
Chris@42 7 * the Free Software Foundation; either version 2 of the License, or
Chris@42 8 * (at your option) any later version.
Chris@42 9 *
Chris@42 10 * This program is distributed in the hope that it will be useful,
Chris@42 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@42 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@42 13 * GNU General Public License for more details.
Chris@42 14 *
Chris@42 15 * You should have received a copy of the GNU General Public License
Chris@42 16 * along with this program; if not, write to the Free Software
Chris@42 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Chris@42 18 *
Chris@42 19 */
Chris@42 20
Chris@42 21
Chris@42 22 #include "verify.h"
Chris@42 23 #include <math.h>
Chris@42 24 #include <stdlib.h>
Chris@42 25 #include <stdio.h>
Chris@42 26
Chris@42 27 /*
Chris@42 28 * Utility functions:
Chris@42 29 */
Chris@42 30 static double dabs(double x) { return (x < 0.0) ? -x : x; }
Chris@42 31 static double dmin(double x, double y) { return (x < y) ? x : y; }
Chris@42 32 static double norm2(double x, double y) { return dmax(dabs(x), dabs(y)); }
Chris@42 33
Chris@42 34 double dmax(double x, double y) { return (x > y) ? x : y; }
Chris@42 35
Chris@42 36 static double aerror(C *a, C *b, int n)
Chris@42 37 {
Chris@42 38 if (n > 0) {
Chris@42 39 /* compute the relative Linf error */
Chris@42 40 double e = 0.0, mag = 0.0;
Chris@42 41 int i;
Chris@42 42
Chris@42 43 for (i = 0; i < n; ++i) {
Chris@42 44 e = dmax(e, norm2(c_re(a[i]) - c_re(b[i]),
Chris@42 45 c_im(a[i]) - c_im(b[i])));
Chris@42 46 mag = dmax(mag,
Chris@42 47 dmin(norm2(c_re(a[i]), c_im(a[i])),
Chris@42 48 norm2(c_re(b[i]), c_im(b[i]))));
Chris@42 49 }
Chris@42 50 e /= mag;
Chris@42 51
Chris@42 52 #ifdef HAVE_ISNAN
Chris@42 53 BENCH_ASSERT(!isnan(e));
Chris@42 54 #endif
Chris@42 55 return e;
Chris@42 56 } else
Chris@42 57 return 0.0;
Chris@42 58 }
Chris@42 59
Chris@42 60 #ifdef HAVE_DRAND48
Chris@42 61 # if defined(HAVE_DECL_DRAND48) && !HAVE_DECL_DRAND48
Chris@42 62 extern double drand48(void);
Chris@42 63 # endif
Chris@42 64 double mydrand(void)
Chris@42 65 {
Chris@42 66 return drand48() - 0.5;
Chris@42 67 }
Chris@42 68 #else
Chris@42 69 double mydrand(void)
Chris@42 70 {
Chris@42 71 double d = rand();
Chris@42 72 return (d / (double) RAND_MAX) - 0.5;
Chris@42 73 }
Chris@42 74 #endif
Chris@42 75
Chris@42 76 void arand(C *a, int n)
Chris@42 77 {
Chris@42 78 int i;
Chris@42 79
Chris@42 80 /* generate random inputs */
Chris@42 81 for (i = 0; i < n; ++i) {
Chris@42 82 c_re(a[i]) = mydrand();
Chris@42 83 c_im(a[i]) = mydrand();
Chris@42 84 }
Chris@42 85 }
Chris@42 86
Chris@42 87 /* make array real */
Chris@42 88 void mkreal(C *A, int n)
Chris@42 89 {
Chris@42 90 int i;
Chris@42 91
Chris@42 92 for (i = 0; i < n; ++i) {
Chris@42 93 c_im(A[i]) = 0.0;
Chris@42 94 }
Chris@42 95 }
Chris@42 96
Chris@42 97 static void assign_conj(C *Ac, C *A, int rank, const bench_iodim *dim, int stride)
Chris@42 98 {
Chris@42 99 if (rank == 0) {
Chris@42 100 c_re(*Ac) = c_re(*A);
Chris@42 101 c_im(*Ac) = -c_im(*A);
Chris@42 102 }
Chris@42 103 else {
Chris@42 104 int i, n0 = dim[rank - 1].n, s = stride;
Chris@42 105 rank -= 1;
Chris@42 106 stride *= n0;
Chris@42 107 assign_conj(Ac, A, rank, dim, stride);
Chris@42 108 for (i = 1; i < n0; ++i)
Chris@42 109 assign_conj(Ac + (n0 - i) * s, A + i * s, rank, dim, stride);
Chris@42 110 }
Chris@42 111 }
Chris@42 112
Chris@42 113 /* make array hermitian */
Chris@42 114 void mkhermitian(C *A, int rank, const bench_iodim *dim, int stride)
Chris@42 115 {
Chris@42 116 if (rank == 0)
Chris@42 117 c_im(*A) = 0.0;
Chris@42 118 else {
Chris@42 119 int i, n0 = dim[rank - 1].n, s = stride;
Chris@42 120 rank -= 1;
Chris@42 121 stride *= n0;
Chris@42 122 mkhermitian(A, rank, dim, stride);
Chris@42 123 for (i = 1; 2*i < n0; ++i)
Chris@42 124 assign_conj(A + (n0 - i) * s, A + i * s, rank, dim, stride);
Chris@42 125 if (2*i == n0)
Chris@42 126 mkhermitian(A + i * s, rank, dim, stride);
Chris@42 127 }
Chris@42 128 }
Chris@42 129
Chris@42 130 void mkhermitian1(C *a, int n)
Chris@42 131 {
Chris@42 132 bench_iodim d;
Chris@42 133
Chris@42 134 d.n = n;
Chris@42 135 d.is = d.os = 1;
Chris@42 136 mkhermitian(a, 1, &d, 1);
Chris@42 137 }
Chris@42 138
Chris@42 139 /* C = A */
Chris@42 140 void acopy(C *c, C *a, int n)
Chris@42 141 {
Chris@42 142 int i;
Chris@42 143
Chris@42 144 for (i = 0; i < n; ++i) {
Chris@42 145 c_re(c[i]) = c_re(a[i]);
Chris@42 146 c_im(c[i]) = c_im(a[i]);
Chris@42 147 }
Chris@42 148 }
Chris@42 149
Chris@42 150 /* C = A + B */
Chris@42 151 void aadd(C *c, C *a, C *b, int n)
Chris@42 152 {
Chris@42 153 int i;
Chris@42 154
Chris@42 155 for (i = 0; i < n; ++i) {
Chris@42 156 c_re(c[i]) = c_re(a[i]) + c_re(b[i]);
Chris@42 157 c_im(c[i]) = c_im(a[i]) + c_im(b[i]);
Chris@42 158 }
Chris@42 159 }
Chris@42 160
Chris@42 161 /* C = A - B */
Chris@42 162 void asub(C *c, C *a, C *b, int n)
Chris@42 163 {
Chris@42 164 int i;
Chris@42 165
Chris@42 166 for (i = 0; i < n; ++i) {
Chris@42 167 c_re(c[i]) = c_re(a[i]) - c_re(b[i]);
Chris@42 168 c_im(c[i]) = c_im(a[i]) - c_im(b[i]);
Chris@42 169 }
Chris@42 170 }
Chris@42 171
Chris@42 172 /* B = rotate left A (complex) */
Chris@42 173 void arol(C *b, C *a, int n, int nb, int na)
Chris@42 174 {
Chris@42 175 int i, ib, ia;
Chris@42 176
Chris@42 177 for (ib = 0; ib < nb; ++ib) {
Chris@42 178 for (i = 0; i < n - 1; ++i)
Chris@42 179 for (ia = 0; ia < na; ++ia) {
Chris@42 180 C *pb = b + (ib * n + i) * na + ia;
Chris@42 181 C *pa = a + (ib * n + i + 1) * na + ia;
Chris@42 182 c_re(*pb) = c_re(*pa);
Chris@42 183 c_im(*pb) = c_im(*pa);
Chris@42 184 }
Chris@42 185
Chris@42 186 for (ia = 0; ia < na; ++ia) {
Chris@42 187 C *pb = b + (ib * n + n - 1) * na + ia;
Chris@42 188 C *pa = a + ib * n * na + ia;
Chris@42 189 c_re(*pb) = c_re(*pa);
Chris@42 190 c_im(*pb) = c_im(*pa);
Chris@42 191 }
Chris@42 192 }
Chris@42 193 }
Chris@42 194
Chris@42 195 void aphase_shift(C *b, C *a, int n, int nb, int na, double sign)
Chris@42 196 {
Chris@42 197 int j, jb, ja;
Chris@42 198 trigreal twopin;
Chris@42 199 twopin = K2PI / n;
Chris@42 200
Chris@42 201 for (jb = 0; jb < nb; ++jb)
Chris@42 202 for (j = 0; j < n; ++j) {
Chris@42 203 trigreal s = sign * SIN(j * twopin);
Chris@42 204 trigreal c = COS(j * twopin);
Chris@42 205
Chris@42 206 for (ja = 0; ja < na; ++ja) {
Chris@42 207 int k = (jb * n + j) * na + ja;
Chris@42 208 c_re(b[k]) = c_re(a[k]) * c - c_im(a[k]) * s;
Chris@42 209 c_im(b[k]) = c_re(a[k]) * s + c_im(a[k]) * c;
Chris@42 210 }
Chris@42 211 }
Chris@42 212 }
Chris@42 213
Chris@42 214 /* A = alpha * A (complex, in place) */
Chris@42 215 void ascale(C *a, C alpha, int n)
Chris@42 216 {
Chris@42 217 int i;
Chris@42 218
Chris@42 219 for (i = 0; i < n; ++i) {
Chris@42 220 R xr = c_re(a[i]), xi = c_im(a[i]);
Chris@42 221 c_re(a[i]) = xr * c_re(alpha) - xi * c_im(alpha);
Chris@42 222 c_im(a[i]) = xr * c_im(alpha) + xi * c_re(alpha);
Chris@42 223 }
Chris@42 224 }
Chris@42 225
Chris@42 226
Chris@42 227 double acmp(C *a, C *b, int n, const char *test, double tol)
Chris@42 228 {
Chris@42 229 double d = aerror(a, b, n);
Chris@42 230 if (d > tol) {
Chris@42 231 ovtpvt_err("Found relative error %e (%s)\n", d, test);
Chris@42 232
Chris@42 233 {
Chris@42 234 int i, N;
Chris@42 235 N = n > 300 && verbose <= 2 ? 300 : n;
Chris@42 236 for (i = 0; i < N; ++i)
Chris@42 237 ovtpvt_err("%8d %16.12f %16.12f %16.12f %16.12f\n", i,
Chris@42 238 (double) c_re(a[i]), (double) c_im(a[i]),
Chris@42 239 (double) c_re(b[i]), (double) c_im(b[i]));
Chris@42 240 }
Chris@42 241
Chris@42 242 bench_exit(EXIT_FAILURE);
Chris@42 243 }
Chris@42 244 return d;
Chris@42 245 }
Chris@42 246
Chris@42 247
Chris@42 248 /*
Chris@42 249 * Implementation of the FFT tester described in
Chris@42 250 *
Chris@42 251 * Funda Ergün. Testing multivariate linear functions: Overcoming the
Chris@42 252 * generator bottleneck. In Proceedings of the Twenty-Seventh Annual
Chris@42 253 * ACM Symposium on the Theory of Computing, pages 407-416, Las Vegas,
Chris@42 254 * Nevada, 29 May--1 June 1995.
Chris@42 255 *
Chris@42 256 * Also: F. Ergun, S. R. Kumar, and D. Sivakumar, "Self-testing without
Chris@42 257 * the generator bottleneck," SIAM J. on Computing 29 (5), 1630-51 (2000).
Chris@42 258 */
Chris@42 259
Chris@42 260 static double impulse0(dofft_closure *k,
Chris@42 261 int n, int vecn,
Chris@42 262 C *inA, C *inB, C *inC,
Chris@42 263 C *outA, C *outB, C *outC,
Chris@42 264 C *tmp, int rounds, double tol)
Chris@42 265 {
Chris@42 266 int N = n * vecn;
Chris@42 267 double e = 0.0;
Chris@42 268 int j;
Chris@42 269
Chris@42 270 k->apply(k, inA, tmp);
Chris@42 271 e = dmax(e, acmp(tmp, outA, N, "impulse 1", tol));
Chris@42 272
Chris@42 273 for (j = 0; j < rounds; ++j) {
Chris@42 274 arand(inB, N);
Chris@42 275 asub(inC, inA, inB, N);
Chris@42 276 k->apply(k, inB, outB);
Chris@42 277 k->apply(k, inC, outC);
Chris@42 278 aadd(tmp, outB, outC, N);
Chris@42 279 e = dmax(e, acmp(tmp, outA, N, "impulse", tol));
Chris@42 280 }
Chris@42 281 return e;
Chris@42 282 }
Chris@42 283
Chris@42 284 double impulse(dofft_closure *k,
Chris@42 285 int n, int vecn,
Chris@42 286 C *inA, C *inB, C *inC,
Chris@42 287 C *outA, C *outB, C *outC,
Chris@42 288 C *tmp, int rounds, double tol)
Chris@42 289 {
Chris@42 290 int i, j;
Chris@42 291 double e = 0.0;
Chris@42 292
Chris@42 293 /* check impulsive input */
Chris@42 294 for (i = 0; i < vecn; ++i) {
Chris@42 295 R x = (sqrt(n)*(i+1)) / (double)(vecn+1);
Chris@42 296 for (j = 0; j < n; ++j) {
Chris@42 297 c_re(inA[j + i * n]) = 0;
Chris@42 298 c_im(inA[j + i * n]) = 0;
Chris@42 299 c_re(outA[j + i * n]) = x;
Chris@42 300 c_im(outA[j + i * n]) = 0;
Chris@42 301 }
Chris@42 302 c_re(inA[i * n]) = x;
Chris@42 303 c_im(inA[i * n]) = 0;
Chris@42 304 }
Chris@42 305
Chris@42 306 e = dmax(e, impulse0(k, n, vecn, inA, inB, inC, outA, outB, outC,
Chris@42 307 tmp, rounds, tol));
Chris@42 308
Chris@42 309 /* check constant input */
Chris@42 310 for (i = 0; i < vecn; ++i) {
Chris@42 311 R x = (i+1) / ((double)(vecn+1) * sqrt(n));
Chris@42 312 for (j = 0; j < n; ++j) {
Chris@42 313 c_re(inA[j + i * n]) = x;
Chris@42 314 c_im(inA[j + i * n]) = 0;
Chris@42 315 c_re(outA[j + i * n]) = 0;
Chris@42 316 c_im(outA[j + i * n]) = 0;
Chris@42 317 }
Chris@42 318 c_re(outA[i * n]) = n * x;
Chris@42 319 c_im(outA[i * n]) = 0;
Chris@42 320 }
Chris@42 321
Chris@42 322 e = dmax(e, impulse0(k, n, vecn, inA, inB, inC, outA, outB, outC,
Chris@42 323 tmp, rounds, tol));
Chris@42 324 return e;
Chris@42 325 }
Chris@42 326
Chris@42 327 double linear(dofft_closure *k, int realp,
Chris@42 328 int n, C *inA, C *inB, C *inC, C *outA,
Chris@42 329 C *outB, C *outC, C *tmp, int rounds, double tol)
Chris@42 330 {
Chris@42 331 int j;
Chris@42 332 double e = 0.0;
Chris@42 333
Chris@42 334 for (j = 0; j < rounds; ++j) {
Chris@42 335 C alpha, beta;
Chris@42 336 c_re(alpha) = mydrand();
Chris@42 337 c_im(alpha) = realp ? 0.0 : mydrand();
Chris@42 338 c_re(beta) = mydrand();
Chris@42 339 c_im(beta) = realp ? 0.0 : mydrand();
Chris@42 340 arand(inA, n);
Chris@42 341 arand(inB, n);
Chris@42 342 k->apply(k, inA, outA);
Chris@42 343 k->apply(k, inB, outB);
Chris@42 344
Chris@42 345 ascale(outA, alpha, n);
Chris@42 346 ascale(outB, beta, n);
Chris@42 347 aadd(tmp, outA, outB, n);
Chris@42 348 ascale(inA, alpha, n);
Chris@42 349 ascale(inB, beta, n);
Chris@42 350 aadd(inC, inA, inB, n);
Chris@42 351 k->apply(k, inC, outC);
Chris@42 352
Chris@42 353 e = dmax(e, acmp(outC, tmp, n, "linear", tol));
Chris@42 354 }
Chris@42 355 return e;
Chris@42 356 }
Chris@42 357
Chris@42 358
Chris@42 359
Chris@42 360 double tf_shift(dofft_closure *k,
Chris@42 361 int realp, const bench_tensor *sz,
Chris@42 362 int n, int vecn, double sign,
Chris@42 363 C *inA, C *inB, C *outA, C *outB, C *tmp,
Chris@42 364 int rounds, double tol, int which_shift)
Chris@42 365 {
Chris@42 366 int nb, na, dim, N = n * vecn;
Chris@42 367 int i, j;
Chris@42 368 double e = 0.0;
Chris@42 369
Chris@42 370 /* test 3: check the time-shift property */
Chris@42 371 /* the paper performs more tests, but this code should be fine too */
Chris@42 372
Chris@42 373 nb = 1;
Chris@42 374 na = n;
Chris@42 375
Chris@42 376 /* check shifts across all SZ dimensions */
Chris@42 377 for (dim = 0; dim < sz->rnk; ++dim) {
Chris@42 378 int ncur = sz->dims[dim].n;
Chris@42 379
Chris@42 380 na /= ncur;
Chris@42 381
Chris@42 382 for (j = 0; j < rounds; ++j) {
Chris@42 383 arand(inA, N);
Chris@42 384
Chris@42 385 if (which_shift == TIME_SHIFT) {
Chris@42 386 for (i = 0; i < vecn; ++i) {
Chris@42 387 if (realp) mkreal(inA + i * n, n);
Chris@42 388 arol(inB + i * n, inA + i * n, ncur, nb, na);
Chris@42 389 }
Chris@42 390 k->apply(k, inA, outA);
Chris@42 391 k->apply(k, inB, outB);
Chris@42 392 for (i = 0; i < vecn; ++i)
Chris@42 393 aphase_shift(tmp + i * n, outB + i * n, ncur,
Chris@42 394 nb, na, sign);
Chris@42 395 e = dmax(e, acmp(tmp, outA, N, "time shift", tol));
Chris@42 396 } else {
Chris@42 397 for (i = 0; i < vecn; ++i) {
Chris@42 398 if (realp)
Chris@42 399 mkhermitian(inA + i * n, sz->rnk, sz->dims, 1);
Chris@42 400 aphase_shift(inB + i * n, inA + i * n, ncur,
Chris@42 401 nb, na, -sign);
Chris@42 402 }
Chris@42 403 k->apply(k, inA, outA);
Chris@42 404 k->apply(k, inB, outB);
Chris@42 405 for (i = 0; i < vecn; ++i)
Chris@42 406 arol(tmp + i * n, outB + i * n, ncur, nb, na);
Chris@42 407 e = dmax(e, acmp(tmp, outA, N, "freq shift", tol));
Chris@42 408 }
Chris@42 409 }
Chris@42 410
Chris@42 411 nb *= ncur;
Chris@42 412 }
Chris@42 413 return e;
Chris@42 414 }
Chris@42 415
Chris@42 416
Chris@42 417 void preserves_input(dofft_closure *k, aconstrain constrain,
Chris@42 418 int n, C *inA, C *inB, C *outB, int rounds)
Chris@42 419 {
Chris@42 420 int j;
Chris@42 421 int recopy_input = k->recopy_input;
Chris@42 422
Chris@42 423 k->recopy_input = 1;
Chris@42 424 for (j = 0; j < rounds; ++j) {
Chris@42 425 arand(inA, n);
Chris@42 426 if (constrain)
Chris@42 427 constrain(inA, n);
Chris@42 428
Chris@42 429 acopy(inB, inA, n);
Chris@42 430 k->apply(k, inB, outB);
Chris@42 431 acmp(inB, inA, n, "preserves_input", 0.0);
Chris@42 432 }
Chris@42 433 k->recopy_input = recopy_input;
Chris@42 434 }
Chris@42 435
Chris@42 436
Chris@42 437 /* Make a copy of the size tensor, with the same dimensions, but with
Chris@42 438 the strides corresponding to a "packed" row-major array with the
Chris@42 439 given stride. */
Chris@42 440 bench_tensor *verify_pack(const bench_tensor *sz, int s)
Chris@42 441 {
Chris@42 442 bench_tensor *x = tensor_copy(sz);
Chris@42 443 if (BENCH_FINITE_RNK(x->rnk) && x->rnk > 0) {
Chris@42 444 int i;
Chris@42 445 x->dims[x->rnk - 1].is = s;
Chris@42 446 x->dims[x->rnk - 1].os = s;
Chris@42 447 for (i = x->rnk - 1; i > 0; --i) {
Chris@42 448 x->dims[i - 1].is = x->dims[i].is * x->dims[i].n;
Chris@42 449 x->dims[i - 1].os = x->dims[i].os * x->dims[i].n;
Chris@42 450 }
Chris@42 451 }
Chris@42 452 return x;
Chris@42 453 }
Chris@42 454
Chris@42 455 static int all_zero(C *a, int n)
Chris@42 456 {
Chris@42 457 int i;
Chris@42 458 for (i = 0; i < n; ++i)
Chris@42 459 if (c_re(a[i]) != 0.0 || c_im(a[i]) != 0.0)
Chris@42 460 return 0;
Chris@42 461 return 1;
Chris@42 462 }
Chris@42 463
Chris@42 464 static int one_accuracy_test(dofft_closure *k, aconstrain constrain,
Chris@42 465 int sign, int n, C *a, C *b,
Chris@42 466 double t[6])
Chris@42 467 {
Chris@42 468 double err[6];
Chris@42 469
Chris@42 470 if (constrain)
Chris@42 471 constrain(a, n);
Chris@42 472
Chris@42 473 if (all_zero(a, n))
Chris@42 474 return 0;
Chris@42 475
Chris@42 476 k->apply(k, a, b);
Chris@42 477 fftaccuracy(n, a, b, sign, err);
Chris@42 478
Chris@42 479 t[0] += err[0];
Chris@42 480 t[1] += err[1] * err[1];
Chris@42 481 t[2] = dmax(t[2], err[2]);
Chris@42 482 t[3] += err[3];
Chris@42 483 t[4] += err[4] * err[4];
Chris@42 484 t[5] = dmax(t[5], err[5]);
Chris@42 485
Chris@42 486 return 1;
Chris@42 487 }
Chris@42 488
Chris@42 489 void accuracy_test(dofft_closure *k, aconstrain constrain,
Chris@42 490 int sign, int n, C *a, C *b, int rounds, int impulse_rounds,
Chris@42 491 double t[6])
Chris@42 492 {
Chris@42 493 int r, i;
Chris@42 494 int ntests = 0;
Chris@42 495 bench_complex czero = {0, 0};
Chris@42 496
Chris@42 497 for (i = 0; i < 6; ++i) t[i] = 0.0;
Chris@42 498
Chris@42 499 for (r = 0; r < rounds; ++r) {
Chris@42 500 arand(a, n);
Chris@42 501 if (one_accuracy_test(k, constrain, sign, n, a, b, t))
Chris@42 502 ++ntests;
Chris@42 503 }
Chris@42 504
Chris@42 505 /* impulses at beginning of array */
Chris@42 506 for (r = 0; r < impulse_rounds; ++r) {
Chris@42 507 if (r > n - r - 1)
Chris@42 508 continue;
Chris@42 509
Chris@42 510 caset(a, n, czero);
Chris@42 511 c_re(a[r]) = c_im(a[r]) = 1.0;
Chris@42 512
Chris@42 513 if (one_accuracy_test(k, constrain, sign, n, a, b, t))
Chris@42 514 ++ntests;
Chris@42 515 }
Chris@42 516
Chris@42 517 /* impulses at end of array */
Chris@42 518 for (r = 0; r < impulse_rounds; ++r) {
Chris@42 519 if (r <= n - r - 1)
Chris@42 520 continue;
Chris@42 521
Chris@42 522 caset(a, n, czero);
Chris@42 523 c_re(a[n - r - 1]) = c_im(a[n - r - 1]) = 1.0;
Chris@42 524
Chris@42 525 if (one_accuracy_test(k, constrain, sign, n, a, b, t))
Chris@42 526 ++ntests;
Chris@42 527 }
Chris@42 528
Chris@42 529 /* randomly-located impulses */
Chris@42 530 for (r = 0; r < impulse_rounds; ++r) {
Chris@42 531 caset(a, n, czero);
Chris@42 532 i = rand() % n;
Chris@42 533 c_re(a[i]) = c_im(a[i]) = 1.0;
Chris@42 534
Chris@42 535 if (one_accuracy_test(k, constrain, sign, n, a, b, t))
Chris@42 536 ++ntests;
Chris@42 537 }
Chris@42 538
Chris@42 539 t[0] /= ntests;
Chris@42 540 t[1] = sqrt(t[1] / ntests);
Chris@42 541 t[3] /= ntests;
Chris@42 542 t[4] = sqrt(t[4] / ntests);
Chris@42 543
Chris@42 544 fftaccuracy_done();
Chris@42 545 }