1//! These tests are adapted from the Rust core library's unittests.
2
3#![cfg(not(feature = "compact"))]
4
5use minimal_lexical::lemire;
6use minimal_lexical::num::Float;
7
8fn compute_error32(q: i32, w: u64) -> (i32, u64) {
9    let fp = lemire::compute_error::<f32>(q, w);
10    (fp.exp, fp.mant)
11}
12
13fn compute_error64(q: i32, w: u64) -> (i32, u64) {
14    let fp = lemire::compute_error::<f64>(q, w);
15    (fp.exp, fp.mant)
16}
17
18fn compute_error_scaled32(q: i32, w: u64, lz: i32) -> (i32, u64) {
19    let fp = lemire::compute_error_scaled::<f32>(q, w, lz);
20    (fp.exp, fp.mant)
21}
22
23fn compute_error_scaled64(q: i32, w: u64, lz: i32) -> (i32, u64) {
24    let fp = lemire::compute_error_scaled::<f64>(q, w, lz);
25    (fp.exp, fp.mant)
26}
27
28fn compute_float32(q: i32, w: u64) -> (i32, u64) {
29    let fp = lemire::compute_float::<f32>(q, w);
30    (fp.exp, fp.mant)
31}
32
33fn compute_float64(q: i32, w: u64) -> (i32, u64) {
34    let fp = lemire::compute_float::<f64>(q, w);
35    (fp.exp, fp.mant)
36}
37
38#[test]
39fn compute_error32_test() {
40    // These test near-halfway cases for single-precision floats.
41    assert_eq!(compute_error32(0, 16777216), (111 + f32::INVALID_FP, 9223372036854775808));
42    assert_eq!(compute_error32(0, 16777217), (111 + f32::INVALID_FP, 9223372586610589696));
43    assert_eq!(compute_error32(0, 16777218), (111 + f32::INVALID_FP, 9223373136366403584));
44    assert_eq!(compute_error32(0, 16777219), (111 + f32::INVALID_FP, 9223373686122217472));
45    assert_eq!(compute_error32(0, 16777220), (111 + f32::INVALID_FP, 9223374235878031360));
46
47    // These are examples of the above tests, with
48    // digits from the exponent shifted to the mantissa.
49    assert_eq!(
50        compute_error32(-10, 167772160000000000),
51        (111 + f32::INVALID_FP, 9223372036854775808)
52    );
53    assert_eq!(
54        compute_error32(-10, 167772170000000000),
55        (111 + f32::INVALID_FP, 9223372586610589696)
56    );
57    assert_eq!(
58        compute_error32(-10, 167772180000000000),
59        (111 + f32::INVALID_FP, 9223373136366403584)
60    );
61    // Let's check the lines to see if anything is different in table...
62    assert_eq!(
63        compute_error32(-10, 167772190000000000),
64        (111 + f32::INVALID_FP, 9223373686122217472)
65    );
66    assert_eq!(
67        compute_error32(-10, 167772200000000000),
68        (111 + f32::INVALID_FP, 9223374235878031360)
69    );
70}
71
72#[test]
73fn compute_error64_test() {
74    // These test near-halfway cases for double-precision floats.
75    assert_eq!(compute_error64(0, 9007199254740992), (1065 + f64::INVALID_FP, 9223372036854775808));
76    assert_eq!(compute_error64(0, 9007199254740993), (1065 + f64::INVALID_FP, 9223372036854776832));
77    assert_eq!(compute_error64(0, 9007199254740994), (1065 + f64::INVALID_FP, 9223372036854777856));
78    assert_eq!(compute_error64(0, 9007199254740995), (1065 + f64::INVALID_FP, 9223372036854778880));
79    assert_eq!(compute_error64(0, 9007199254740996), (1065 + f64::INVALID_FP, 9223372036854779904));
80    assert_eq!(
81        compute_error64(0, 18014398509481984),
82        (1066 + f64::INVALID_FP, 9223372036854775808)
83    );
84    assert_eq!(
85        compute_error64(0, 18014398509481986),
86        (1066 + f64::INVALID_FP, 9223372036854776832)
87    );
88    assert_eq!(
89        compute_error64(0, 18014398509481988),
90        (1066 + f64::INVALID_FP, 9223372036854777856)
91    );
92    assert_eq!(
93        compute_error64(0, 18014398509481990),
94        (1066 + f64::INVALID_FP, 9223372036854778880)
95    );
96    assert_eq!(
97        compute_error64(0, 18014398509481992),
98        (1066 + f64::INVALID_FP, 9223372036854779904)
99    );
100
101    // Test a much closer set of examples.
102    assert_eq!(
103        compute_error64(0, 9007199254740991),
104        (1064 + f64::INVALID_FP, 18446744073709549568)
105    );
106    assert_eq!(
107        compute_error64(0, 9223372036854776831),
108        (1075 + f64::INVALID_FP, 9223372036854776830)
109    );
110    assert_eq!(
111        compute_error64(0, 9223372036854776832),
112        (1075 + f64::INVALID_FP, 9223372036854776832)
113    );
114    assert_eq!(
115        compute_error64(0, 9223372036854776833),
116        (1075 + f64::INVALID_FP, 9223372036854776832)
117    );
118    assert_eq!(
119        compute_error64(-42, 9123456727292927),
120        (925 + f64::INVALID_FP, 13021432563531497894)
121    );
122    assert_eq!(
123        compute_error64(-43, 91234567272929275),
124        (925 + f64::INVALID_FP, 13021432563531498606)
125    );
126    assert_eq!(
127        compute_error64(-42, 9123456727292928),
128        (925 + f64::INVALID_FP, 13021432563531499320)
129    );
130
131    // These are examples of the above tests, with
132    // digits from the exponent shifted to the mantissa.
133    assert_eq!(
134        compute_error64(-3, 9007199254740992000),
135        (1065 + f64::INVALID_FP, 9223372036854775808)
136    );
137    assert_eq!(
138        compute_error64(-3, 9007199254740993000),
139        (1065 + f64::INVALID_FP, 9223372036854776832)
140    );
141    assert_eq!(
142        compute_error64(-3, 9007199254740994000),
143        (1065 + f64::INVALID_FP, 9223372036854777856)
144    );
145    assert_eq!(
146        compute_error64(-3, 9007199254740995000),
147        (1065 + f64::INVALID_FP, 9223372036854778880)
148    );
149    assert_eq!(
150        compute_error64(-3, 9007199254740996000),
151        (1065 + f64::INVALID_FP, 9223372036854779904)
152    );
153
154    // Test from errors in atof.
155    assert_eq!(
156        compute_error64(-18, 1000000178813934326),
157        (1012 + f64::INVALID_FP, 9223373686122217470)
158    );
159
160    // Check edge-cases from previous errors.
161    assert_eq!(
162        compute_error64(-342, 2470328229206232720),
163        (-64 + f64::INVALID_FP, 18446744073709551608)
164    );
165}
166
167#[test]
168fn compute_error_scaled32_test() {
169    // These are the same examples above, just using pre-computed scaled values.
170
171    // These test near-halfway cases for single-precision floats.
172    assert_eq!(
173        compute_error_scaled32(0, 4611686018427387904, 39),
174        (111 + f32::INVALID_FP, 9223372036854775808)
175    );
176    assert_eq!(
177        compute_error_scaled32(0, 4611686293305294848, 39),
178        (111 + f32::INVALID_FP, 9223372586610589696)
179    );
180    assert_eq!(
181        compute_error_scaled32(0, 4611686568183201792, 39),
182        (111 + f32::INVALID_FP, 9223373136366403584)
183    );
184    assert_eq!(
185        compute_error_scaled32(0, 4611686843061108736, 39),
186        (111 + f32::INVALID_FP, 9223373686122217472)
187    );
188    assert_eq!(
189        compute_error_scaled32(0, 4611687117939015680, 39),
190        (111 + f32::INVALID_FP, 9223374235878031360)
191    );
192
193    assert_eq!(
194        compute_error_scaled32(-10, 9223372036854775808, 6),
195        (111 + f32::INVALID_FP, 9223372036854775808)
196    );
197    assert_eq!(
198        compute_error_scaled32(-10, 9223372586610589696, 6),
199        (111 + f32::INVALID_FP, 9223372586610589696)
200    );
201    assert_eq!(
202        compute_error_scaled32(-10, 9223373136366403584, 6),
203        (111 + f32::INVALID_FP, 9223373136366403584)
204    );
205    assert_eq!(
206        compute_error_scaled32(-10, 9223373686122217472, 6),
207        (111 + f32::INVALID_FP, 9223373686122217472)
208    );
209    assert_eq!(
210        compute_error_scaled32(-10, 9223374235878031360, 6),
211        (111 + f32::INVALID_FP, 9223374235878031360)
212    );
213}
214
215#[test]
216fn compute_error_scaled64_test() {
217    // These are the same examples above, just using pre-computed scaled values.
218
219    // These test near-halfway cases for double-precision floats.
220    assert_eq!(
221        compute_error_scaled64(0, 4611686018427387904, 10),
222        (1065 + f64::INVALID_FP, 9223372036854775808)
223    );
224    assert_eq!(
225        compute_error_scaled64(0, 4611686018427388416, 10),
226        (1065 + f64::INVALID_FP, 9223372036854776832)
227    );
228    assert_eq!(
229        compute_error_scaled64(0, 4611686018427388928, 10),
230        (1065 + f64::INVALID_FP, 9223372036854777856)
231    );
232    assert_eq!(
233        compute_error_scaled64(0, 4611686018427389440, 10),
234        (1065 + f64::INVALID_FP, 9223372036854778880)
235    );
236    assert_eq!(
237        compute_error_scaled64(0, 4611686018427389952, 10),
238        (1065 + f64::INVALID_FP, 9223372036854779904)
239    );
240    assert_eq!(
241        compute_error_scaled64(0, 4611686018427387904, 9),
242        (1066 + f64::INVALID_FP, 9223372036854775808)
243    );
244    assert_eq!(
245        compute_error_scaled64(0, 4611686018427388416, 9),
246        (1066 + f64::INVALID_FP, 9223372036854776832)
247    );
248    assert_eq!(
249        compute_error_scaled64(0, 4611686018427388928, 9),
250        (1066 + f64::INVALID_FP, 9223372036854777856)
251    );
252    assert_eq!(
253        compute_error_scaled64(0, 4611686018427389440, 9),
254        (1066 + f64::INVALID_FP, 9223372036854778880)
255    );
256    assert_eq!(
257        compute_error_scaled64(0, 4611686018427389952, 9),
258        (1066 + f64::INVALID_FP, 9223372036854779904)
259    );
260
261    // Test a much closer set of examples.
262    assert_eq!(
263        compute_error_scaled64(0, 9223372036854774784, 11),
264        (1064 + f64::INVALID_FP, 18446744073709549568)
265    );
266    assert_eq!(
267        compute_error_scaled64(0, 4611686018427388415, 0),
268        (1075 + f64::INVALID_FP, 9223372036854776830)
269    );
270    assert_eq!(
271        compute_error_scaled64(0, 4611686018427388416, 0),
272        (1075 + f64::INVALID_FP, 9223372036854776832)
273    );
274    assert_eq!(
275        compute_error_scaled64(0, 4611686018427388416, 0),
276        (1075 + f64::INVALID_FP, 9223372036854776832)
277    );
278    assert_eq!(
279        compute_error_scaled64(-42, 6510716281765748947, 10),
280        (925 + f64::INVALID_FP, 13021432563531497894)
281    );
282    assert_eq!(
283        compute_error_scaled64(-43, 6510716281765749303, 7),
284        (925 + f64::INVALID_FP, 13021432563531498606)
285    );
286    assert_eq!(
287        compute_error_scaled64(-42, 6510716281765749660, 10),
288        (925 + f64::INVALID_FP, 13021432563531499320)
289    );
290
291    // These are examples of the above tests, with
292    // digits from the exponent shifted to the mantissa.
293    assert_eq!(
294        compute_error_scaled64(-3, 9223372036854775808, 1),
295        (1065 + f64::INVALID_FP, 9223372036854775808)
296    );
297    assert_eq!(
298        compute_error_scaled64(-3, 9223372036854776832, 1),
299        (1065 + f64::INVALID_FP, 9223372036854776832)
300    );
301    assert_eq!(
302        compute_error_scaled64(-3, 9223372036854777856, 1),
303        (1065 + f64::INVALID_FP, 9223372036854777856)
304    );
305    assert_eq!(
306        compute_error_scaled64(-3, 9223372036854778880, 1),
307        (1065 + f64::INVALID_FP, 9223372036854778880)
308    );
309    assert_eq!(
310        compute_error_scaled64(-3, 9223372036854779904, 1),
311        (1065 + f64::INVALID_FP, 9223372036854779904)
312    );
313
314    // Test from errors in atof.
315    assert_eq!(
316        compute_error_scaled64(-18, 9223373686122217470, 4),
317        (1012 + f64::INVALID_FP, 9223373686122217470)
318    );
319
320    // Check edge-cases from previous errors.
321    assert_eq!(
322        compute_error_scaled64(-342, 9223372036854775804, 2),
323        (-64 + f64::INVALID_FP, 18446744073709551608)
324    );
325}
326
327#[test]
328fn compute_float_f32_rounding() {
329    // These test near-halfway cases for single-precision floats.
330    assert_eq!(compute_float32(0, 16777216), (151, 0));
331    assert_eq!(compute_float32(0, 16777217), (151, 0));
332    assert_eq!(compute_float32(0, 16777218), (151, 1));
333    assert_eq!(compute_float32(0, 16777219), (151, 2));
334    assert_eq!(compute_float32(0, 16777220), (151, 2));
335
336    // These are examples of the above tests, with
337    // digits from the exponent shifted to the mantissa.
338    assert_eq!(compute_float32(-10, 167772160000000000), (151, 0));
339    assert_eq!(compute_float32(-10, 167772170000000000), (151, 0));
340    assert_eq!(compute_float32(-10, 167772180000000000), (151, 1));
341    // Let's check the lines to see if anything is different in table...
342    assert_eq!(compute_float32(-10, 167772190000000000), (151, 2));
343    assert_eq!(compute_float32(-10, 167772200000000000), (151, 2));
344}
345
346#[test]
347fn compute_float_f64_rounding() {
348    // Also need to check halfway cases **inside** that exponent range.
349
350    // These test near-halfway cases for double-precision floats.
351    assert_eq!(compute_float64(0, 9007199254740992), (1076, 0));
352    assert_eq!(compute_float64(0, 9007199254740993), (1076, 0));
353    assert_eq!(compute_float64(0, 9007199254740994), (1076, 1));
354    assert_eq!(compute_float64(0, 9007199254740995), (1076, 2));
355    assert_eq!(compute_float64(0, 9007199254740996), (1076, 2));
356    assert_eq!(compute_float64(0, 18014398509481984), (1077, 0));
357    assert_eq!(compute_float64(0, 18014398509481986), (1077, 0));
358    assert_eq!(compute_float64(0, 18014398509481988), (1077, 1));
359    assert_eq!(compute_float64(0, 18014398509481990), (1077, 2));
360    assert_eq!(compute_float64(0, 18014398509481992), (1077, 2));
361
362    // Test a much closer set of examples.
363    assert_eq!(compute_float64(0, 9007199254740991), (1075, 4503599627370495));
364    assert_eq!(compute_float64(0, 9223372036854776831), (1086, 0));
365    assert_eq!(compute_float64(0, 9223372036854776832), (1086, 0));
366    assert_eq!(compute_float64(0, 9223372036854776833), (1086, 1));
367    assert_eq!(compute_float64(-42, 9123456727292927), (936, 1854521741541368));
368    assert_eq!(compute_float64(-43, 91234567272929275), (936, 1854521741541369));
369    assert_eq!(compute_float64(-42, 9123456727292928), (936, 1854521741541369));
370
371    // These are examples of the above tests, with
372    // digits from the exponent shifted to the mantissa.
373    assert_eq!(compute_float64(-3, 9007199254740992000), (1076, 0));
374    assert_eq!(compute_float64(-3, 9007199254740993000), (1076, 0));
375    assert_eq!(compute_float64(-3, 9007199254740994000), (1076, 1));
376    assert_eq!(compute_float64(-3, 9007199254740995000), (1076, 2));
377    assert_eq!(compute_float64(-3, 9007199254740996000), (1076, 2));
378}
379