annotate src/fftw-3.3.5/libbench2/verify-lib.c @ 148:b4bfdf10c4b3

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