aboutsummaryrefslogtreecommitdiff
path: root/test/src/TestFloat.c
blob: dac6171ad2b92ea943db12810e86a67300a2c5bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
#include <BH/String.h>
#include <BH/Util.h>
#include <BH/Unit.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>


static int compareString(double value,
                         int format,
                         int precision,
                         const char *ref)
{
    int result;
    char *str;

    str = BH_StringFromDouble(value, format, precision);
    result = strcmp(str, ref);
    if (result)
        printf("Value: %.17g\tReference: %s\tGot: %s\n", value, ref, str);

    BH_StringFree(str);

    return result;
}


static int roundtripString(double value,
                           int format)
{
    double result;
    char *str;

    str = BH_StringFromDouble(value, format, -1);
    result = BH_StringToDouble(str, NULL);
    if (result != value)
        printf("Value: %.17g\tGot: %.17g\tStr: %s\n", value, result, str);

    BH_StringFree(str);

    return result != value;
}


BH_UNIT_TEST(FixedFormat)
{
    BH_VERIFY(compareString(30.0159265358979323846, 'f', 0, "30") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'f', 1, "30.0") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'f', 2, "30.02") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'f', 3, "30.016") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'f', 4, "30.0159") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'f', 5, "30.01593") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'f', 0, "-30") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'f', 1, "-30.0") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'f', 2, "-30.02") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'f', 3, "-30.016") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'f', 4, "-30.0159") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'f', 5, "-30.01593") == 0);

    BH_VERIFY(compareString(0.0, 'f', 0, "0") == 0);
    BH_VERIFY(compareString(0.0, 'f', 1, "0.0") == 0);
    BH_VERIFY(compareString(-0.0, 'f', 0, "-0") == 0);
    BH_VERIFY(compareString(-0.0, 'f', 1, "-0.0") == 0);

    BH_VERIFY(compareString(0.00015425, 'f', 0, "0") == 0);
    BH_VERIFY(compareString(0.00015425, 'f', 1, "0.0") == 0);
    BH_VERIFY(compareString(0.00015425, 'f', 2, "0.00") == 0);
    BH_VERIFY(compareString(0.00015425, 'f', 3, "0.000") == 0);
    BH_VERIFY(compareString(0.00015425, 'f', 4, "0.0002") == 0);
    BH_VERIFY(compareString(0.00015425, 'f', 5, "0.00015") == 0);
    BH_VERIFY(compareString(-0.00015425, 'f', 0, "-0") == 0);
    BH_VERIFY(compareString(-0.00015425, 'f', 1, "-0.0") == 0);
    BH_VERIFY(compareString(-0.00015425, 'f', 2, "-0.00") == 0);
    BH_VERIFY(compareString(-0.00015425, 'f', 3, "-0.000") == 0);
    BH_VERIFY(compareString(-0.00015425, 'f', 4, "-0.0002") == 0);
    BH_VERIFY(compareString(-0.00015425, 'f', 5, "-0.00015") == 0);

    BH_VERIFY(compareString(1234567.1234, 'f', 0, "1234567") == 0);
    BH_VERIFY(compareString(-1234567.1234, 'f', 0, "-1234567") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'f', 0, "1230000000") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'f', 1, "1230000000.0") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'f', 2, "1230000000.00") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'f', 3, "1230000000.001") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'f', 0, "-1230000000") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'f', 1, "-1230000000.0") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'f', 2, "-1230000000.00") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'f', 3, "-1230000000.001") == 0);

    return 0;
}


BH_UNIT_TEST(FixedRoundTrip)
{
    BH_VERIFY(roundtripString(1.0, 'f') == 0);
    BH_VERIFY(roundtripString(-1.0, 'f') == 0);
    BH_VERIFY(roundtripString(0.0, 'f') == 0);
    BH_VERIFY(roundtripString(-0.0, 'f') == 0);
    BH_VERIFY(roundtripString(3.14159, 'f') == 0);
    BH_VERIFY(roundtripString(-3.14159, 'f') == 0);
    BH_VERIFY(roundtripString(123000000.0, 'f') == 0);
    BH_VERIFY(roundtripString(-123000000.0, 'f') == 0);
    BH_VERIFY(roundtripString(0.81, 'f') == 0);
    BH_VERIFY(roundtripString(-0.81, 'f') == 0);
    BH_VERIFY(roundtripString(0.81, 'f') == 0);
    BH_VERIFY(roundtripString(-0.81, 'f') == 0);
    BH_VERIFY(roundtripString(144115188075855877.0, 'f') == 0);
    BH_VERIFY(roundtripString(-144115188075855877.0, 'f') == 0);
    BH_VERIFY(roundtripString(DBL_MIN, 'f') == 0);
    BH_VERIFY(roundtripString(-DBL_MIN, 'f') == 0);
    BH_VERIFY(roundtripString(DBL_MAX, 'f') == 0);
    BH_VERIFY(roundtripString(-DBL_MAX, 'f') == 0);

    return 0;
}


