1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set expandtab shiftwidth=4 tabstop=4: */
3
4 #include "modp_numtoa.h"
5 #include <stdio.h>
6 #include <limits.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "minunit.h"
10
11 /* Need only for INFINITY and optionally NAN macros */
12 /* We do not link with -lm */
13 #include <math.h>
14
testITOA()15 static char* testITOA()
16 {
17 char buf1[100];
18 char buf2[100];
19 int i;
20 for (i = 0; i < 100000; ++i) {
21 sprintf(buf1, "%d", i);
22 modp_itoa10(i, buf2);
23 mu_assert_str_equals(buf1, buf2);
24
25 sprintf(buf1, "%d", -i);
26 modp_itoa10(-i, buf2);
27 mu_assert_str_equals(buf1, buf2);
28
29 sprintf(buf1, "%d", INT_MAX - i);
30 modp_itoa10(INT_MAX - i, buf2);
31 mu_assert_str_equals(buf1, buf2);
32
33 sprintf(buf1, "%d", -(INT_MAX - i));
34 modp_itoa10(-(INT_MAX - i), buf2);
35 mu_assert_str_equals(buf1, buf2);
36 }
37 return 0;
38 }
39
testUITOA()40 static char* testUITOA()
41 {
42 char buf1[100];
43 char buf2[100];
44 uint32_t i;
45 for (i = 0; i < 1000000; ++i) {
46 sprintf(buf1, "%u", i);
47 modp_uitoa10(i, buf2);
48 mu_assert_str_equals(buf1, buf2);
49 }
50
51 for (i = 0; i < 1000000; ++i) {
52 sprintf(buf1, "%u", 0xFFFFFFFFu - i);
53 modp_uitoa10(0xFFFFFFFFu -i, buf2);
54 mu_assert_str_equals(buf1, buf2);
55 }
56 return 0;
57 }
58
testLITOA()59 static char* testLITOA()
60 {
61 char buf1[100];
62 char buf2[100];
63 long int i;
64 for (i = 0; i < 100000; ++i) {
65 sprintf(buf1, "%ld", i);
66 modp_litoa10(i, buf2);
67 mu_assert_str_equals(buf1, buf2);
68
69 sprintf(buf1, "%ld", -i);
70 modp_litoa10(-i, buf2);
71 mu_assert_str_equals(buf1, buf2);
72
73 sprintf(buf1, "%ld", LONG_MAX - i);
74 modp_litoa10(LONG_MAX - i, buf2);
75 mu_assert_str_equals(buf1, buf2);
76
77 sprintf(buf1, "%ld", -(LONG_MAX - i));
78 modp_litoa10(-(LONG_MAX - i), buf2);
79 mu_assert_str_equals(buf1, buf2);
80 }
81 return 0;
82 }
83
testULITOA()84 static char* testULITOA()
85 {
86 char buf1[100];
87 char buf2[100];
88 long long unsigned int i;
89 for (i = 0; i < 1000000; ++i) {
90 sprintf(buf1, "%llu", i);
91 modp_ulitoa10(i, buf2);
92 mu_assert_str_equals(buf1, buf2);
93 }
94
95 for (i = 0; i < 1000000; ++i) {
96 sprintf(buf1, "%llu", 0xFFFFFFFFFFFFFFFFllu - i);
97 modp_ulitoa10(0xFFFFFFFFFFFFFFFFull -i, buf2);
98 mu_assert_str_equals(buf1, buf2);
99 }
100 return 0;
101 }
102
testDoubleToA()103 static char* testDoubleToA()
104 {
105 char buf1[100];
106 char buf2[100];
107 char msg[200];
108 double d;
109
110 /* test each combination of whole number + fraction,
111 at every precision */
112 /* and test negative version */
113 double wholes[] = {0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,
114 67.0,101.0, 10000, 99999};
115 double frac[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.49, 0.5, 0.51, 0.6, 0.7,
116 0.9, 0.01, 0.25, 0.125, 0.05, 0.005, 0.0005, 0.00005,
117 0.001, 0.00001, 0.99, 0.999, 0.9999};
118 const char* formats[] = {"%.0f", "%.1f", "%.2f", "%.3f", "%.4f", "%.5f",
119 "%.6f", "%.7f", "%.8f", "%.9f"};
120
121 int imax = sizeof(wholes)/sizeof(double);
122 int jmax = sizeof(frac)/sizeof(double);
123 int kmax = sizeof(formats)/sizeof(const char*);
124
125 int i,j,k;
126 for (i = 0; i < imax; ++i) {
127 for (j = 0; j < jmax; ++j) {
128 for (k = 0; k < kmax; ++k) {
129 d = wholes[i] + frac[j];
130
131 sprintf(msg, "whole=%f, frac=%f, prec=%d -- ",
132 wholes[i], frac[j], k);
133 sprintf(buf1, formats[k], d);
134 modp_dtoa(d, buf2, k);
135 mu_assert_str_equals_msg(msg,buf1, buf2);
136
137 if (d != 0) {
138 sprintf(msg, "whole=%f, frac=%f, prec=%d -- ",
139 -wholes[i], frac[j], k);
140 /* not dealing with "-0" issues */
141 d = -d;
142 sprintf(buf1, formats[k], d);
143 modp_dtoa(d, buf2, k);
144 mu_assert_str_equals_msg(msg,buf1, buf2);
145 }
146
147 }
148 }
149 }
150
151 /* test very large positive number */
152 d = 1.0e200;
153 modp_dtoa(d, buf2, 6);
154 mu_assert_str_equals("1.000000e+200", buf2);
155
156 /* test very large negative number */
157 d = -1.0e200;
158 modp_dtoa(d, buf2, 6);
159 mu_assert_str_equals("-1.000000e+200", buf2);
160
161 /* test very small positive number */
162 d = 1e-10;
163 sprintf(buf1, "%.6f", d);
164 modp_dtoa(d, buf2, 6);
165 mu_assert_str_equals(buf1, buf2);
166
167 /* test very small negative number */
168 d = -1e-10;
169 sprintf(buf1, "%.6f", d);
170 modp_dtoa(d, buf2, 6);
171 mu_assert_str_equals(buf1, buf2);
172
173 return 0;
174 }
175
176 // Helper function
177 // Removes trailing zeros
178 // this is horible but it's just for testing.
stripTrailingZeros(char * buf)179 static void stripTrailingZeros(char* buf)
180 {
181 size_t i;
182 int hasdot = 0;
183 for (i = 0; i < strlen(buf); ++i) {
184 if (buf[i] == '.') {
185 hasdot = 1;
186 break;
187 }
188 }
189
190 // it's just an integer
191 if (!hasdot) {
192 return;
193 }
194
195 i = strlen(buf);
196 if (i == 0) {
197 return;
198 }
199 --i;
200
201 while (i > 0 && (buf[i] == '0' || buf[i] == '.')) {
202 if (buf[i] == '.') {
203 buf[i] = '\0';
204 break;
205 } else {
206 buf[i] = '\0';
207 --i;
208 }
209 }
210 }
211
testDoubleToA2()212 static char* testDoubleToA2()
213 {
214 char buf1[100];
215 char buf2[100];
216 char msg[200];
217 double d;
218
219 /* test each combination of whole number + fraction,
220 at every precision */
221 /* and test negative version */
222 double wholes[] = {0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,
223 67.0,101.0, 10000, 99999};
224 double frac[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.49, 0.5, 0.51, 0.6, 0.7,
225 0.9, 0.01, 0.25, 0.125, 0.05, 0.005, 0.0005, 0.00005,
226 0.001, 0.00001, 0.99, 0.999, 0.9999};
227 const char* formats[] = {"%.0f", "%.1f", "%.2f", "%.3f", "%.4f", "%.5f",
228 "%.6f", "%.7f", "%.8f", "%.9f"};
229
230 int imax = sizeof(wholes)/sizeof(double);
231 int jmax = sizeof(frac)/sizeof(double);
232 int kmax = sizeof(formats)/sizeof(const char*);
233
234 int i,j,k;
235 for (i = 0; i < imax; ++i) {
236 for (j = 0; j < jmax; ++j) {
237 for (k = 0; k < kmax; ++k) {
238 d = wholes[i] + frac[j];
239
240 sprintf(msg, "whole=%f, frac=%f, prec=%d -- ",
241 wholes[i], frac[j], k);
242
243 sprintf(buf1, formats[k], d);
244 stripTrailingZeros(buf1);
245 modp_dtoa2(d, buf2, k);
246 mu_assert_str_equals_msg(msg,buf1, buf2);
247
248 if (d != 0) {
249 sprintf(msg, "whole=%f, frac=%f, prec=%d -- ",
250 -wholes[i], frac[j], k);
251 /* not dealing with "-0" issues */
252 d = -d;
253 sprintf(buf1, formats[k], d);
254 stripTrailingZeros(buf1);
255
256 modp_dtoa2(d, buf2, k);
257 mu_assert_str_equals_msg(msg,buf1, buf2);
258 }
259
260 }
261 }
262 }
263
264 /* test very large positive number */
265 d = 1.0e200;
266 modp_dtoa2(d, buf2, 6);
267 mu_assert_str_equals("1.000000e+200", buf2);
268
269 /* test very large negative number */
270 d = -1.0e200;
271 modp_dtoa2(d, buf2, 6);
272 mu_assert_str_equals("-1.000000e+200", buf2);
273
274 /* test very small positive number */
275 d = 1e-10;
276 sprintf(buf1, "%.6f", d);
277 stripTrailingZeros(buf1);
278
279 modp_dtoa2(d, buf2, 6);
280 mu_assert_str_equals(buf1, buf2);
281
282 /* test very small negative number */
283 d = -1e-10;
284 sprintf(buf1, "%.6f", d);
285 stripTrailingZeros(buf1);
286
287 modp_dtoa2(d, buf2, 6);
288 mu_assert_str_equals(buf1, buf2);
289
290 // test bad precision values
291 d = 1.1;
292 modp_dtoa(d, buf2, -1);
293 mu_assert_str_equals("1", buf2);
294 modp_dtoa2(d, buf2, 10);
295 mu_assert_str_equals("1.1", buf2);
296 return 0;
297 }
298
299 /* From Issue 7 -- http://code.google.com/p/stringencoders/issues/detail?id=7
300 * thanks to http://code.google.com/u/simhasana/
301 */
testOverflowLITOA()302 static char* testOverflowLITOA() {
303 char buf1[100];
304 char buf2[100];
305
306 long long int longmin = LONG_MIN;
307 sprintf(buf1, "%lld", longmin);
308 modp_litoa10(longmin, buf2);
309 mu_assert_str_equals(buf1, buf2);
310
311 long long int longmax = LONG_MAX;
312 sprintf(buf1, "%lld", longmax);
313 modp_litoa10(longmax, buf2);
314 mu_assert_str_equals(buf1, buf2);
315
316 return 0;
317 }
318
testOverflowITOA()319 static char* testOverflowITOA() {
320 char buf1[100];
321 char buf2[100];
322
323 int32_t intmin = INT_MIN;
324 sprintf(buf1, "%d", intmin);
325 modp_itoa10(intmin, buf2);
326 mu_assert_str_equals(buf1, buf2);
327
328 int32_t intmax = INT_MAX;
329 sprintf(buf1, "%d", intmax);
330 modp_itoa10(intmax, buf2);
331 mu_assert_str_equals(buf1, buf2);
332
333 return 0;
334 }
335
336 // Test NaN and Infinity behavior
testDTOANonFinite()337 static char* testDTOANonFinite() {
338 char buf1[100];
339 char buf2[100];
340 double d;
341
342 // down below are some IFDEFs that may or may not exist.
343 // depending on compiler settings "buf1" might not be used
344 // and halt compilation. The next line touches buf1 so this
345 // doesn't happen
346 (void)buf1;
347
348 /* Test for inf */
349 d = 1e200 * 1e200;
350 // NOTE!!! next line will core dump!
351 //sprintf(buf1, "%.6f", d);
352 buf2[0] = '\0';
353 modp_dtoa2(d, buf2, 6);
354 mu_assert_str_equals("inf", buf2);
355
356 /* INFINITY should be standard. Defined in <math.h> */
357 /* http://www.gnu.org/s/libc/manual/html_node/Infinity-and-NaN.html */
358 #ifdef INFINITY
359 d = INFINITY;
360
361 // test libc support
362 sprintf(buf1, "%f", d);
363 mu_assert_str_equals("inf", buf1);
364
365 buf2[0] = '\0';
366 modp_dtoa(d, buf2, 6);
367 mu_assert_str_equals("inf", buf2);
368
369 buf2[0] = '\0';
370 modp_dtoa2(d, buf2, 6);
371 mu_assert_str_equals("inf", buf2);
372 #endif
373
374 /* NAN is a GNU extension, defined in <math.h> */
375 /* http://www.gnu.org/s/libc/manual/html_node/Infinity-and-NaN.html */
376 #ifdef NAN
377 d = NAN;
378
379 // test libc support
380 sprintf(buf1, "%f", d);
381 mu_assert_str_equals("nan", buf1);
382
383 // now test ours
384 buf2[0] = '\0';
385 modp_dtoa(d, buf2, 6);
386 mu_assert_str_equals("nan", buf2);
387 buf2[0] = '\0';
388 modp_dtoa2(d, buf2, 6);
389 mu_assert_str_equals("nan", buf2);
390 #endif
391
392 return 0;
393
394 }
395
all_tests()396 static char* all_tests() {
397 mu_run_test(testITOA);
398 mu_run_test(testUITOA);
399 mu_run_test(testLITOA);
400 mu_run_test(testULITOA);
401 mu_run_test(testDoubleToA);
402 mu_run_test(testDoubleToA2);
403 mu_run_test(testOverflowLITOA);
404 mu_run_test(testOverflowITOA);
405 mu_run_test(testDTOANonFinite);
406 return 0;
407 }
408
409 UNITTESTS
410