1 // Adapted from https://github.com/Alexhuszagh/rust-lexical.
2 
3 use crate::lexical::float::ExtendedFloat;
4 use crate::lexical::rounding::round_nearest_tie_even;
5 use std::{f32, f64};
6 
7 // NORMALIZE
8 
check_normalize(mant: u64, exp: i32, shift: u32, r_mant: u64, r_exp: i32)9 fn check_normalize(mant: u64, exp: i32, shift: u32, r_mant: u64, r_exp: i32) {
10     let mut x = ExtendedFloat { mant, exp };
11     assert_eq!(x.normalize(), shift);
12     assert_eq!(
13         x,
14         ExtendedFloat {
15             mant: r_mant,
16             exp: r_exp
17         }
18     );
19 }
20 
21 #[test]
normalize_test()22 fn normalize_test() {
23     // F32
24     // 0
25     check_normalize(0, 0, 0, 0, 0);
26 
27     // min value
28     check_normalize(1, -149, 63, 9223372036854775808, -212);
29 
30     // 1.0e-40
31     check_normalize(71362, -149, 47, 10043308644012916736, -196);
32 
33     // 1.0e-20
34     check_normalize(12379400, -90, 40, 13611294244890214400, -130);
35 
36     // 1.0
37     check_normalize(8388608, -23, 40, 9223372036854775808, -63);
38 
39     // 1e20
40     check_normalize(11368684, 43, 40, 12500000250510966784, 3);
41 
42     // max value
43     check_normalize(16777213, 104, 40, 18446740775174668288, 64);
44 
45     // F64
46 
47     // min value
48     check_normalize(1, -1074, 63, 9223372036854775808, -1137);
49 
50     // 1.0e-250
51     check_normalize(6448907850777164, -883, 11, 13207363278391631872, -894);
52 
53     // 1.0e-150
54     check_normalize(7371020360979573, -551, 11, 15095849699286165504, -562);
55 
56     // 1.0e-45
57     check_normalize(6427752177035961, -202, 11, 13164036458569648128, -213);
58 
59     // 1.0e-40
60     check_normalize(4903985730770844, -185, 11, 10043362776618688512, -196);
61 
62     // 1.0e-20
63     check_normalize(6646139978924579, -119, 11, 13611294676837537792, -130);
64 
65     // 1.0
66     check_normalize(4503599627370496, -52, 11, 9223372036854775808, -63);
67 
68     // 1e20
69     check_normalize(6103515625000000, 14, 11, 12500000000000000000, 3);
70 
71     // 1e40
72     check_normalize(8271806125530277, 80, 11, 16940658945086007296, 69);
73 
74     // 1e150
75     check_normalize(5503284107318959, 446, 11, 11270725851789228032, 435);
76 
77     // 1e250
78     check_normalize(6290184345309700, 778, 11, 12882297539194265600, 767);
79 
80     // max value
81     check_normalize(9007199254740991, 971, 11, 18446744073709549568, 960);
82 }
83 
84 // ROUND
85 
check_round_to_f32(mant: u64, exp: i32, r_mant: u64, r_exp: i32)86 fn check_round_to_f32(mant: u64, exp: i32, r_mant: u64, r_exp: i32) {
87     let mut x = ExtendedFloat { mant, exp };
88     x.round_to_native::<f32, _>(round_nearest_tie_even);
89     assert_eq!(
90         x,
91         ExtendedFloat {
92             mant: r_mant,
93             exp: r_exp
94         }
95     );
96 }
97 
98 #[test]
round_to_f32_test()99 fn round_to_f32_test() {
100     // This is lossy, so some of these values are **slightly** rounded.
101 
102     // underflow
103     check_round_to_f32(9223372036854775808, -213, 0, -149);
104 
105     // min value
106     check_round_to_f32(9223372036854775808, -212, 1, -149);
107 
108     // 1.0e-40
109     check_round_to_f32(10043308644012916736, -196, 71362, -149);
110 
111     // 1.0e-20
112     check_round_to_f32(13611294244890214400, -130, 12379400, -90);
113 
114     // 1.0
115     check_round_to_f32(9223372036854775808, -63, 8388608, -23);
116 
117     // 1e20
118     check_round_to_f32(12500000250510966784, 3, 11368684, 43);
119 
120     // max value
121     check_round_to_f32(18446740775174668288, 64, 16777213, 104);
122 
123     // overflow
124     check_round_to_f32(18446740775174668288, 65, 16777213, 105);
125 }
126 
check_round_to_f64(mant: u64, exp: i32, r_mant: u64, r_exp: i32)127 fn check_round_to_f64(mant: u64, exp: i32, r_mant: u64, r_exp: i32) {
128     let mut x = ExtendedFloat { mant, exp };
129     x.round_to_native::<f64, _>(round_nearest_tie_even);
130     assert_eq!(
131         x,
132         ExtendedFloat {
133             mant: r_mant,
134             exp: r_exp
135         }
136     );
137 }
138 
139 #[test]
round_to_f64_test()140 fn round_to_f64_test() {
141     // This is lossy, so some of these values are **slightly** rounded.
142 
143     // underflow
144     check_round_to_f64(9223372036854775808, -1138, 0, -1074);
145 
146     // min value
147     check_round_to_f64(9223372036854775808, -1137, 1, -1074);
148 
149     // 1.0e-250
150     check_round_to_f64(15095849699286165504, -562, 7371020360979573, -551);
151 
152     // 1.0e-150
153     check_round_to_f64(15095849699286165504, -562, 7371020360979573, -551);
154 
155     // 1.0e-45
156     check_round_to_f64(13164036458569648128, -213, 6427752177035961, -202);
157 
158     // 1.0e-40
159     check_round_to_f64(10043362776618688512, -196, 4903985730770844, -185);
160 
161     // 1.0e-20
162     check_round_to_f64(13611294676837537792, -130, 6646139978924579, -119);
163 
164     // 1.0
165     check_round_to_f64(9223372036854775808, -63, 4503599627370496, -52);
166 
167     // 1e20
168     check_round_to_f64(12500000000000000000, 3, 6103515625000000, 14);
169 
170     // 1e40
171     check_round_to_f64(16940658945086007296, 69, 8271806125530277, 80);
172 
173     // 1e150
174     check_round_to_f64(11270725851789228032, 435, 5503284107318959, 446);
175 
176     // 1e250
177     check_round_to_f64(12882297539194265600, 767, 6290184345309700, 778);
178 
179     // max value
180     check_round_to_f64(18446744073709549568, 960, 9007199254740991, 971);
181 
182     // Bug fixes
183     // 1.2345e-308
184     check_round_to_f64(10234494226754558294, -1086, 2498655817078750, -1074);
185 }
186 
assert_normalized_eq(mut x: ExtendedFloat, mut y: ExtendedFloat)187 fn assert_normalized_eq(mut x: ExtendedFloat, mut y: ExtendedFloat) {
188     x.normalize();
189     y.normalize();
190     assert_eq!(x, y);
191 }
192 
193 #[test]
from_float()194 fn from_float() {
195     let values: [f32; 26] = [
196         1e-40, 2e-40, 1e-35, 2e-35, 1e-30, 2e-30, 1e-25, 2e-25, 1e-20, 2e-20, 1e-15, 2e-15, 1e-10,
197         2e-10, 1e-5, 2e-5, 1.0, 2.0, 1e5, 2e5, 1e10, 2e10, 1e15, 2e15, 1e20, 2e20,
198     ];
199     for value in &values {
200         assert_normalized_eq(
201             ExtendedFloat::from_float(*value),
202             ExtendedFloat::from_float(*value as f64),
203         );
204     }
205 }
206 
207 // TO
208 
209 // Sample of interesting numbers to check during standard test builds.
210 const INTEGERS: [u64; 32] = [
211     0,                    // 0x0
212     1,                    // 0x1
213     7,                    // 0x7
214     15,                   // 0xF
215     112,                  // 0x70
216     119,                  // 0x77
217     127,                  // 0x7F
218     240,                  // 0xF0
219     247,                  // 0xF7
220     255,                  // 0xFF
221     2032,                 // 0x7F0
222     2039,                 // 0x7F7
223     2047,                 // 0x7FF
224     4080,                 // 0xFF0
225     4087,                 // 0xFF7
226     4095,                 // 0xFFF
227     65520,                // 0xFFF0
228     65527,                // 0xFFF7
229     65535,                // 0xFFFF
230     1048560,              // 0xFFFF0
231     1048567,              // 0xFFFF7
232     1048575,              // 0xFFFFF
233     16777200,             // 0xFFFFF0
234     16777207,             // 0xFFFFF7
235     16777215,             // 0xFFFFFF
236     268435440,            // 0xFFFFFF0
237     268435447,            // 0xFFFFFF7
238     268435455,            // 0xFFFFFFF
239     4294967280,           // 0xFFFFFFF0
240     4294967287,           // 0xFFFFFFF7
241     4294967295,           // 0xFFFFFFFF
242     18446744073709551615, // 0xFFFFFFFFFFFFFFFF
243 ];
244 
245 #[test]
to_f32_test()246 fn to_f32_test() {
247     // underflow
248     let x = ExtendedFloat {
249         mant: 9223372036854775808,
250         exp: -213,
251     };
252     assert_eq!(x.into_float::<f32>(), 0.0);
253 
254     // min value
255     let x = ExtendedFloat {
256         mant: 9223372036854775808,
257         exp: -212,
258     };
259     assert_eq!(x.into_float::<f32>(), 1e-45);
260 
261     // 1.0e-40
262     let x = ExtendedFloat {
263         mant: 10043308644012916736,
264         exp: -196,
265     };
266     assert_eq!(x.into_float::<f32>(), 1e-40);
267 
268     // 1.0e-20
269     let x = ExtendedFloat {
270         mant: 13611294244890214400,
271         exp: -130,
272     };
273     assert_eq!(x.into_float::<f32>(), 1e-20);
274 
275     // 1.0
276     let x = ExtendedFloat {
277         mant: 9223372036854775808,
278         exp: -63,
279     };
280     assert_eq!(x.into_float::<f32>(), 1.0);
281 
282     // 1e20
283     let x = ExtendedFloat {
284         mant: 12500000250510966784,
285         exp: 3,
286     };
287     assert_eq!(x.into_float::<f32>(), 1e20);
288 
289     // max value
290     let x = ExtendedFloat {
291         mant: 18446740775174668288,
292         exp: 64,
293     };
294     assert_eq!(x.into_float::<f32>(), 3.402823e38);
295 
296     // almost max, high exp
297     let x = ExtendedFloat {
298         mant: 1048575,
299         exp: 108,
300     };
301     assert_eq!(x.into_float::<f32>(), 3.4028204e38);
302 
303     // max value + 1
304     let x = ExtendedFloat {
305         mant: 16777216,
306         exp: 104,
307     };
308     assert_eq!(x.into_float::<f32>(), f32::INFINITY);
309 
310     // max value + 1
311     let x = ExtendedFloat {
312         mant: 1048576,
313         exp: 108,
314     };
315     assert_eq!(x.into_float::<f32>(), f32::INFINITY);
316 
317     // 1e40
318     let x = ExtendedFloat {
319         mant: 16940658945086007296,
320         exp: 69,
321     };
322     assert_eq!(x.into_float::<f32>(), f32::INFINITY);
323 
324     // Integers.
325     for int in &INTEGERS {
326         let fp = ExtendedFloat { mant: *int, exp: 0 };
327         assert_eq!(fp.into_float::<f32>(), *int as f32, "{:?} as f32", *int);
328     }
329 }
330 
331 #[test]
to_f64_test()332 fn to_f64_test() {
333     // underflow
334     let x = ExtendedFloat {
335         mant: 9223372036854775808,
336         exp: -1138,
337     };
338     assert_eq!(x.into_float::<f64>(), 0.0);
339 
340     // min value
341     let x = ExtendedFloat {
342         mant: 9223372036854775808,
343         exp: -1137,
344     };
345     assert_eq!(x.into_float::<f64>(), 5e-324);
346 
347     // 1.0e-250
348     let x = ExtendedFloat {
349         mant: 13207363278391631872,
350         exp: -894,
351     };
352     assert_eq!(x.into_float::<f64>(), 1e-250);
353 
354     // 1.0e-150
355     let x = ExtendedFloat {
356         mant: 15095849699286165504,
357         exp: -562,
358     };
359     assert_eq!(x.into_float::<f64>(), 1e-150);
360 
361     // 1.0e-45
362     let x = ExtendedFloat {
363         mant: 13164036458569648128,
364         exp: -213,
365     };
366     assert_eq!(x.into_float::<f64>(), 1e-45);
367 
368     // 1.0e-40
369     let x = ExtendedFloat {
370         mant: 10043362776618688512,
371         exp: -196,
372     };
373     assert_eq!(x.into_float::<f64>(), 1e-40);
374 
375     // 1.0e-20
376     let x = ExtendedFloat {
377         mant: 13611294676837537792,
378         exp: -130,
379     };
380     assert_eq!(x.into_float::<f64>(), 1e-20);
381 
382     // 1.0
383     let x = ExtendedFloat {
384         mant: 9223372036854775808,
385         exp: -63,
386     };
387     assert_eq!(x.into_float::<f64>(), 1.0);
388 
389     // 1e20
390     let x = ExtendedFloat {
391         mant: 12500000000000000000,
392         exp: 3,
393     };
394     assert_eq!(x.into_float::<f64>(), 1e20);
395 
396     // 1e40
397     let x = ExtendedFloat {
398         mant: 16940658945086007296,
399         exp: 69,
400     };
401     assert_eq!(x.into_float::<f64>(), 1e40);
402 
403     // 1e150
404     let x = ExtendedFloat {
405         mant: 11270725851789228032,
406         exp: 435,
407     };
408     assert_eq!(x.into_float::<f64>(), 1e150);
409 
410     // 1e250
411     let x = ExtendedFloat {
412         mant: 12882297539194265600,
413         exp: 767,
414     };
415     assert_eq!(x.into_float::<f64>(), 1e250);
416 
417     // max value
418     let x = ExtendedFloat {
419         mant: 9007199254740991,
420         exp: 971,
421     };
422     assert_eq!(x.into_float::<f64>(), 1.7976931348623157e308);
423 
424     // max value
425     let x = ExtendedFloat {
426         mant: 18446744073709549568,
427         exp: 960,
428     };
429     assert_eq!(x.into_float::<f64>(), 1.7976931348623157e308);
430 
431     // overflow
432     let x = ExtendedFloat {
433         mant: 9007199254740992,
434         exp: 971,
435     };
436     assert_eq!(x.into_float::<f64>(), f64::INFINITY);
437 
438     // overflow
439     let x = ExtendedFloat {
440         mant: 18446744073709549568,
441         exp: 961,
442     };
443     assert_eq!(x.into_float::<f64>(), f64::INFINITY);
444 
445     // Underflow
446     // Adapted from failures in strtod.
447     let x = ExtendedFloat {
448         exp: -1139,
449         mant: 18446744073709550712,
450     };
451     assert_eq!(x.into_float::<f64>(), 0.0);
452 
453     let x = ExtendedFloat {
454         exp: -1139,
455         mant: 18446744073709551460,
456     };
457     assert_eq!(x.into_float::<f64>(), 0.0);
458 
459     let x = ExtendedFloat {
460         exp: -1138,
461         mant: 9223372036854776103,
462     };
463     assert_eq!(x.into_float::<f64>(), 5e-324);
464 
465     // Integers.
466     for int in &INTEGERS {
467         let fp = ExtendedFloat { mant: *int, exp: 0 };
468         assert_eq!(fp.into_float::<f64>(), *int as f64, "{:?} as f64", *int);
469     }
470 }
471 
472 // OPERATIONS
473 
check_mul(a: ExtendedFloat, b: ExtendedFloat, c: ExtendedFloat)474 fn check_mul(a: ExtendedFloat, b: ExtendedFloat, c: ExtendedFloat) {
475     let r = a.mul(&b);
476     assert_eq!(r, c);
477 }
478 
479 #[test]
mul_test()480 fn mul_test() {
481     // Normalized (64-bit mantissa)
482     let a = ExtendedFloat {
483         mant: 13164036458569648128,
484         exp: -213,
485     };
486     let b = ExtendedFloat {
487         mant: 9223372036854775808,
488         exp: -62,
489     };
490     let c = ExtendedFloat {
491         mant: 6582018229284824064,
492         exp: -211,
493     };
494     check_mul(a, b, c);
495 
496     // Check with integers
497     // 64-bit mantissa
498     let mut a = ExtendedFloat { mant: 10, exp: 0 };
499     let mut b = ExtendedFloat { mant: 10, exp: 0 };
500     a.normalize();
501     b.normalize();
502     assert_eq!(a.mul(&b).into_float::<f64>(), 100.0);
503 
504     // Check both values need high bits set.
505     let a = ExtendedFloat {
506         mant: 1 << 32,
507         exp: -31,
508     };
509     let b = ExtendedFloat {
510         mant: 1 << 32,
511         exp: -31,
512     };
513     assert_eq!(a.mul(&b).into_float::<f64>(), 4.0);
514 
515     // Check both values need high bits set.
516     let a = ExtendedFloat {
517         mant: 10 << 31,
518         exp: -31,
519     };
520     let b = ExtendedFloat {
521         mant: 10 << 31,
522         exp: -31,
523     };
524     assert_eq!(a.mul(&b).into_float::<f64>(), 100.0);
525 }
526 
check_imul(mut a: ExtendedFloat, b: ExtendedFloat, c: ExtendedFloat)527 fn check_imul(mut a: ExtendedFloat, b: ExtendedFloat, c: ExtendedFloat) {
528     a.imul(&b);
529     assert_eq!(a, c);
530 }
531 
532 #[test]
imul_test()533 fn imul_test() {
534     // Normalized (64-bit mantissa)
535     let a = ExtendedFloat {
536         mant: 13164036458569648128,
537         exp: -213,
538     };
539     let b = ExtendedFloat {
540         mant: 9223372036854775808,
541         exp: -62,
542     };
543     let c = ExtendedFloat {
544         mant: 6582018229284824064,
545         exp: -211,
546     };
547     check_imul(a, b, c);
548 
549     // Check with integers
550     // 64-bit mantissa
551     let mut a = ExtendedFloat { mant: 10, exp: 0 };
552     let mut b = ExtendedFloat { mant: 10, exp: 0 };
553     a.normalize();
554     b.normalize();
555     a.imul(&b);
556     assert_eq!(a.into_float::<f64>(), 100.0);
557 
558     // Check both values need high bits set.
559     let mut a = ExtendedFloat {
560         mant: 1 << 32,
561         exp: -31,
562     };
563     let b = ExtendedFloat {
564         mant: 1 << 32,
565         exp: -31,
566     };
567     a.imul(&b);
568     assert_eq!(a.into_float::<f64>(), 4.0);
569 
570     // Check both values need high bits set.
571     let mut a = ExtendedFloat {
572         mant: 10 << 31,
573         exp: -31,
574     };
575     let b = ExtendedFloat {
576         mant: 10 << 31,
577         exp: -31,
578     };
579     a.imul(&b);
580     assert_eq!(a.into_float::<f64>(), 100.0);
581 }
582