BH_UNIT_TEST(ScientificFormat)
{
    BH_VERIFY(compareString(30.0159265358979323846, 'e', 0, "3e+01") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'e', 1, "3.0e+01") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'e', 2, "3.00e+01") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'e', 3, "3.002e+01") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'e', 4, "3.0016e+01") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'e', 5, "3.00159e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'e', 0, "-3e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'e', 1, "-3.0e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'e', 2, "-3.00e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'e', 3, "-3.002e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'e', 4, "-3.0016e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'e', 5, "-3.00159e+01") == 0);

    BH_VERIFY(compareString(0.0, 'e', 0, "0e+00") == 0);
    BH_VERIFY(compareString(0.0, 'e', 1, "0.0e+00") == 0);
    BH_VERIFY(compareString(-0.0, 'e', 0, "-0e+00") == 0);
    BH_VERIFY(compareString(-0.0, 'e', 1, "-0.0e+00") == 0);

    BH_VERIFY(compareString(0.00015425, 'e', 0, "2e-04") == 0);
    BH_VERIFY(compareString(0.00015425, 'e', 1, "1.5e-04") == 0);
    BH_VERIFY(compareString(0.00015425, 'e', 2, "1.54e-04") == 0);
    BH_VERIFY(compareString(0.00015425, 'e', 3, "1.543e-04") == 0);
    BH_VERIFY(compareString(0.00015425, 'e', 4, "1.5425e-04") == 0);
    BH_VERIFY(compareString(0.00015425, 'e', 5, "1.54250e-04") == 0);
    BH_VERIFY(compareString(-0.00015425, 'e', 0, "-2e-04") == 0);
    BH_VERIFY(compareString(-0.00015425, 'e', 1, "-1.5e-04") == 0);
    BH_VERIFY(compareString(-0.00015425, 'e', 2, "-1.54e-04") == 0);
    BH_VERIFY(compareString(-0.00015425, 'e', 3, "-1.543e-04") == 0);
    BH_VERIFY(compareString(-0.00015425, 'e', 4, "-1.5425e-04") == 0);
    BH_VERIFY(compareString(-0.00015425, 'e', 5, "-1.54250e-04") == 0);

    BH_VERIFY(compareString(1234567.1234, 'e', 0, "1e+06") == 0);
    BH_VERIFY(compareString(-1234567.1234, 'e', 0, "-1e+06") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'e', 0, "1e+09") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'e', 1, "1.2e+09") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'e', 2, "1.23e+09") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'e', 3, "1.230e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'e', 0, "-1e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'e', 1, "-1.2e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'e', 2, "-1.23e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'e', 3, "-1.230e+09") == 0);

    return 0;
}


