4 * Copyright (c) 2011-2013 John Cunningham Bowler
6 * Last changed in libpng 1.6.0 [February 14, 2013]
8 * This code is released under the libpng license.
9 * For conditions of distribution and use, see the disclaimer
10 * and license in png.h
12 * Test internal arithmetic functions of libpng.
14 * This code must be linked against a math library (-lm), but does not require
15 * libpng or zlib to work. Because it includes the complete source of 'png.c'
16 * it tests the code with whatever compiler options are used to build it.
17 * Changing these options can substantially change the errors in the
18 * calculations that the compiler chooses!
20 #define _POSIX_SOURCE 1
21 #define _ISOC99_SOURCE 1
23 /* Obtain a copy of the code to be tested (plus other things), disabling
24 * stuff that is not required.
32 #include "../../pngpriv.h"
34 #define png_error png_warning
36 void png_warning(png_const_structrp png_ptr
, png_const_charp msg
)
38 fprintf(stderr
, "validation: %s\n", msg
);
41 #define png_fixed_error png_fixed_warning
43 void png_fixed_warning(png_const_structrp png_ptr
, png_const_charp msg
)
45 fprintf(stderr
, "overflow in: %s\n", msg
);
48 #define png_set_error_fn(pp, ep, efp, wfp) ((void)0)
49 #define png_malloc(pp, s) malloc(s)
50 #define png_malloc_warn(pp, s) malloc(s)
51 #define png_malloc_base(pp, s) malloc(s)
52 #define png_calloc(pp, s) calloc(1, (s))
53 #define png_free(pp, s) free(s)
55 #define png_safecat(b, sb, pos, str) (pos)
56 #define png_format_number(start, end, format, number) (start)
58 #define crc32(crc, pp, s) (crc)
59 #define inflateReset(zs) Z_OK
61 #define png_create_struct(type) (0)
62 #define png_destroy_struct(pp) ((void)0)
63 #define png_create_struct_2(type, m, mm) (0)
64 #define png_destroy_struct_2(pp, f, mm) ((void)0)
66 #undef PNG_SIMPLIFIED_READ_SUPPORTED
67 #undef PNG_SIMPLIFIED_WRITE_SUPPORTED
68 #undef PNG_USER_MEM_SUPPORTED
70 #include "../../png.c"
72 /* Validate ASCII to fp routines. */
73 static int verbose
= 0;
75 int validation_ascii_to_fp(int count
, int argc
, char **argv
)
78 double max_error
=2; /* As a percentage error-in-last-digit/.5 */
79 double max_error_abs
=17; /* Used when precision is DBL_DIG */
82 double test
= 0; /* Important to test this. */
91 if (strcmp(*++argv
, "-a") == 0)
93 else if (strcmp(*argv
, "-e") == 0 && argc
> 0)
96 max_error
= atof(*++argv
);
98 else if (strcmp(*argv
, "-E") == 0 && argc
> 0)
101 max_error_abs
= atof(*++argv
);
105 fprintf(stderr
, "unknown argument %s\n", *argv
);
112 int state
, failed
= 0;
121 fprintf(stderr
, "%.*g %d\n", DBL_DIG
, test
, precision
);
123 /* Check for overflow in the buffer by setting a marker. */
124 memset(buffer
, 71, sizeof buffer
);
126 png_ascii_from_fp(0, buffer
, precision
+10, test
, precision
);
128 /* Allow for a three digit exponent, this stuff will fail if
129 * the exponent is bigger than this!
131 if (buffer
[precision
+7] != 71)
133 fprintf(stderr
, "%g[%d] -> '%s'[%lu] buffer overflow\n", test
,
134 precision
, buffer
, (unsigned long)strlen(buffer
));
138 /* Following are used for the number parser below and must be
139 * initialized to zero.
146 if (test
>= 0 && strcmp(buffer
, "inf") ||
147 test
< 0 && strcmp(buffer
, "-inf"))
149 fprintf(stderr
, "%g[%d] -> '%s' but expected 'inf'\n", test
,
154 else if (!png_check_fp_number(buffer
, precision
+10, &state
, &index
) ||
157 fprintf(stderr
, "%g[%d] -> '%s' but has bad format ('%c')\n", test
,
158 precision
, buffer
, buffer
[index
]);
161 else if (PNG_FP_IS_NEGATIVE(state
) && !(test
< 0))
163 fprintf(stderr
, "%g[%d] -> '%s' but negative value not so reported\n",
164 test
, precision
, buffer
);
166 assert(!PNG_FP_IS_ZERO(state
));
167 assert(!PNG_FP_IS_POSITIVE(state
));
169 else if (PNG_FP_IS_ZERO(state
) && !(test
== 0))
171 fprintf(stderr
, "%g[%d] -> '%s' but zero value not so reported\n",
172 test
, precision
, buffer
);
174 assert(!PNG_FP_IS_NEGATIVE(state
));
175 assert(!PNG_FP_IS_POSITIVE(state
));
177 else if (PNG_FP_IS_POSITIVE(state
) && !(test
> 0))
179 fprintf(stderr
, "%g[%d] -> '%s' but positive value not so reported\n",
180 test
, precision
, buffer
);
182 assert(!PNG_FP_IS_NEGATIVE(state
));
183 assert(!PNG_FP_IS_ZERO(state
));
187 /* Check the result against the original. */
188 double out
= atof(buffer
);
189 double change
= fabs((out
- test
)/test
);
190 double allow
= .5/pow(10,
191 (precision
>= DBL_DIG
) ? DBL_DIG
-1 : precision
-1);
193 /* NOTE: if you hit this error case are you compiling with gcc
194 * and -O0? Try -O2 - the errors can accumulate if the FP
195 * code above is not optimized and may drift outside the .5 in
196 * DBL_DIG allowed. In any case a small number of errors may
197 * occur (very small ones - 1 or 2%) because of rounding in the
198 * calculations, either in the conversion API or in atof.
200 if (change
>= allow
&& (isfinite(out
) ||
201 fabs(test
/DBL_MAX
) <= 1-allow
))
203 double percent
= (precision
>= DBL_DIG
) ? max_error_abs
: max_error
;
204 double allowp
= (change
-allow
)*100/allow
;
206 if (precision
>= DBL_DIG
)
208 if (max_abs
< allowp
) max_abs
= allowp
;
213 if (max
< allowp
) max
= allowp
;
216 if (showall
|| allowp
>= percent
)
219 "%.*g[%d] -> '%s' -> %.*g number changed (%g > %g (%d%%))\n",
220 DBL_DIG
, test
, precision
, buffer
, DBL_DIG
, out
, change
, allow
,
235 /* Generate a new number and precision. */
237 if (precision
& 1) test
= -test
;
240 /* Generate random numbers. */
241 if (test
== 0 || !isfinite(test
))
245 /* Derive the exponent from the previous rand() value. */
246 int exponent
= precision
% (DBL_MAX_EXP
- DBL_MIN_EXP
) + DBL_MIN_EXP
;
248 test
= frexp(test
* rand(), &tmp
);
249 test
= ldexp(test
, exponent
);
250 precision
>>= 8; /* arbitrary */
253 /* This limits the precision to 32 digits, enough for standard
254 * IEEE implementations which have at most 15 digits.
256 precision
= (precision
& 0x1f) + 1;
260 printf("Tested %d finite values, %d non-finite, %d OK (%d failed) %d minor "
261 "arithmetic errors\n", finite
, nonfinite
, ok
, failcount
, minorarith
);
262 printf(" Error with >=%d digit precision %.2f%%\n", DBL_DIG
, max_abs
);
263 printf(" Error with < %d digit precision %.2f%%\n", DBL_DIG
, max
);
268 /* Observe that valid FP numbers have the forms listed in the PNG extensions
271 * [+,-]{integer,integer.fraction,.fraction}[{e,E}[+,-]integer]
273 * Test each of these in turn, including invalid cases.
275 typedef enum checkfp_state
277 start
, fraction
, exponent
, states
280 /* The characters (other than digits) that characterize the states: */
281 static const char none
[] = "";
282 static const char hexdigits
[16] = "0123456789ABCDEF";
286 const char *start
; /* Characters valid at the start */
287 const char *end
; /* Valid characters that end the state */
288 const char *tests
; /* Characters to test after 2 digits seen */
290 state_characters
[states
] =
292 /* start: */ { "+-.", ".eE", "+-.e*0369" },
293 /* fraction: */ { none
, "eE", "+-.E#0147" },
294 /* exponent: */ { "+-", none
, "+-.eE^0258" }
299 char number
[1024]; /* Buffer for number being tested */
300 int limit
; /* Command line limit */
301 int verbose
; /* Shadows global variable */
302 int ctimes
; /* Number of numbers tested */
303 int cmillions
; /* Count of millions of numbers */
304 int cinvalid
; /* Invalid strings checked */
305 int cnoaccept
; /* Characters not accepted */
311 int cnumber
; /* Index into number string */
312 checkfp_state check_state
; /* Current number state */
313 int at_start
; /* At start (first character) of state */
314 int cdigits_in_state
; /* Digits seen in that state */
315 int limit
; /* Limit on same for checking all chars */
316 int state
; /* Current parser state */
317 int is_negative
; /* Number is negative */
318 int is_zero
; /* Number is (still) zero */
319 int number_was_valid
; /* Previous character validity */
323 static int check_all_characters(checkfp_command
*co
, checkfp_control c
);
325 static int check_some_characters(checkfp_command
*co
, checkfp_control c
,
328 static int check_one_character(checkfp_command
*co
, checkfp_control c
, int ch
)
330 /* Test this character (ch) to ensure the parser does the correct thing.
333 const char test
= (char)ch
;
334 int number_is_valid
= png_check_fp_number(&test
, 1, &c
.state
, &index
);
335 int character_accepted
= (index
== 1);
337 if (c
.check_state
!= exponent
&& isdigit(ch
) && ch
!= '0')
340 if (c
.check_state
== start
&& c
.at_start
&& ch
== '-')
344 co
->number
[c
.cnumber
++] = (char)ch
;
347 co
->number
[c
.cnumber
++] = '<';
348 co
->number
[c
.cnumber
++] = hexdigits
[(ch
>> 4) & 0xf];
349 co
->number
[c
.cnumber
++] = hexdigits
[ch
& 0xf];
350 co
->number
[c
.cnumber
++] = '>';
352 co
->number
[c
.cnumber
] = 0;
355 fprintf(stderr
, "%s\n", co
->number
);
357 if (++(co
->ctimes
) == 1000000)
359 if (co
->verbose
== 1)
365 if (!number_is_valid
)
368 if (!character_accepted
)
371 /* This should never fail (it's a serious bug if it does): */
372 if (index
!= 0 && index
!= 1)
374 fprintf(stderr
, "%s: read beyond end of string (%lu)\n", co
->number
,
375 (unsigned long)index
);
379 /* Validate the new state, note that the PNG_FP_IS_ macros all return
380 * false unless the number is valid.
382 if (PNG_FP_IS_NEGATIVE(c
.state
) !=
383 (number_is_valid
&& !c
.is_zero
&& c
.is_negative
))
385 fprintf(stderr
, "%s: negative when it is not\n", co
->number
);
389 if (PNG_FP_IS_ZERO(c
.state
) != (number_is_valid
&& c
.is_zero
))
391 fprintf(stderr
, "%s: zero when it is not\n", co
->number
);
395 if (PNG_FP_IS_POSITIVE(c
.state
) !=
396 (number_is_valid
&& !c
.is_zero
&& !c
.is_negative
))
398 fprintf(stderr
, "%s: positive when it is not\n", co
->number
);
402 /* Testing a digit */
405 if (!character_accepted
)
407 fprintf(stderr
, "%s: digit '%c' not accepted\n", co
->number
, ch
);
411 if (!number_is_valid
)
413 fprintf(stderr
, "%s: saw a digit (%c) but number not valid\n",
418 ++c
.cdigits_in_state
;
420 c
.number_was_valid
= 1;
422 /* Continue testing characters in this state. Either test all of
423 * them or, if we have already seen one digit in this state, just test a
426 if (c
.cdigits_in_state
< 1)
427 return check_all_characters(co
, c
);
430 return check_some_characters(co
, c
,
431 state_characters
[c
.check_state
].tests
);
434 /* A non-digit; is it allowed here? */
435 else if (((ch
== '+' || ch
== '-') && c
.check_state
!= fraction
&&
437 (ch
== '.' && c
.check_state
== start
) ||
438 ((ch
== 'e' || ch
== 'E') && c
.number_was_valid
&&
439 c
.check_state
!= exponent
))
441 if (!character_accepted
)
443 fprintf(stderr
, "%s: character '%c' not accepted\n", co
->number
, ch
);
447 /* The number remains valid after start of fraction but nowhere else. */
448 if (number_is_valid
&& (c
.check_state
!= start
|| ch
!= '.'))
450 fprintf(stderr
, "%s: saw a non-digit (%c) but number valid\n",
455 c
.number_was_valid
= number_is_valid
;
457 /* Check for a state change. When changing to 'fraction' if the number
458 * is valid at this point set the at_start to false to allow an exponent
461 if (c
.check_state
== start
&& ch
== '.')
463 c
.check_state
= fraction
;
464 c
.at_start
= !number_is_valid
;
465 c
.cdigits_in_state
= 0;
467 return check_all_characters(co
, c
);
470 else if (c
.check_state
< exponent
&& (ch
== 'e' || ch
== 'E'))
472 c
.check_state
= exponent
;
474 c
.cdigits_in_state
= 0;
476 return check_all_characters(co
, c
);
479 /* Else it was a sign, and the state doesn't change. */
482 if (ch
!= '-' && ch
!= '+')
484 fprintf(stderr
, "checkfp: internal error (1)\n");
489 return check_all_characters(co
, c
);
493 /* Testing an invalid character */
496 if (character_accepted
)
498 fprintf(stderr
, "%s: character '%c' [0x%.2x] accepted\n", co
->number
,
503 if (number_is_valid
!= c
.number_was_valid
)
506 "%s: character '%c' [0x%.2x] changed number validity\n", co
->number
,
511 /* Do nothing - the parser has stuck; return success and keep going with
512 * the next character.
516 /* Successful return (the caller will try the next character.) */
520 static int check_all_characters(checkfp_command
*co
, checkfp_control c
)
524 if (c
.cnumber
+4 < sizeof co
->number
) for (ch
=0; ch
<256; ++ch
)
526 if (!check_one_character(co
, c
, ch
))
533 static int check_some_characters(checkfp_command
*co
, checkfp_control c
,
540 if (c
.cnumber
+4 < sizeof co
->number
&& c
.limit
>= 0)
542 if (c
.limit
> 0) for (i
=0; tests
[i
]; ++i
)
544 if (!check_one_character(co
, c
, tests
[i
]))
548 /* At the end check all the characters. */
550 return check_all_characters(co
, c
);
556 int validation_checkfp(int count
, int argc
, char **argv
)
559 checkfp_command command
;
560 checkfp_control control
;
562 command
.number
[0] = 0;
564 command
.verbose
= verbose
;
566 command
.cmillions
= 0;
567 command
.cinvalid
= 0;
568 command
.cnoaccept
= 0;
573 if (argc
> 1 && strcmp(*argv
, "-l") == 0)
576 command
.limit
= atoi(*++argv
);
581 fprintf(stderr
, "unknown argument %s\n", *argv
);
587 control
.check_state
= start
;
588 control
.at_start
= 1;
589 control
.cdigits_in_state
= 0;
590 control
.limit
= command
.limit
;
592 control
.is_negative
= 0;
594 control
.number_was_valid
= 0;
596 result
= check_all_characters(&command
, control
);
598 printf("checkfp: %s: checked %d,%.3d,%.3d,%.3d strings (%d invalid)\n",
599 result
? "pass" : "FAIL", command
.cmillions
/ 1000,
600 command
.cmillions
% 1000, command
.ctimes
/ 1000, command
.ctimes
% 1000,
606 int validation_muldiv(int count
, int argc
, char **argv
)
614 png_uint_32 randbuffer
;
616 png_int_32 times
, div
;
620 fprintf(stderr
, "unknown argument %s\n", *++argv
);
624 /* Find out about the random number generator. */
625 randbuffer
= RAND_MAX
;
626 while (randbuffer
!= 0) ++randbits
, randbuffer
>>= 1;
627 printf("Using random number generator that makes %d bits\n", randbits
);
628 for (div
=0; div
<32; div
+= randbits
)
629 randbuffer
= (randbuffer
<< randbits
) ^ rand();
635 png_fixed_point result
;
636 /* NOTE: your mileage may vary, a type is required below that can
637 * hold 64 bits or more, if floating point is used a 64-bit or
638 * better mantissa is required.
640 long long int fp
, fpround
;
641 unsigned long hi
, lo
;
644 /* Check the values, png_64bit_product can only handle positive
645 * numbers, so correct for that here.
650 if (a
< 0) u1
= -a
, n
= 1; else u1
= a
;
651 if (times
< 0) u2
= -times
, n
= !n
; else u2
= times
;
652 png_64bit_product(u1
, u2
, &hi
, &lo
);
656 lo
= ((~lo
) + 1) & 0xffffffff;
664 if ((fp
& 0xffffffff) != lo
|| ((fp
>> 32) & 0xffffffff) != hi
)
666 fprintf(stderr
, "png_64bit_product %d * %d -> %lx|%.8lx not %llx\n",
667 a
, times
, hi
, lo
, fp
);
673 /* Round - this is C round to zero. */
674 if ((fp
< 0) != (div
< 0))
681 /* Assume 2's complement here: */
682 ok
= fpround
<= PNG_UINT_31_MAX
&&
683 fpround
>= -1-(long long int)PNG_UINT_31_MAX
;
687 ok
= 0, ++overflow
, fpround
= fp
/*misleading*/;
690 fprintf(stderr
, "TEST %d * %d / %d -> %lld (%s)\n", a
, times
, div
,
691 fp
, ok
? "ok" : "overflow");
694 if (png_muldiv(&result
, a
, times
, div
) != ok
)
698 fprintf(stderr
, "%d * %d / %d -> overflow (expected %lld)\n", a
,
701 fprintf(stderr
, "%d * %d / %d -> %d (expected overflow %lld)\n", a
,
702 times
, div
, result
, fp
);
704 else if (ok
&& result
!= fpround
)
707 fprintf(stderr
, "%d * %d / %d -> %d not %lld\n", a
, times
, div
, result
,
713 /* Generate three new values, this uses rand() and rand() only returns
720 randbuffer
= (randbuffer
<< randbits
) ^ rand();
724 printf("%d tests including %d overflows, %d passed, %d failed (%d 64-bit "
725 "errors)\n", tested
, overflow
, passed
, error
, error64
);
729 /* When FP is on this just becomes a speed test - compile without FP to get real
732 #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
733 #define LN2 .000010576586617430806112933839 /* log(2)/65536 */
734 #define L2INV 94548.46219969910586572651 /* 65536/log(2) */
736 /* For speed testing, need the internal functions too: */
737 static png_uint_32
png_log8bit(unsigned x
)
740 return (png_uint_32
)floor(.5-log(x
/255.)*L2INV
);
745 static png_uint_32
png_log16bit(png_uint_32 x
)
748 return (png_uint_32
)floor(.5-log(x
/65535.)*L2INV
);
753 static png_uint_32
png_exp(png_uint_32 x
)
755 return (png_uint_32
)floor(.5 + exp(x
* -LN2
) * 0xffffffffU
);
758 static png_byte
png_exp8bit(png_uint_32 log
)
760 return (png_byte
)floor(.5 + exp(log
* -LN2
) * 255);
763 static png_uint_16
png_exp16bit(png_uint_32 log
)
765 return (png_uint_16
)floor(.5 + exp(log
* -LN2
) * 65535);
767 #endif /* FLOATING_ARITHMETIC */
769 int validation_gamma(int argc
, char **argv
)
771 double gamma
[9] = { 2.2, 1.8, 1.52, 1.45, 1., 1/1.45, 1/1.52, 1/1.8, 1/2.2 };
773 int i
, silent
=0, onlygamma
=0;
775 /* Silence the output with -s, just test the gamma functions with -g: */
777 if (strcmp(*++argv
, "-s") == 0)
779 else if (strcmp(*argv
, "-g") == 0)
783 fprintf(stderr
, "unknown argument %s\n", *argv
);
789 /* First validate the log functions: */
791 for (i
=0; i
<256; ++i
)
793 double correct
= -log(i
/255.)/log(2.)*65536;
794 double error
= png_log8bit(i
) - correct
;
796 if (i
!= 0 && fabs(error
) > maxerr
)
797 maxerr
= fabs(error
);
799 if (i
== 0 && png_log8bit(i
) != 0xffffffff ||
800 i
!= 0 && png_log8bit(i
) != floor(correct
+.5))
802 fprintf(stderr
, "8-bit log error: %d: got %u, expected %f\n",
803 i
, png_log8bit(i
), correct
);
808 printf("maximum 8-bit log error = %f\n", maxerr
);
811 for (i
=0; i
<65536; ++i
)
813 double correct
= -log(i
/65535.)/log(2.)*65536;
814 double error
= png_log16bit(i
) - correct
;
816 if (i
!= 0 && fabs(error
) > maxerr
)
817 maxerr
= fabs(error
);
819 if (i
== 0 && png_log16bit(i
) != 0xffffffff ||
820 i
!= 0 && png_log16bit(i
) != floor(correct
+.5))
822 if (error
> .68) /* By experiment error is less than .68 */
824 fprintf(stderr
, "16-bit log error: %d: got %u, expected %f"
825 " error: %f\n", i
, png_log16bit(i
), correct
, error
);
831 printf("maximum 16-bit log error = %f\n", maxerr
);
833 /* Now exponentiations. */
835 for (i
=0; i
<=0xfffff; ++i
)
837 double correct
= exp(-i
/65536. * log(2.)) * (65536. * 65536);
838 double error
= png_exp(i
) - correct
;
840 if (fabs(error
) > maxerr
)
841 maxerr
= fabs(error
);
842 if (fabs(error
) > 1883) /* By experiment. */
844 fprintf(stderr
, "32-bit exp error: %d: got %u, expected %f"
845 " error: %f\n", i
, png_exp(i
), correct
, error
);
850 printf("maximum 32-bit exp error = %f\n", maxerr
);
853 for (i
=0; i
<=0xfffff; ++i
)
855 double correct
= exp(-i
/65536. * log(2.)) * 255;
856 double error
= png_exp8bit(i
) - correct
;
858 if (fabs(error
) > maxerr
)
859 maxerr
= fabs(error
);
860 if (fabs(error
) > .50002) /* By experiment */
862 fprintf(stderr
, "8-bit exp error: %d: got %u, expected %f"
863 " error: %f\n", i
, png_exp8bit(i
), correct
, error
);
868 printf("maximum 8-bit exp error = %f\n", maxerr
);
871 for (i
=0; i
<=0xfffff; ++i
)
873 double correct
= exp(-i
/65536. * log(2.)) * 65535;
874 double error
= png_exp16bit(i
) - correct
;
876 if (fabs(error
) > maxerr
)
877 maxerr
= fabs(error
);
878 if (fabs(error
) > .524) /* By experiment */
880 fprintf(stderr
, "16-bit exp error: %d: got %u, expected %f"
881 " error: %f\n", i
, png_exp16bit(i
), correct
, error
);
886 printf("maximum 16-bit exp error = %f\n", maxerr
);
889 /* Test the overall gamma correction. */
894 png_fixed_point gfp
= floor(g
* PNG_FP_1
+ .5);
897 printf("Test gamma %f\n", g
);
900 for (j
=0; j
<256; ++j
)
902 double correct
= pow(j
/255., g
) * 255;
903 png_byte out
= png_gamma_8bit_correct(j
, gfp
);
904 double error
= out
- correct
;
906 if (fabs(error
) > maxerr
)
907 maxerr
= fabs(error
);
908 if (out
!= floor(correct
+.5))
910 fprintf(stderr
, "8bit %d ^ %f: got %d expected %f error %f\n",
911 j
, g
, out
, correct
, error
);
916 printf("gamma %f: maximum 8-bit error %f\n", g
, maxerr
);
919 for (j
=0; j
<65536; ++j
)
921 double correct
= pow(j
/65535., g
) * 65535;
922 png_uint_16 out
= png_gamma_16bit_correct(j
, gfp
);
923 double error
= out
- correct
;
925 if (fabs(error
) > maxerr
)
926 maxerr
= fabs(error
);
927 if (fabs(error
) > 1.62)
929 fprintf(stderr
, "16bit %d ^ %f: got %d expected %f error %f\n",
930 j
, g
, out
, correct
, error
);
935 printf("gamma %f: maximum 16-bit error %f\n", g
, maxerr
);
941 /**************************** VALIDATION TESTS ********************************/
942 /* Various validation routines are included herein, they require some
943 * definition for png_warning and png_error, seetings of VALIDATION:
945 * 1: validates the ASCII to floating point conversions
946 * 2: validates png_muldiv
947 * 3: accuracy test of fixed point gamma tables
950 /* The following COUNT (10^8) takes about 1 hour on a 1GHz Pentium IV
953 #define COUNT 1000000000
955 int main(int argc
, char **argv
)
961 if (argc
> 2 && strcmp(argv
[1], "-c") == 0)
963 count
= atoi(argv
[2]);
968 else if (strcmp(argv
[1], "-v") == 0)
979 if (count
> 0 && argc
> 1)
981 if (strcmp(argv
[1], "ascii") == 0)
982 return validation_ascii_to_fp(count
, argc
-1, argv
+1);
983 else if (strcmp(argv
[1], "checkfp") == 0)
984 return validation_checkfp(count
, argc
-1, argv
+1);
985 else if (strcmp(argv
[1], "muldiv") == 0)
986 return validation_muldiv(count
, argc
-1, argv
+1);
987 else if (strcmp(argv
[1], "gamma") == 0)
988 return validation_gamma(argc
-1, argv
+1);
993 "usage: tarith [-v] [-c count] {ascii,muldiv,gamma} [args]\n");
994 fprintf(stderr
, " arguments: ascii [-a (all results)] [-e error%%]\n");
995 fprintf(stderr
, " checkfp [-l max-number-chars]\n");
996 fprintf(stderr
, " muldiv\n");
997 fprintf(stderr
, " gamma -s (silent) -g (only gamma; no log)\n");