Skip to content

Commit 5584dd1

Browse files
authored
Refactor library_int53.js test suite to ease adding more tests to it. (#16865)
* Refactor library_int53.js test suite to ease adding more tests to it. Add rebaselining support to test_int53. * Address review
1 parent 69acf8f commit 5584dd1

File tree

4 files changed

+232
-176
lines changed

4 files changed

+232
-176
lines changed

tests/core/test_int53.c

Lines changed: 45 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,57 @@
11
#ifdef __EMSCRIPTEN__
22
#include <emscripten.h>
33
#endif
4-
#include <stdint.h>
5-
#include <stdio.h>
6-
#include <float.h>
7-
#include <math.h>
84

9-
#include <time.h>
5+
#include "test_int53.h"
6+
7+
#include <stdio.h>
108
#include <stdlib.h>
9+
#include <time.h>
1110

1211
// Uncomment to compute the expected result:
13-
//#define ANSWERS
12+
//#define GENERATE_ANSWERS
1413

1514
void writeI53ToI64_int64(int64_t *heapAddress, int64_t num) {
16-
#ifdef ANSWERS
15+
#ifdef GENERATE_ANSWERS
1716
*heapAddress = num;
1817
#else
1918
EM_ASM(writeI53ToI64($0, $1), heapAddress, (double)num);
2019
#endif
2120
}
2221

2322
void writeI53ToI64_double(int64_t *heapAddress, double num) {
24-
#ifdef ANSWERS
25-
*heapAddress = (int64_t)num;
23+
#ifdef GENERATE_ANSWERS
24+
if (num > 0 || num <= -9223372036854775808.0 /* underflow, garbage in-garbage out situation: just produce a value that matches current JS impl*/)
25+
*(uint64_t*)heapAddress = (uint64_t)num;
26+
else
27+
*heapAddress = (int64_t)num;
2628
#else
2729
EM_ASM(writeI53ToI64($0, $1), heapAddress, num);
2830
#endif
2931
}
3032

3133
void writeI53ToI64Clamped_double(int64_t *heapAddress, double num) {
32-
#ifdef ANSWERS
33-
*heapAddress = (int64_t)num;
34+
#ifdef GENERATE_ANSWERS
35+
if (num >= 9223372036854775808.0)
36+
*heapAddress = 0x7FFFFFFFFFFFFFFFLL;
37+
else if (num <= -9223372036854775808.0)
38+
*heapAddress = -0x8000000000000000LL;
39+
else if (num > 0)
40+
*(uint64_t*)heapAddress = (uint64_t)num;
41+
else
42+
*heapAddress = (int64_t)num;
3443
#else
3544
EM_ASM(writeI53ToI64Clamped($0, $1), heapAddress, num);
3645
#endif
3746
}
3847

3948
void writeI53ToI64Signaling_double(int64_t *heapAddress, double num) {
40-
#ifdef ANSWERS
41-
*heapAddress = (int64_t)num;
49+
#ifdef GENERATE_ANSWERS
50+
if (num <= -9223372036854775808.0 || num >= 9223372036854775808.0) {
51+
*heapAddress = 0x0102030401020304ULL;
52+
} else {
53+
*heapAddress = (int64_t)num;
54+
}
4255
#else
4356
EM_ASM(try {
4457
writeI53ToI64Signaling($0, $1)
@@ -50,16 +63,25 @@ void writeI53ToI64Signaling_double(int64_t *heapAddress, double num) {
5063
}
5164

5265
void writeI53ToU64Clamped_double(uint64_t *heapAddress, double num) {
53-
#ifdef ANSWERS
54-
*heapAddress = (uint64_t)num;
66+
#ifdef GENERATE_ANSWERS
67+
if (num >= 18446744073709551616.0)
68+
*heapAddress = 0xFFFFFFFFFFFFFFFFULL;
69+
else if (num < 0)
70+
*heapAddress = 0;
71+
else
72+
*heapAddress = (uint64_t)num;
5573
#else
5674
EM_ASM(writeI53ToU64Clamped($0, $1), heapAddress, num);
5775
#endif
5876
}
5977

6078
void writeI53ToU64Signaling_double(uint64_t *heapAddress, double num) {
61-
#ifdef ANSWERS
62-
*heapAddress = (uint64_t)num;
79+
#ifdef GENERATE_ANSWERS
80+
if (num < 0 || num >= 18446744073709551616.0) {
81+
*heapAddress = 0x0102030401020304ULL;
82+
} else {
83+
*heapAddress = (uint64_t)num;
84+
}
6385
#else
6486
EM_ASM(try {
6587
writeI53ToU64Signaling($0, $1)
@@ -71,7 +93,7 @@ void writeI53ToU64Signaling_double(uint64_t *heapAddress, double num) {
7193
}
7294

7395
int64_t readI53FromI64_toInt64(int64_t *heapAddress) {
74-
#ifdef ANSWERS
96+
#ifdef GENERATE_ANSWERS
7597
return *heapAddress;
7698
#else
7799
return (int64_t)EM_ASM_DOUBLE(return readI53FromI64($0), heapAddress);
@@ -80,31 +102,31 @@ int64_t readI53FromI64_toInt64(int64_t *heapAddress) {
80102

81103
double readI53FromI64(int64_t *heapAddress)
82104
{
83-
#ifdef ANSWERS
105+
#ifdef GENERATE_ANSWERS
84106
return (double)*heapAddress;
85107
#else
86108
return EM_ASM_DOUBLE(return readI53FromI64($0), heapAddress);
87109
#endif
88110
}
89111

90112
int64_t readI53FromU64_toInt64(uint64_t *heapAddress) {
91-
#ifdef ANSWERS
113+
#ifdef GENERATE_ANSWERS
92114
return (int64_t)*heapAddress;
93115
#else
94116
return (int64_t)EM_ASM_DOUBLE(return readI53FromU64($0), heapAddress);
95117
#endif
96118
}
97119

98120
double readI53FromU64(uint64_t *heapAddress) {
99-
#ifdef ANSWERS
121+
#ifdef GENERATE_ANSWERS
100122
return (double)*heapAddress;
101123
#else
102124
return EM_ASM_DOUBLE(return readI53FromU64($0), heapAddress);
103125
#endif
104126
}
105127

106128
int64_t convertI32PairToI53(int32_t lo, int32_t hi) {
107-
#ifdef ANSWERS
129+
#ifdef GENERATE_ANSWERS
108130
uint64_t val = (uint32_t)lo;
109131
val |= ((uint64_t)(uint32_t)hi) << 32;
110132
return (int64_t)val;
@@ -114,7 +136,7 @@ int64_t convertI32PairToI53(int32_t lo, int32_t hi) {
114136
}
115137

116138
int64_t convertU32PairToI53(uint32_t lo, uint32_t hi) {
117-
#ifdef ANSWERS
139+
#ifdef GENERATE_ANSWERS
118140
uint64_t val = (uint32_t)lo;
119141
val |= ((uint64_t)(uint32_t)hi) << 32;
120142
return val;
@@ -155,158 +177,6 @@ uint64_t testReadWriteU64AsI53(uint64_t num) {
155177
}
156178

157179
int main() {
158-
// We can subdivide the set of all possible double precision floating point
159-
// numbers + 64-bit (u)int numbers to eight categories:
160-
// 1. Lossless integers: numbers that are precisely representable by both a
161-
// double and 64-bit signed integer, and all numbers smaller in abs value are
162-
// also precisely representable.
163-
// I.e. numbers [-2^53, 2^53] (inclusive)
164-
const uint64_t losslessIntegers[] = {
165-
0,
166-
1,
167-
2,
168-
3,
169-
0x0FFFFFFu,
170-
0x1000000u, // == 16777216, largest consecutive single-precision floating point number
171-
0x1000001u,
172-
0x01020304u,
173-
0x7FFFFFFFu,
174-
0x80000000u,
175-
0x90000000u,
176-
0xFFFFFFFFu,
177-
0x100000000ull,
178-
0x100000001ull,
179-
0x17FFFFFFFull,
180-
0x180000000ull,
181-
0xFFFFFFFFFull,
182-
0x10203000000000ull,
183-
0x1FFFFF00000000ull,
184-
0x1FFFFF00000001ull,
185-
0x1FFFFFFFFFFFFEull,
186-
0x1FFFFFFFFFFFFFull,
187-
0x20000000000000ull, // 9,007,199,254,740,992, largest consecutive double-precision floating point number
188-
};
189-
190-
// 2. Precise integers: numbers that are precisely representable by both a
191-
// double and 64-bit unsigned integer, but their neighboring numbers are
192-
// not. E.g.
193-
// E.g. 9223372036854775808 == 0x8000000000000000ull and
194-
// 18,446,744,073,709,549,568 == 0xfffffffffffff800ull are integer numbers
195-
// representable as both double and 64-bit uint.
196-
const uint64_t preciseUnsignedIntegers[] = {
197-
0x8000000000000000ull, // 9,223,372,036,854,775,808, a number around the sign point of int64_t, representable as double
198-
// Disabled for now, this is not converting consistently in different build modes.
199-
//0x8000000000000800ull, // 9,223,372,036,854,777,856, a number around the sign point of int64_t, representable as double (however conversion to this is not possible due to precision issues)
200-
0x25F5BDA103AA08ull, // 10684768937290248
201-
0x3F3837D5442494ull, // 17794735985140884
202-
0x55B4ACAE7DC2A0ull, // 24124026775257760
203-
0x72BDFA99BF28A8ull, // 32297031363930280
204-
0xA4055CD86A9F40ull, // 46167792506543936
205-
0x125AFCA30078D10ull, // 82665451100278032
206-
0x1268C844FE925C0ull, // 82908143057184192
207-
0x12A1DB1454D02A0ull, // 83912190268867232
208-
0x13E8D61ECEA80C0ull, // 89664494320124096
209-
0x1881B7DBD49D3D0ull, // 110368417731171280
210-
0xFE73E98A5E93F00ull, // 1145953455528558336
211-
0x2A44DB9E56754000ull, // 3045800721111138304
212-
0x7FFFFFFFFFFFFC00ull, // 9,223,372,036,854,774,784, a number around the sign point of int64_t, representable as double
213-
// Disabled for now, the following do not convert consistently in different build modes.
214-
// 0x9C04E99FFB426800ull, // 11242367443148105728
215-
// 0xB1BEDE55F1E6B000ull, // 12807918851000283136
216-
// 0xE762A64DFB28E800ull, // 16673071624335452160
217-
// 0xFFFFFFFFFFFFF800ull, // 18,446,744,073,709,549,568, largest integer that is representable as both a double and a uint64_t. (however conversion to this is not possible due to precision issues) (-2048 as int64)
218-
};
219-
220-
// 3. Precise negative integers: numbers that are precisely representable by
221-
// both a double and 64-bit signed integer, but their neighboring numbers are
222-
// not.
223-
const int64_t preciseNegativeIntegers[] = {
224-
0xFFD32C4AC85FB1AEll, // -12617674251062866
225-
0xFF3A4C372D2373A8ll, // -55648245524499544
226-
0xFF15853220D118D0ll, // -66000169181570864
227-
0xFE555489B4E3E2D0ll, // -120096864633363760
228-
0xFAFD5B94D7646780ll, // -361031700292802688
229-
0xF838033421CB9A40ll, // -560694631167452608
230-
0xD310CE1F89FC2200ll, // -3237861497225076224
231-
0xCA6ACDC11C161C00ll, // -3861047501233185792
232-
0xAF6178DCAFF5A800ll, // -5809229155090978816
233-
0x9AFE3153D877A400ll, // -7278325711600376832
234-
0x8B7B357A4C942C00ll, // -8396058280915096576
235-
};
236-
237-
// 4. Imprecise unsigned integers: Numbers representable by a 64-bit uint, but
238-
// not representable in a double, so a rounding error occurs with uint64_t
239-
// -> double -> uint64_t conversion.
240-
// I.e. numbers [2^53+1, 2^64-1] for uint64 that are not representable as a
241-
// double. E.g. 0xffffffffffffffffull == 18,446,744,073,709,551,615 cannot
242-
// be stored in a double.
243-
const uint64_t impreciseUnsignedIntegers[] = {
244-
0x1C4FD83EC4ABAEEull, // 127505432520080110 error -2
245-
0x6A89C715876E7CCull, // 479805370944382924 error 12
246-
0xA4ABE649588F1E0ull, // 741614427870654944 error -32
247-
0xC980AC53EFE9DFCull, // 907487167196863996 error -4
248-
0x1860F52F16D4DA11ull, // 1756673437269809681 error 17
249-
0x198BF5B92CEFC68Dull, // 1840835048382645901 error -115
250-
0x2A02A453407B9F26ull, // 3027162577017478950 error -218
251-
0x36B24960B42D38E5ull, // 3941293303591155941 error 229
252-
0x702767EAC6668103ull, // 8081542314388259075 error 259
253-
0x80D1029A15D7ADAEull, // 9282203167801978286 error -594
254-
0x91604C04718E9B6Dull, // 10475456315232525165 error 877
255-
0xB4B9C5F0621A4DD9ull, // 13022657433747213785 error -551
256-
0xC138364191D593EBull, // 13922937903263355883 error 1003
257-
0xC7B40DCF0DBA8958ull, // 14390141892295297368 error 344
258-
0xF297E30AE976BAE9ull, // 17480690114667920105 error 745
259-
0xFAEA007C9BD7F40Dull, // 18080264189222843405 error -1011
260-
0xFBB8A15D8F62FC95ull, // 18138424922444332181 error -875
261-
0xFFFFFFFFFFFFFFFFull // 18,446,744,073,709,551,615, largest uint64 integer. (-1 as int64)
262-
};
263-
264-
// 5. Imprecise negative integers: Numbers representable by a 64-bit int, but
265-
// not representable in a double, so a rounding error occurs with int64_t ->
266-
// double -> int64_t conversion.
267-
// I.e. numbers [-2^63, -2^53-1] for int64 that are not representable as a double.
268-
const int64_t impreciseNegativeIntegers[] = {
269-
0xFE23F334576C950Ell, // -133996157760400114 error -2
270-
0xFCD4520C047DF684ll, // -228467469520603516 error 4
271-
0xFC33BD80FF0149B0ll, // -273666790607730256 error -16
272-
0xEF76BD16E384CA04ll, // -1191557145388856828 error 4
273-
0xEDFB655E2E82185Fll, // -1298332612384647073 error 95
274-
0xE4643C51E609E373ll, // -1989398812941491341 error 115
275-
0xD121A4BE92C4A969ll, // -3377237107138057879 error -151
276-
0xB53BA491A205DFDAll, // -5387531583823159334 error -38
277-
0x9592DF0A9FA4AEE9ll, // -7668821978737496343 error -279
278-
0x9027EEEFCC17CE38ll, // -8059210294467506632 error -456
279-
0x8818DC364AF41065ll, // -8639913759366442907 error 101
280-
};
281-
282-
const double otherDoubles[] = {
283-
// 6. Rational numbers within range: double precision fractional numbers
284-
// that are within [-2^63, 2^63-1] for int64 and [0, 2^64-1] for uint64, but
285-
// not integers.
286-
DBL_TRUE_MIN, // smallest positive double (unnormalized)
287-
DBL_MIN, // smallest normalized positive double
288-
DBL_EPSILON, // smallest positive double so that 1+e != e
289-
0.1,
290-
0.25,
291-
0.5,
292-
0.75,
293-
1.912606627916564328,
294-
2.7463697084735994025,
295-
150655528000.36105347,
296-
679247267523850.5,
297-
967873430891084.25,
298-
1913278962515964.5,
299-
300-
// 7. Out of range numbers: Double precision numbers >= 2^64 and < -2^63,
301-
// i.e. they don't fit within an int64/uint64 range.
302-
DBL_MAX, // largest noninfinite double
303-
INFINITY, // +inf
304-
305-
// 8. NaNs:
306-
// NAN
307-
// Ignoring payloaded NaNs for now.
308-
};
309-
310180
printf("Testing positive losslessIntegers:\n");
311181
for (int i = 0; i < sizeof(losslessIntegers) / sizeof(losslessIntegers[0]); ++i) {
312182
uint64_t num = losslessIntegers[i];

0 commit comments

Comments
 (0)