grisu3_test.c (4678B)
1 #include <inttypes.h> 2 #include <string.h> 3 #include <stdio.h> 4 5 #include "grisu3_parse.h" 6 #include "grisu3_print.h" 7 8 #define TEST(x, s) do { \ 9 if (!(x)) { \ 10 fprintf(stderr, \ 11 "fail: %s\n" \ 12 " input: %s\n" \ 13 " expected: %.17g\n" \ 14 " got: %.17g\n" \ 15 " binary xor: 0x%016"PRId64"\n", \ 16 s, buf, expect, v, (a ^ b)); \ 17 return 1; \ 18 } \ 19 } while (0) 20 21 static int test_parse_double(char *buf) 22 { 23 const char *k, *end; 24 double v, expect; 25 uint64_t a = 0, b = 0; 26 int len = strlen(buf); 27 28 end = buf + len; 29 30 expect = strtod(buf, 0); 31 /* Include '\0' in bytes being parsed to make strtod safe. */ 32 k = grisu3_parse_double(buf, len, &v); 33 34 /* Make sure we parsed and accepted everything. */ 35 TEST(k == end, "didn't parse to end"); 36 37 a = grisu3_cast_uint64_from_double(expect); 38 b = grisu3_cast_uint64_from_double(v); 39 40 #ifdef GRISU3_PARSE_ALLOW_ERROR 41 /* 42 * Just where exponent wraps, this assumption will be incorrect. 43 * TODO: need next higher double function. 44 */ 45 TEST(a - b <= 1, "binary representation differs by more than lsb"); 46 #else 47 /* Binary comparison should match. */ 48 TEST(expect == v, "double representation differs"); 49 TEST(a == b, "binary representation differs"); 50 #endif 51 52 #if 0 53 /* This will print the test data also when correct. */ 54 TEST(0, "test case passed, just debugging"); 55 #endif 56 57 return 0; 58 } 59 60 /* 61 * We currently do not test grisu3_print_double because 62 * it is a direct port of dtoa_grisu3 from grisu3.c 63 * which presumably has been tested in MathGeoLib. 64 * 65 * grisu3_parse_double is a new implementation. 66 */ 67 int test_suite() 68 { 69 char buf[50]; 70 int fail = 0; 71 72 fail += test_parse_double("1.23434"); 73 fail += test_parse_double("1234.34"); 74 fail += test_parse_double("1234.34e4"); 75 fail += test_parse_double("1234.34e-4"); 76 fail += test_parse_double("1.23434E+4"); 77 fail += test_parse_double("3.2897984798741413E+194"); 78 fail += test_parse_double("-3.2897984798741413E-194"); 79 80 sprintf(buf, "3289798479874141.314124124128497098e109"); 81 fail += test_parse_double(buf); 82 sprintf(buf, "3289798479874141.314124124128497098e209"); 83 fail += test_parse_double(buf); 84 sprintf(buf, "-3289798479874141.314124124128497098e209"); 85 fail += test_parse_double(buf); 86 sprintf(buf, "3289798479874141.314124124128497098e+209"); 87 fail += test_parse_double(buf); 88 sprintf(buf, "-3289798479874141.314124124128497098e-209"); 89 fail += test_parse_double(buf); 90 91 return fail; 92 } 93 94 void example() 95 { 96 double v; 97 const char *buf = "1234.34e-4"; 98 const char *x, *end; 99 char result_buf[50]; 100 int len; 101 102 fprintf(stderr, "grisu3_parse_double example:\n parsing '%s' as double\n", buf); 103 /* A non-numeric terminator (e.g. '\0') is required to ensure strtod fallback is safe. */ 104 len = strlen(buf); 105 end = buf + len; 106 x = grisu3_parse_double(buf, len, &v); 107 if (x == 0) { 108 fprintf(stderr, "syntax or range error\n"); 109 } else if (x == buf) { 110 fprintf(stderr, "parse double failed\n"); 111 } else if (x != end) { 112 fprintf(stderr, "parse double did not read everything\n"); 113 } else { 114 fprintf(stderr, "got: %.17g\n", v); 115 } 116 /* 117 * TODO: with the current example: the input "0.123434" is printed 118 * as "1.23434e-1" which is sub-optimal and different from sprintf. 119 * 120 * This is not the grisu3 algorithm but a post formatting step 121 * in grisu3_print_double (originally dtoa_grisu) and may be a bug 122 * in the logic choosing the best print format. 123 * sprintf "%.17g" and "%g" both print as "0.123434" 124 */ 125 fprintf(stderr, "grisu3_print_double example:\n printing %g\n", v); 126 grisu3_print_double(v, result_buf); 127 fprintf(stderr, "got: %s\n", result_buf); 128 } 129 130 int main() 131 { 132 example(); 133 fprintf(stderr, "running tests\n"); 134 if (test_suite()) { 135 fprintf(stderr, "GRISU3 PARSE TEST FAILED\n"); 136 return -1; 137 } else { 138 fprintf(stderr, "GRISU3 PARSE TEST PASSED\n"); 139 return 0; 140 } 141 }