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