changed reading hint
[gromacs/adressmacs.git] / src / fftw / test_main.c
blob05e36ddfcc382475277ba52324f4f6fd6d5e14cc
1 /*
2 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * test_main.c: driver for test programs (linked with fftw_test.c/rfftw_test.c)
24 /* $Id$ */
25 #include <fftw-int.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <math.h>
30 #include <time.h>
31 #include <ctype.h>
33 #include "test_main.h"
35 #ifdef HAVE_GETOPT
36 # ifdef HAVE_GETOPT_H
37 # include <getopt.h>
38 # elif defined(HAVE_UNISTD_H)
39 # include <unistd.h>
40 # endif
41 #endif
42 #include <unistd.h>
43 #define HAVE_GETOPT
44 double mydrand(void)
46 double d = rand();
47 return (d / (double) RAND_MAX) - .5;
50 /* return random 0 or non-zero */
51 int coinflip(void)
53 return (rand() & 8192); /* higher-order bits are often more random
58 /* parse a string of the form N1xN2x... and return a size structure */
59 struct size parse_size(char *s)
61 struct size sz;
62 int n;
64 sz.rank = 0;
65 sz.is_nd = 0;
67 if (*s == 'x' || *s == 'X' || *s == '*') {
68 ++s;
69 /* force ND transform of rank 1 */
70 sz.is_nd = 1;
72 accept_digit:
73 n = 0;
75 CHECK(isdigit(*s),
76 "invalid digit");
78 while (isdigit(*s)) {
79 n = n * 10 + (*s - '0');
80 ++s;
83 sz.narray[sz.rank] = n;
84 ++sz.rank;
86 CHECK(sz.rank < MAX_CMDLINE_RANK,
87 "maximum rank exceeded");
89 if (*s == 'x' || *s == 'X' || *s == '*') {
90 ++s;
91 goto accept_digit;
93 /* force ND transform if rank > 1 */
94 if (sz.rank > 1)
95 sz.is_nd = 1;
96 return sz;
99 /*******************
100 * global variables
101 *******************/
102 int verbose;
103 int wisdom_flag, measure_flag;
104 int speed_flag = FFTW_MEASURE;
105 int chk_mem_leak;
106 int paranoid;
107 int howmany_fields = 1;
108 int max_iterations = 0; /*
109 * maximum number of iterations to perform
110 * in "infinite" tests--default (0) means
111 * no limit
114 /* When testing MPI stuff, only one process gets to do I/O: */
115 int io_okay = 1;
116 #define my_printf if (io_okay) printf
117 #define my_fprintf if (io_okay) fprintf
118 #define my_fflush if (io_okay) fflush
120 /*******************
121 * procedures
122 *******************/
124 /* smart time printer */
125 char *smart_sprint_time(double x)
127 static char buf[128];
129 if (x < 1.0E-6)
130 sprintf(buf, "%f ns", x * 1.0E9);
131 else if (x < 1.0E-3)
132 sprintf(buf, "%f us", x * 1.0E6);
133 else if (x < 1.0)
134 sprintf(buf, "%f ms", x * 1.0E3);
135 else
136 sprintf(buf, "%f s", x);
138 return buf;
141 /* greet the user */
142 /* jokes stolen from http://whereis.mit.edu/bin/map */
143 void please_wait(void)
145 int i;
146 const char *s[] =
148 "(while a large software vendor in Seattle takes over the world)",
149 "(and remember, this is faster than Java)",
150 "(and dream of faster computers)",
151 "(checking the gravitational constant in your locale)",
152 "(at least you are not on hold)",
153 "(while X11 grows by another kilobyte)",
154 "(while Windows NT reboots)",
155 "(correcting for the phase of the moon)",
156 "(your call is important to us)",
157 "(while the Linux user-base doubles)",
158 "(while you decide where you want to go tomorrow)",
159 "(exorcising evil spirits)",
161 int choices = sizeof(s) / sizeof(*s);
163 i = rand() % choices;
164 my_printf("Please wait %s.\n", s[i < 0 ? -i : i]);
167 void please_wait_forever(void)
169 int i;
170 const char *s[] =
172 "(but it won't crash, either)",
173 "(at least in theory)",
174 "(please be patient)",
175 "(our next release will complete it more quickly)",
176 #if defined(__WIN32__) || defined(WIN32) || defined(_WINDOWS)
177 "(by the way, Linux executes infinite loops faster)",
178 #endif
180 int choices = sizeof(s) / sizeof(*s);
182 if (!max_iterations) {
183 i = rand() % choices;
184 my_printf("This test does not terminate %s.\n", s[i < 0 ? -i : i]);
185 } else {
186 my_printf("This test will run for %d iterations.\n", max_iterations);
187 please_wait();
191 /*************************************************
192 * Speed tests
193 *************************************************/
195 double mflops(double t, int N)
197 return (5.0 * N * log((double) N) / (log(2.0) * t * 1.0e6));
200 void print_dims(struct size sz)
202 int i;
204 my_printf("%d", sz.narray[0]);
205 for (i = 1; i < sz.rank; ++i)
206 my_printf("x%d", sz.narray[i]);
209 void test_speed(int n)
211 int specific;
213 please_wait();
215 if (howmany_fields > 1)
216 WHEN_VERBOSE(1, my_printf("TIMING MULTIPLE-FIELD FFT: "
217 "howmany=%d, stride=%d, dist=%d\n\n",
218 howmany_fields, howmany_fields, 1));
220 for (specific = 0; specific <= 1; ++specific) {
221 WHEN_VERBOSE(1,
222 my_printf("SPEED TEST: n = %d, FFTW_FORWARD, out of place, %s\n",
223 n, SPECIFICP(specific)));
224 test_speed_aux(n, FFTW_FORWARD, 0, specific);
226 WHEN_VERBOSE(1,
227 my_printf("SPEED TEST: n = %d, FFTW_FORWARD, in place, %s\n",
228 n, SPECIFICP(specific)));
229 test_speed_aux(n, FFTW_FORWARD, FFTW_IN_PLACE, specific);
231 WHEN_VERBOSE(1,
232 my_printf("SPEED TEST: n = %d, FFTW_BACKWARD, out of place, %s\n",
233 n, SPECIFICP(specific)));
234 test_speed_aux(n, FFTW_BACKWARD, 0, specific);
236 WHEN_VERBOSE(1,
237 my_printf("SPEED TEST: n = %d, FFTW_BACKWARD, in place, %s\n",
238 n, SPECIFICP(specific)));
239 test_speed_aux(n, FFTW_BACKWARD, FFTW_IN_PLACE, specific);
243 void test_speed_nd(struct size sz)
245 int specific;
247 please_wait();
249 if (howmany_fields > 1)
250 WHEN_VERBOSE(1, my_printf("TIMING MULTIPLE-FIELD FFT: "
251 "howmany=%d, stride=%d, dist=%d\n\n",
252 howmany_fields, howmany_fields, 1));
254 for (specific = 0; specific <= 1; ++specific) {
255 my_printf("SPEED TEST: ");
256 WHEN_VERBOSE(1, print_dims(sz));
257 WHEN_VERBOSE(1, my_printf(", FFTW_FORWARD, in place, %s\n",
258 SPECIFICP(specific)));
259 test_speed_nd_aux(sz, FFTW_FORWARD,
260 FFTW_IN_PLACE, specific);
262 WHEN_VERBOSE(1, my_printf("SPEED TEST: "));
263 print_dims(sz);
264 WHEN_VERBOSE(1, my_printf(", FFTW_BACKWARD, in place, %s\n",
265 SPECIFICP(specific)));
266 test_speed_nd_aux(sz, FFTW_BACKWARD, FFTW_IN_PLACE, specific);
270 /*************************************************
271 * correctness tests
272 *************************************************/
274 double compute_error_complex(fftw_complex * A, int astride,
275 fftw_complex * B, int bstride, int n)
277 /* compute the relative error */
278 double error = 0.0;
279 int i;
281 for (i = 0; i < n; ++i) {
282 double a;
283 double mag;
284 a = sqrt(SQR(c_re(A[i * astride]) - c_re(B[i * bstride])) +
285 SQR(c_im(A[i * astride]) - c_im(B[i * bstride])));
286 mag = 0.5 * (sqrt(SQR(c_re(A[i * astride]))
287 + SQR(c_im(A[i * astride]))) +
288 sqrt(SQR(c_re(B[i * bstride]))
289 + SQR(c_im(B[i * bstride])))) + TOLERANCE;
291 a /= mag;
292 if (a > error)
293 error = a;
295 #ifdef HAVE_ISNAN
296 CHECK(!isnan(a), "NaN in answer");
297 #endif
299 return error;
302 /* test forever */
303 void test_all(void)
305 int n;
307 please_wait_forever();
308 for (n = 1; !max_iterations || n <= max_iterations; ++n) {
309 test_correctness(n);
310 if (!(wisdom_flag & FFTW_USE_WISDOM) && chk_mem_leak)
311 fftw_check_memory_leaks();
315 #define MAX_FACTOR 13
317 int rand_small_factors(int N)
319 int f, n = 1;
321 f = rand() % MAX_FACTOR + 1;
323 while (n * f <= N) {
324 n *= f;
325 f = rand() % MAX_FACTOR + 1;
328 return n;
331 #define MAX_N 16384
333 struct size random_dims(int rank)
335 int maxsize, dim;
336 double maxsize_d;
337 struct size sz;
339 /* workaround to weird gcc warning */
340 maxsize_d = pow((double) (rank == 1 ? MAX_N / 4 : MAX_N),
341 1.0 / (double) rank);
342 maxsize = (int) maxsize_d;
344 if (maxsize < 1)
345 maxsize = 1;
347 sz.rank = rank;
348 for (dim = 0; dim < rank; ++dim)
349 sz.narray[dim] = rand_small_factors(maxsize);
351 return sz;
354 void test_random(void)
356 static int counter = 0;
357 struct size sz;
359 if ((++counter) % 16 == 0) {
360 sz.rank = 1;
361 sz.narray[0] = rand() % (MAX_N / 16) + 1;
362 } else {
363 sz = random_dims(1);
366 test_correctness(sz.narray[0]);
369 /*************************************************
370 * multi-dimensional correctness tests
371 *************************************************/
373 void testnd_correctness_both(struct size sz,
374 int alt_api, int specific, int force_buf)
376 WHEN_VERBOSE(1,
377 my_printf("Testing nd correctness for size = ");
378 print_dims(sz);
379 my_printf("...");
380 my_fflush(stdout));
382 if (alt_api)
383 WHEN_VERBOSE(1, my_printf("alt. api..."));
384 if (specific)
385 WHEN_VERBOSE(1, my_printf("specific..."));
386 if (force_buf)
387 WHEN_VERBOSE(1, my_printf("force buf..."));
389 testnd_correctness(sz, FFTW_FORWARD, alt_api, specific, force_buf);
390 testnd_correctness(sz, FFTW_BACKWARD, alt_api, specific, force_buf);
392 WHEN_VERBOSE(1, my_printf("OK\n"));
395 void testnd_correctness_aux(struct size sz)
397 int alt_api, specific, force_buf;
399 for (alt_api = 0; alt_api <= 1; ++alt_api)
400 for (specific = 0; specific <= 1; ++specific)
401 for (force_buf = 0; force_buf <= 1; ++force_buf)
402 testnd_correctness_both(sz, alt_api, specific,
403 force_buf);
406 void testnd_correctness_square(int rank, int size)
408 struct size sz;
409 int alt_api, specific, force_buf;
410 int i;
412 sz.rank = rank;
413 for (i = 0; i < rank; ++i)
414 sz.narray[i] = size;
416 for (alt_api = 0; alt_api <= 1; ++alt_api)
417 for (specific = 0; specific <= 1; ++specific)
418 for (force_buf = 0; force_buf <= 1; ++force_buf)
419 testnd_correctness_both(sz, alt_api,
420 specific, force_buf);
424 void testnd_random(int rank)
426 struct size sz;
428 sz = random_dims(rank);
429 testnd_correctness_both(sz, coinflip(), coinflip(), coinflip());
432 /* loop forever */
433 void test_all_random(int rank)
435 int counter;
436 please_wait_forever();
438 for (counter = 0; !max_iterations || counter < max_iterations; ++counter) {
439 if (rank > 0)
440 testnd_random(rank);
441 else if ((counter) % 2 == 0)
442 test_random();
443 else
444 testnd_random(rand() % MAX_RANK + 1);
449 int pow2sqrt(int n)
450 /* return greatest power of two <= sqrt(n) */
452 int s = 1;
454 while (s * s * 4 <= n)
455 s *= 2;
456 return s;
459 /* test forever */
460 void testnd_all(int rank)
462 int n;
464 please_wait_forever();
466 for (n = 1; !max_iterations || n <= max_iterations; ++n)
467 testnd_correctness_square(rank, n);
470 fftw_direction random_dir(void)
472 if (coinflip())
473 return FFTW_FORWARD;
474 else
475 return FFTW_BACKWARD;
478 /*************************************************
479 * timer tests
480 *************************************************/
482 static int hack_sum_i;
484 void negative_time(void)
486 my_fprintf(stderr,
487 "* PROBLEM: I measured a negative time interval.\n"
488 "* Please make sure you defined the timer correctly\n"
489 "* or contact fftw@theory.lcs.mit.edu for help.\n");
493 * paranoid test to see if time is monotonic. If not, you are
494 * really in trouble
496 void test_timer_paranoid(void)
498 fftw_time start_t, end_t;
499 double sec;
500 int i;
502 start_t = fftw_get_time();
504 /* waste some time */
505 for (i = 0; i < 10000; ++i)
506 hack_sum_i = i;
508 end_t = fftw_get_time();
509 sec = fftw_time_to_sec(fftw_time_diff(end_t, start_t));
510 if (sec < 0.0)
511 negative_time();
514 /* compute useful numbers */
515 static int fib(int n)
517 if (n < 2)
518 return n;
519 else {
520 int x, y;
521 x = fib(n - 1);
522 y = fib(n - 2);
523 return x + y;
527 static int hack_fib;
529 void test_timer(void)
531 double times[32], acc, min_time = 10000.00;
532 unsigned long iters, iter;
533 fftw_time begin, end, start;
534 double t, tmax, tmin;
535 int last = 0, i, repeat;
537 please_wait();
538 test_timer_paranoid();
540 start = fftw_get_time();
542 for (i = 0; i < 32; i++) {
543 iters = 1 << i;
544 tmin = 1.0E10;
545 tmax = -1.0E10;
547 for (repeat = 0; repeat < FFTW_TIME_REPEAT; ++repeat) {
548 begin = fftw_get_time();
549 for (iter = 0; iter < iters; ++iter) {
550 hack_fib = fib(10);
552 end = fftw_get_time();
554 t = fftw_time_to_sec(fftw_time_diff(end, begin));
555 if (t < tmin)
556 tmin = t;
557 if (t > tmax)
558 tmax = t;
560 /* do not run for too long */
561 t = fftw_time_to_sec(fftw_time_diff(end, start));
562 if (t > FFTW_TIME_LIMIT)
563 break;
566 if (tmin < 0.0)
567 negative_time();
569 times[i] = tmin;
571 WHEN_VERBOSE(2,
572 my_printf("Number of iterations = 2^%d = %lu, time = %g, "
573 "time/iter = %g\n",
574 i, iters, times[i],
575 times[i] / iters));
576 WHEN_VERBOSE(2,
577 my_printf(" (out of %d tries, tmin = %g, tmax = %g)\n",
578 FFTW_TIME_REPEAT, tmin, tmax));
580 last = i;
581 if (times[i] > 10.0)
582 break;
586 * at this point, `last' is the last valid element in the
587 * `times' array.
590 for (i = 0; i <= last; ++i)
591 if (times[i] > 0.0 && times[i] < min_time)
592 min_time = times[i];
594 WHEN_VERBOSE(1, my_printf("\nMinimum resolvable time interval = %g seconds.\n\n",
595 min_time));
597 for (acc = 0.1; acc > 0.0005; acc *= 0.1) {
598 double t_final;
599 t_final = times[last] / (1 << last);
601 for (i = last; i >= 0; --i) {
602 double t_cur, error;
603 iters = 1 << i;
604 t_cur = times[i] / iters;
605 error = (t_cur - t_final) / t_final;
606 if (error < 0.0)
607 error = -error;
608 if (error > acc)
609 break;
612 ++i;
614 WHEN_VERBOSE(1,
615 my_printf("Minimum time for %g%% consistency = %g seconds.\n",
616 acc * 100.0, times[i]));
618 WHEN_VERBOSE(1,
619 my_printf("\nMinimum time used in FFTW timing (FFTW_TIME_MIN)"
620 " = %g seconds.\n", FFTW_TIME_MIN));
623 /*************************************************
624 * help
625 *************************************************/
627 #ifdef HAVE_GETOPT_LONG
628 # define WHEN_LONG_OPTIONS(x) x
629 #else
630 # define WHEN_LONG_OPTIONS(x) ""
631 #endif
633 static void usage(int exit_when_done)
635 my_printf("Usage: %s_test [options]\n", fftw_prefix);
636 my_printf(WHEN_LONG_OPTIONS(" --speed=<n>\n")
637 " -s <n> : test speed for size n\n");
638 my_printf(WHEN_LONG_OPTIONS("\n --correctness=<n>\n")
639 " -c <n> : test correctness for size n\n");
640 my_printf(WHEN_LONG_OPTIONS("\n --random=<rank>>\n")
641 " -r <rank> : test correctness for random sizes "
642 "(does not terminate)\n");
643 my_printf(WHEN_LONG_OPTIONS("\n --all=<rank>\n")
644 " -a <rank> : test correctness for all sizes "
645 "(does not terminate)\n");
646 my_printf(WHEN_LONG_OPTIONS("\n --fields=<n>\n")
647 " -f <n> : n fields ('howmany' param) in speed tests\n");
648 my_printf(WHEN_LONG_OPTIONS("\n --planner=<rank>\n")
649 " -p <rank> : test planner\n");
650 my_printf(WHEN_LONG_OPTIONS("\n --measure\n")
651 " -m : use FFTW_MEASURE in correctness tests\n");
652 my_printf(WHEN_LONG_OPTIONS("\n --estimate\n")
653 " -e : use FFTW_ESTIMATE in speed tests\n");
654 my_printf(WHEN_LONG_OPTIONS("\n --wisdom=<file>\n")
655 " -w <file> : use wisdom & read/write it from/to file\n");
656 my_printf(WHEN_LONG_OPTIONS("\n --timer\n")
657 " -t : test timer resolution\n");
658 my_printf(WHEN_LONG_OPTIONS("\n --x-repeat=<n>\n")
659 " -x <n> : run non-terminating tests (-r, -a) only n times\n");
660 my_printf(WHEN_LONG_OPTIONS("\n --paranoid\n")
661 " -P : enable paranoid tests\n");
662 my_printf(WHEN_LONG_OPTIONS("\n --verbose\n")
663 " -v : verbose output for subsequent options\n");
664 my_printf(WHEN_LONG_OPTIONS("\n --version\n")
665 " -V : print FFTW version information\n");
666 my_printf(WHEN_LONG_OPTIONS("\n --help\n")
667 " -h : this help\n");
668 #ifndef HAVE_GETOPT
669 my_printf("(When run with no arguments, an interactive mode is used.)\n");
670 #endif
671 if (exit_when_done)
672 exit(EXIT_FAILURE);
675 char wfname[128];
677 void handle_option(char opt, char *optarg)
679 FILE *wf;
680 struct size sz;
681 int rank, n;
683 switch (opt) {
684 case 's':
685 sz = parse_size(optarg);
686 if (!sz.is_nd)
687 test_speed(sz.narray[0]);
688 else
689 test_speed_nd(sz);
690 break;
692 case 'c':
693 sz = parse_size(optarg);
694 if (!sz.is_nd)
695 test_correctness(sz.narray[0]);
696 else
697 testnd_correctness_aux(sz);
698 break;
700 case 'p':
701 rank = atoi(optarg);
702 test_planner(rank);
703 break;
705 case 'P':
706 paranoid = 1;
707 enter_paranoid_mode();
708 break;
710 case 'r':
711 rank = atoi(optarg);
712 test_all_random(rank);
713 break;
715 case 'a':
716 rank = atoi(optarg);
717 if (rank == 0)
718 test_all();
719 else
720 testnd_all(rank);
721 break;
723 case 't':
724 test_timer();
725 break;
727 case 'f':
728 n = atoi(optarg);
729 CHECK(n > 0, "-f requires a positive integer argument");
730 howmany_fields = n;
731 break;
733 case 'm':
734 measure_flag = FFTW_MEASURE;
735 break;
737 case 'e':
738 speed_flag = FFTW_ESTIMATE;
739 break;
741 case 'w':
742 wisdom_flag = FFTW_USE_WISDOM;
743 strcpy(wfname, optarg);
744 wf = fopen(wfname, "r");
745 if (wf == 0) {
746 my_printf("Couldn't open wisdom file \"%s\".\n", wfname);
747 my_printf("This file will be created upon completion.\n");
748 } else {
749 CHECK(FFTW_SUCCESS == fftw_import_wisdom_from_file(wf),
750 "invalid wisdom file format");
751 fclose(wf);
753 break;
755 case 'v':
756 verbose++;
757 break;
759 case 'V':
760 my_printf("%s\n", fftw_version);
761 my_printf("%s test program, compiled in %s precision.\n",
762 fftw_prefix,
763 sizeof(fftw_real) == sizeof(double) ? "double"
764 : (sizeof(fftw_real) == sizeof(float) ? "single"
765 : "unknown"));
766 my_printf(
767 "\nCopyright (C) Massachusetts Institute of Technology.\n"
768 "FFTW comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"
769 "you are welcome to redistribute it under the terms of the GNU\n"
770 "General Public License. For more information, see the file COPYING or\n"
771 "the GNU web site at http://www.gnu.org.\n"
772 "\nFor more information regarding FFTW, or to download the latest version,\n"
773 "see the FFTW home page at http://theory.lcs.mit.edu/~fftw.\n");
775 break;
777 case 'x':
778 n = atoi(optarg);
779 CHECK(n > 0, "-x requires a positive integer argument");
780 max_iterations = n;
781 break;
783 case 'h':
784 usage(FALSE);
785 break;
787 default:
788 usage(TRUE);
791 /* every test must free all the used FFTW memory */
792 if (!(wisdom_flag & FFTW_USE_WISDOM) && chk_mem_leak)
793 fftw_check_memory_leaks();
798 short askuser(const char *s)
800 char line[200] = "", c;
801 int i, count = 0;
803 do {
804 if (count++ > 0)
805 my_printf("Invalid response. Please enter \"y\" or \"n\".\n");
806 my_printf("%s (y/n) ", s);
807 /* skip blank lines */
808 while (line[0] == 0 || line[0] == '\n')
809 fgets(line, 200, stdin);
810 for (i = 0; line[i] && (line[i] == ' ' || line[i] == '\t'); ++i);
811 c = line[i];
812 } while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');
814 return (c == 'y' || c == 'Y');
817 /* Standard function to get the next command-line argument for the program.
818 Returns the option character (or -1 if there are no more options),
819 and the option argument (if any) in argval, which is an array of length
820 at least argval_maxlen.
822 The test programs need to implement a function get_option with the
823 same arguments as this one, which will typically just call
824 default_get_option.
826 The reason we need to put this in a separate function is that the MPI
827 test programs can't rely on all of the processes having direct access
828 to the program arguments--they need to pass them as explicit messages
829 from the master process. Sigh. */
830 int default_get_option(int argc, char **argv, char *argval, int argval_maxlen)
832 int c = -1;
834 if (argc <= 1)
835 usage(TRUE);
837 #ifdef HAVE_GETOPT
839 const char short_options[] = "s:c:w:f:p:Pa:r:tvVmehx:";
840 extern char *optarg;
841 extern int optind;
843 # if defined(HAVE_GETOPT_LONG) && defined(HAVE_GETOPT_H)
845 int option_index;
846 const struct option long_options[] = {
847 {"speed", 1, 0, 's'},
848 {"correctness", 1, 0, 'c'},
849 {"wisdom", 1, 0, 'w'},
850 {"fields", 1, 0, 'f'},
851 {"planner", 1, 0, 'p'},
852 {"paranoid", 0, 0, 'P'},
853 {"all", 1, 0, 'a'},
854 {"random", 1, 0, 'r'},
855 {"timer", 0, 0, 't'},
856 {"verbose", 0, 0, 'v'},
857 {"version", 0, 0, 'V'},
858 {"measure", 0, 0, 'm'},
859 {"estimate", 0, 0, 'e'},
860 {"help", 0, 0, 'h'},
861 {"x-repeat", 1, 0, 'x'},
862 {0, 0, 0, 0}
865 c = getopt_long(argc, argv, short_options, long_options,
866 &option_index);
868 # else /* not HAVE_GETOPT_LONG */
869 c = getopt(argc, argv, short_options);
870 # endif /* not HAVE_GETOPT_LONG */
872 if (c == -1 && argc != optind)
873 usage(TRUE); /* there were invalid args; print usage info */
875 if (optarg) {
876 strncpy(argval, optarg, argval_maxlen - 1);
877 argval[argval_maxlen - 1] = 0;
879 else
880 argval[0] = 0;
882 #endif /* HAVE_GETOPT */
884 return c;
887 int main(int argc, char *argv[])
889 verbose = 1;
890 wisdom_flag = 0;
891 measure_flag = FFTW_ESTIMATE;
892 chk_mem_leak = 1;
893 paranoid = 0;
895 #ifdef DETERMINISTIC
896 srand(1123);
897 #else
898 srand((unsigned int) time(NULL));
899 #endif
901 test_init(&argc, argv);
904 * To parse the command line, we use getopt, but this does not seem
905 * to be in the ANSI standard (it is only available on UNIX,
906 * apparently).
908 #ifndef HAVE_GETOPT
909 if (argc > 1)
910 my_printf("Sorry, command-line arguments are not available on\n"
911 "this system. Run fftw_test with no arguments to\n"
912 "use it in interactive mode.\n");
914 if (argc <= 1) {
915 int n = 0;
916 char s[128] = "";
918 usage(FALSE);
920 my_printf("\n");
922 if (askuser("Perform random correctness tests (non-terminating)?"))
923 handle_option('r', "0");
925 if (askuser("Verbose output?"))
926 handle_option('v', "");
927 if (askuser("Paranoid test?"))
928 handle_option('P', "");
930 if (askuser("Use/test wisdom?")) {
931 my_printf(" Enter wisdom file name to use: ");
932 fgets(s, 128, stdin);
933 handle_option('w', s);
935 if (askuser("Test correctness?")) {
936 if (askuser(" -- for all sizes?"))
937 handle_option('a', "");
938 else {
939 my_printf(" Enter n: ");
940 fgets(s, 128, stdin);
941 handle_option('c', s);
944 if (askuser("Test speed?")) {
945 my_printf(" Enter n: ");
946 fgets(s, 128, stdin);
947 handle_option('s', s);
949 if (askuser("Test planner?"))
950 handle_option('p', "");
951 if (askuser("Test timer?"))
952 handle_option('t', "");
954 #else /*
955 * read command-line args using getopt
956 * facility
959 char option_arg[128];
960 int c;
962 while ((c = get_option(argc, argv, option_arg, 128)) != -1)
963 handle_option(c, option_arg);
965 #endif
967 if (wisdom_flag & FFTW_USE_WISDOM) {
968 char *ws;
969 FILE *wf;
971 ws = fftw_export_wisdom_to_string();
972 CHECK(ws != 0, "error exporting wisdom to string");
973 my_printf("\nAccumulated wisdom:\n %s\n", ws);
974 fftw_forget_wisdom();
975 CHECK(FFTW_SUCCESS == fftw_import_wisdom_from_string(ws),
976 "unexpected error reading in wisdom from string");
977 fftw_free(ws);
979 if (io_okay) {
980 wf = fopen(wfname, "w");
981 CHECK(wf != 0, "error creating wisdom file");
982 fftw_export_wisdom_to_file(wf);
983 fclose(wf);
986 /* make sure to dispose of wisdom before checking for memory leaks */
987 fftw_forget_wisdom();
989 fftw_check_memory_leaks();
990 if (io_okay)
991 fftw_print_max_memory_usage();
993 test_finish();
995 return EXIT_SUCCESS;