BH_UNIT_TEST(ShortestFormat)
{
    BH_VERIFY(compareString(30.0159265358979323846, 'g', 0, "3e+01") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'g', 1, "3e+01") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'g', 2, "30") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'g', 3, "30") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'g', 4, "30.02") == 0);
    BH_VERIFY(compareString(30.0159265358979323846, 'g', 5, "30.016") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'g', 0, "-3e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'g', 1, "-3e+01") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'g', 2, "-30") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'g', 3, "-30") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'g', 4, "-30.02") == 0);
    BH_VERIFY(compareString(-30.0159265358979323846, 'g', 5, "-30.016") == 0);

    BH_VERIFY(compareString(0.0, 'g', 0, "0") == 0);
    BH_VERIFY(compareString(0.0, 'g', 1, "0") == 0);
    BH_VERIFY(compareString(-0.0, 'g', 0, "-0") == 0);
    BH_VERIFY(compareString(-0.0, 'g', 1, "-0") == 0);

    BH_VERIFY(compareString(0.00015425, 'g', 0, "0.0002") == 0);
    BH_VERIFY(compareString(0.00015425, 'g', 1, "0.0002") == 0);
    BH_VERIFY(compareString(0.00015425, 'g', 2, "0.00015") == 0);
    BH_VERIFY(compareString(0.00015425, 'g', 3, "0.000154") == 0);
    BH_VERIFY(compareString(0.00015425, 'g', 4, "0.0001543") == 0);
    BH_VERIFY(compareString(0.00015425, 'g', 5, "0.00015425") == 0);
    BH_VERIFY(compareString(-0.00015425, 'g', 0, "-0.0002") == 0);
    BH_VERIFY(compareString(-0.00015425, 'g', 1, "-0.0002") == 0);
    BH_VERIFY(compareString(-0.00015425, 'g', 2, "-0.00015") == 0);
    BH_VERIFY(compareString(-0.00015425, 'g', 3, "-0.000154") == 0);
    BH_VERIFY(compareString(-0.00015425, 'g', 4, "-0.0001543") == 0);
    BH_VERIFY(compareString(-0.00015425, 'g', 5, "-0.00015425") == 0);

    BH_VERIFY(compareString(1234567.1234, 'g', 0, "1e+06") == 0);
    BH_VERIFY(compareString(-1234567.1234, 'g', 0, "-1e+06") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'g', 0, "1e+09") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'g', 1, "1e+09") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'g', 2, "1.2e+09") == 0);
    BH_VERIFY(compareString(1230000000.00123, 'g', 3, "1.23e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'g', 0, "-1e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'g', 1, "-1e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'g', 2, "-1.2e+09") == 0);
    BH_VERIFY(compareString(-1230000000.00123, 'g', 3, "-1.23e+09") == 0);
    BH_VERIFY(compareString(144115188075855877.0, 'g', 17, "1.4411518807585587e+17") == 0);
    BH_VERIFY(compareString(-144115188075855877.0, 'g', 17, "-1.4411518807585587e+17") == 0);

    return 0;
}


BH_UNIT_TEST(ScientificRoundTrip)
{
    BH_VERIFY(roundtripString(1.0, 'e') == 0);
    BH_VERIFY(roundtripString(-1.0, 'e') == 0);
    BH_VERIFY(roundtripString(0.0, 'e') == 0);
    BH_VERIFY(roundtripString(-0.0, 'e') == 0);
    BH_VERIFY(roundtripString(3.14159, 'e') == 0);
    BH_VERIFY(roundtripString(-3.14159, 'e') == 0);
    BH_VERIFY(roundtripString(123000000.0, 'e') == 0);
    BH_VERIFY(roundtripString(-123000000.0, 'e') == 0);
    BH_VERIFY(roundtripString(0.81, 'e') == 0);
    BH_VERIFY(roundtripString(-0.81, 'e') == 0);
    BH_VERIFY(roundtripString(0.81, 'e') == 0);
    BH_VERIFY(roundtripString(-0.81, 'e') == 0);
    BH_VERIFY(roundtripString(144115188075855877.0, 'e') == 0);
    BH_VERIFY(roundtripString(-144115188075855877.0, 'e') == 0);
    BH_VERIFY(roundtripString(DBL_MIN, 'e') == 0);
    BH_VERIFY(roundtripString(-DBL_MIN, 'e') == 0);
    BH_VERIFY(roundtripString(DBL_MAX, 'e') == 0);
    BH_VERIFY(roundtripString(-DBL_MAX, 'e') == 0);

    return 0;
}


BH_UNIT_TEST(ShortestRoundTrip)
{
    BH_VERIFY(roundtripString(1.0, 'g') == 0);
    BH_VERIFY(roundtripString(-1.0, 'g') == 0);
    BH_VERIFY(roundtripString(0.0, 'g') == 0);
    BH_VERIFY(roundtripString(-0.0, 'g') == 0);
    BH_VERIFY(roundtripString(3.14159, 'g') == 0);
    BH_VERIFY(roundtripString(-3.14159, 'g') == 0);
    BH_VERIFY(roundtripString(123000000.0, 'g') == 0);
    BH_VERIFY(roundtripString(-123000000.0, 'g') == 0);
    BH_VERIFY(roundtripString(0.81, 'g') == 0);
    BH_VERIFY(roundtripString(-0.81, 'g') == 0);
    BH_VERIFY(roundtripString(0.81, 'g') == 0);
    BH_VERIFY(roundtripString(-0.81, 'g') == 0);
    BH_VERIFY(roundtripString(144115188075855877.0, 'g') == 0);
    BH_VERIFY(roundtripString(-144115188075855877.0, 'g') == 0);
    BH_VERIFY(roundtripString(DBL_MIN, 'g') == 0);
    BH_VERIFY(roundtripString(-DBL_MIN, 'g') == 0);
    BH_VERIFY(roundtripString(DBL_MAX, 'g') == 0);
    BH_VERIFY(roundtripString(-DBL_MAX, 'g') == 0);

    return 0;
}


BH_UNIT_TEST(Parity)
{
    char buffer[16], output[2000];
    uint64_t frac;
    double value;
    int i, j, k;

    for (i = 0; i < 100; i++)
    {
        frac = (rand() & 0x7FFF);
        frac = (frac << 15) | (rand() & 0x7FFF);
        frac = (frac << 15) | (rand() & 0x7FFF);
        frac = (frac << 15) | (rand() & 0x7FFF);

        for (j = 0; j < 100; j++)
        {
            value = frac * pow(2, (rand() % 2046) - 1024);

            for (k = 0; k < 18; k++)
            {
                char *str;

                sprintf(buffer, "%%.%dg", k);
                str = BH_StringFromDouble(value, 'g', k);
                sprintf(output, buffer, value);

                if (strcmp(str, output))
                {
                    printf("(%.17g) (%d) %s vs %s\n", value, k, str, output);
                    BH_FAIL("Strings aren't equal");
                }
                BH_StringFree(str);
            }
        }
    }

    return 0;
}


BH_UNIT_TEST(ToDouble)
{
    size_t size;

    BH_VERIFY(BH_ClassifyDouble(BH_StringToDouble("  INFa  ", &size)) == BH_FP_INFINITE);
    BH_VERIFY(size == 5);
    BH_VERIFY(BH_ClassifyDouble(BH_StringToDouble("  INFINITYc  ", &size)) == BH_FP_INFINITE);
    BH_VERIFY(size == 10);

    BH_VERIFY(BH_ClassifyDouble(BH_StringToDouble("  -INFb  ", &size)) == (BH_FP_INFINITE | BH_FP_NEGATIVE));
    BH_VERIFY(size == 6);
    BH_VERIFY(BH_ClassifyDouble(BH_StringToDouble("  -INFINITYd  ", &size)) == (BH_FP_INFINITE | BH_FP_NEGATIVE));
    BH_VERIFY(size == 11);

    BH_VERIFY(BH_ClassifyDouble(BH_StringToDouble("  NANe  ", &size)) == BH_FP_NAN);
    BH_VERIFY(size == 5);

    BH_VERIFY_DELTA(BH_StringToDouble("  1234.0312f  ", &size), 1234.0312, 0.00001);
    BH_VERIFY(size == 11);

    BH_VERIFY_DELTA(BH_StringToDouble("  3.14159g  ", &size), 3.14159, 0.00001);
    BH_VERIFY(size == 9);

    BH_VERIFY(BH_StringToDouble("  h  ", &size) == 0.0);
    BH_VERIFY(size == 0);

    BH_VERIFY(BH_StringToDouble("  0  ", &size) == 0.0);
    BH_VERIFY(size == 3);

    BH_VERIFY(BH_StringToDouble("  0.0  ", &size) == 0.0);
    BH_VERIFY(size == 5);

    BH_VERIFY(BH_StringToDouble("  0.  ", &size) == 0.0);
    BH_VERIFY(size == 4);

    BH_VERIFY(BH_StringToDouble("  .0  ", &size) == 0.0);
    BH_VERIFY(size == 4);

    BH_VERIFY(BH_StringToDouble("  .Hello  ", &size) == 0.0);
    BH_VERIFY(size == 0);

    BH_VERIFY(BH_StringToDouble("  .E12  ", &size) == 0.0);
    BH_VERIFY(size == 0);

    return 0;
}


int main(int argc, char **argv)
{
    BH_UNUSED(argc);
    BH_UNUSED(argv);

    BH_UNIT_ADD(FixedFormat);
    BH_UNIT_ADD(FixedRoundTrip);
    BH_UNIT_ADD(ScientificFormat);
    BH_UNIT_ADD(ScientificRoundTrip);
    BH_UNIT_ADD(ShortestFormat);
    BH_UNIT_ADD(ShortestRoundTrip);
    BH_UNIT_ADD(Parity);
    BH_UNIT_ADD(ToDouble);

    return BH_UnitRun();
}