]> git.lizzy.rs Git - rust.git/blob - src/librustc_apfloat/tests/ppc.rs
Rollup merge of #58059 - RalfJung:before_exec, r=alexcrichton
[rust.git] / src / librustc_apfloat / tests / ppc.rs
1 use rustc_apfloat::{Category, Float, Round};
2 use rustc_apfloat::ppc::DoubleDouble;
3
4 use std::cmp::Ordering;
5
6 #[test]
7 fn ppc_double_double() {
8     let test = DoubleDouble::ZERO;
9     let expected = "0x0p+0".parse::<DoubleDouble>().unwrap();
10     assert!(test.is_zero());
11     assert!(!test.is_negative());
12     assert!(test.bitwise_eq(expected));
13     assert_eq!(0, test.to_bits());
14
15     let test = -DoubleDouble::ZERO;
16     let expected = "-0x0p+0".parse::<DoubleDouble>().unwrap();
17     assert!(test.is_zero());
18     assert!(test.is_negative());
19     assert!(test.bitwise_eq(expected));
20     assert_eq!(0x8000000000000000, test.to_bits());
21
22     let test = "1.0".parse::<DoubleDouble>().unwrap();
23     assert_eq!(0x3ff0000000000000, test.to_bits());
24
25     // LDBL_MAX
26     let test = "1.79769313486231580793728971405301e+308"
27         .parse::<DoubleDouble>()
28         .unwrap();
29     assert_eq!(0x7c8ffffffffffffe_7fefffffffffffff, test.to_bits());
30
31     // LDBL_MIN
32     let test = "2.00416836000897277799610805135016e-292"
33         .parse::<DoubleDouble>()
34         .unwrap();
35     assert_eq!(0x0000000000000000_0360000000000000, test.to_bits());
36 }
37
38 #[test]
39 fn ppc_double_double_add_special() {
40     let data = [
41         // (1 + 0) + (-1 + 0) = Category::Zero
42         (
43             0x3ff0000000000000,
44             0xbff0000000000000,
45             Category::Zero,
46             Round::NearestTiesToEven,
47         ),
48         // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = Category::Infinity
49         (
50             0x7c8ffffffffffffe_7fefffffffffffff,
51             0x7948000000000000,
52             Category::Infinity,
53             Round::NearestTiesToEven,
54         ),
55         // FIXME: change the 4th 0x75effffffffffffe to 0x75efffffffffffff when
56         // DoubleDouble's fallback is gone.
57         // LDBL_MAX + (1.011111... >> (1023 - 106) + (1.1111111...0 >> (1023 -
58         // 160))) = Category::Normal
59         (
60             0x7c8ffffffffffffe_7fefffffffffffff,
61             0x75effffffffffffe_7947ffffffffffff,
62             Category::Normal,
63             Round::NearestTiesToEven,
64         ),
65         // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = Category::Infinity
66         (
67             0x7c8ffffffffffffe_7fefffffffffffff,
68             0x7c8ffffffffffffe_7fefffffffffffff,
69             Category::Infinity,
70             Round::NearestTiesToEven,
71         ),
72         // NaN + (1 + 0) = Category::NaN
73         (
74             0x7ff8000000000000,
75             0x3ff0000000000000,
76             Category::NaN,
77             Round::NearestTiesToEven,
78         ),
79     ];
80
81     for &(op1, op2, expected, round) in &data {
82         {
83             let mut a1 = DoubleDouble::from_bits(op1);
84             let a2 = DoubleDouble::from_bits(op2);
85             a1 = a1.add_r(a2, round).value;
86
87             assert_eq!(expected, a1.category(), "{:#x} + {:#x}", op1, op2);
88         }
89         {
90             let a1 = DoubleDouble::from_bits(op1);
91             let mut a2 = DoubleDouble::from_bits(op2);
92             a2 = a2.add_r(a1, round).value;
93
94             assert_eq!(expected, a2.category(), "{:#x} + {:#x}", op2, op1);
95         }
96     }
97 }
98
99 #[test]
100 fn ppc_double_double_add() {
101     let data = [
102         // (1 + 0) + (1e-105 + 0) = (1 + 1e-105)
103         (
104             0x3ff0000000000000,
105             0x3960000000000000,
106             0x3960000000000000_3ff0000000000000,
107             Round::NearestTiesToEven,
108         ),
109         // (1 + 0) + (1e-106 + 0) = (1 + 1e-106)
110         (
111             0x3ff0000000000000,
112             0x3950000000000000,
113             0x3950000000000000_3ff0000000000000,
114             Round::NearestTiesToEven,
115         ),
116         // (1 + 1e-106) + (1e-106 + 0) = (1 + 1e-105)
117         (
118             0x3950000000000000_3ff0000000000000,
119             0x3950000000000000,
120             0x3960000000000000_3ff0000000000000,
121             Round::NearestTiesToEven,
122         ),
123         // (1 + 0) + (epsilon + 0) = (1 + epsilon)
124         (
125             0x3ff0000000000000,
126             0x0000000000000001,
127             0x0000000000000001_3ff0000000000000,
128             Round::NearestTiesToEven,
129         ),
130         // FIXME: change 0xf950000000000000 to 0xf940000000000000, when
131         // DoubleDouble's fallback is gone.
132         // (DBL_MAX - 1 << (1023 - 105)) + (1 << (1023 - 53) + 0) = DBL_MAX +
133         // 1.11111... << (1023 - 52)
134         (
135             0xf950000000000000_7fefffffffffffff,
136             0x7c90000000000000,
137             0x7c8ffffffffffffe_7fefffffffffffff,
138             Round::NearestTiesToEven,
139         ),
140         // FIXME: change 0xf950000000000000 to 0xf940000000000000, when
141         // DoubleDouble's fallback is gone.
142         // (1 << (1023 - 53) + 0) + (DBL_MAX - 1 << (1023 - 105)) = DBL_MAX +
143         // 1.11111... << (1023 - 52)
144         (
145             0x7c90000000000000,
146             0xf950000000000000_7fefffffffffffff,
147             0x7c8ffffffffffffe_7fefffffffffffff,
148             Round::NearestTiesToEven,
149         ),
150     ];
151
152     for &(op1, op2, expected, round) in &data {
153         {
154             let mut a1 = DoubleDouble::from_bits(op1);
155             let a2 = DoubleDouble::from_bits(op2);
156             a1 = a1.add_r(a2, round).value;
157
158             assert_eq!(expected, a1.to_bits(), "{:#x} + {:#x}", op1, op2);
159         }
160         {
161             let a1 = DoubleDouble::from_bits(op1);
162             let mut a2 = DoubleDouble::from_bits(op2);
163             a2 = a2.add_r(a1, round).value;
164
165             assert_eq!(expected, a2.to_bits(), "{:#x} + {:#x}", op2, op1);
166         }
167     }
168 }
169
170 #[test]
171 fn ppc_double_double_subtract() {
172     let data = [
173         // (1 + 0) - (-1e-105 + 0) = (1 + 1e-105)
174         (
175             0x3ff0000000000000,
176             0xb960000000000000,
177             0x3960000000000000_3ff0000000000000,
178             Round::NearestTiesToEven,
179         ),
180         // (1 + 0) - (-1e-106 + 0) = (1 + 1e-106)
181         (
182             0x3ff0000000000000,
183             0xb950000000000000,
184             0x3950000000000000_3ff0000000000000,
185             Round::NearestTiesToEven,
186         ),
187     ];
188
189     for &(op1, op2, expected, round) in &data {
190         let mut a1 = DoubleDouble::from_bits(op1);
191         let a2 = DoubleDouble::from_bits(op2);
192         a1 = a1.sub_r(a2, round).value;
193
194         assert_eq!(expected, a1.to_bits(), "{:#x} - {:#x}", op1, op2);
195     }
196 }
197
198 #[test]
199 fn ppc_double_double_multiply_special() {
200     let data = [
201         // Category::NaN * Category::NaN = Category::NaN
202         (
203             0x7ff8000000000000,
204             0x7ff8000000000000,
205             Category::NaN,
206             Round::NearestTiesToEven,
207         ),
208         // Category::NaN * Category::Zero = Category::NaN
209         (
210             0x7ff8000000000000,
211             0,
212             Category::NaN,
213             Round::NearestTiesToEven,
214         ),
215         // Category::NaN * Category::Infinity = Category::NaN
216         (
217             0x7ff8000000000000,
218             0x7ff0000000000000,
219             Category::NaN,
220             Round::NearestTiesToEven,
221         ),
222         // Category::NaN * Category::Normal = Category::NaN
223         (
224             0x7ff8000000000000,
225             0x3ff0000000000000,
226             Category::NaN,
227             Round::NearestTiesToEven,
228         ),
229         // Category::Infinity * Category::Infinity = Category::Infinity
230         (
231             0x7ff0000000000000,
232             0x7ff0000000000000,
233             Category::Infinity,
234             Round::NearestTiesToEven,
235         ),
236         // Category::Infinity * Category::Zero = Category::NaN
237         (
238             0x7ff0000000000000,
239             0,
240             Category::NaN,
241             Round::NearestTiesToEven,
242         ),
243         // Category::Infinity * Category::Normal = Category::Infinity
244         (
245             0x7ff0000000000000,
246             0x3ff0000000000000,
247             Category::Infinity,
248             Round::NearestTiesToEven,
249         ),
250         // Category::Zero * Category::Zero = Category::Zero
251         (0, 0, Category::Zero, Round::NearestTiesToEven),
252         // Category::Zero * Category::Normal = Category::Zero
253         (
254             0,
255             0x3ff0000000000000,
256             Category::Zero,
257             Round::NearestTiesToEven,
258         ),
259     ];
260
261     for &(op1, op2, expected, round) in &data {
262         {
263             let mut a1 = DoubleDouble::from_bits(op1);
264             let a2 = DoubleDouble::from_bits(op2);
265             a1 = a1.mul_r(a2, round).value;
266
267             assert_eq!(expected, a1.category(), "{:#x} * {:#x}", op1, op2);
268         }
269         {
270             let a1 = DoubleDouble::from_bits(op1);
271             let mut a2 = DoubleDouble::from_bits(op2);
272             a2 = a2.mul_r(a1, round).value;
273
274             assert_eq!(expected, a2.category(), "{:#x} * {:#x}", op2, op1);
275         }
276     }
277 }
278
279 #[test]
280 fn ppc_double_double_multiply() {
281     let data = [
282         // 1/3 * 3 = 1.0
283         (
284             0x3c75555555555556_3fd5555555555555,
285             0x4008000000000000,
286             0x3ff0000000000000,
287             Round::NearestTiesToEven,
288         ),
289         // (1 + epsilon) * (1 + 0) = Category::Zero
290         (
291             0x0000000000000001_3ff0000000000000,
292             0x3ff0000000000000,
293             0x0000000000000001_3ff0000000000000,
294             Round::NearestTiesToEven,
295         ),
296         // (1 + epsilon) * (1 + epsilon) = 1 + 2 * epsilon
297         (
298             0x0000000000000001_3ff0000000000000,
299             0x0000000000000001_3ff0000000000000,
300             0x0000000000000002_3ff0000000000000,
301             Round::NearestTiesToEven,
302         ),
303         // -(1 + epsilon) * (1 + epsilon) = -1
304         (
305             0x0000000000000001_bff0000000000000,
306             0x0000000000000001_3ff0000000000000,
307             0xbff0000000000000,
308             Round::NearestTiesToEven,
309         ),
310         // (0.5 + 0) * (1 + 2 * epsilon) = 0.5 + epsilon
311         (
312             0x3fe0000000000000,
313             0x0000000000000002_3ff0000000000000,
314             0x0000000000000001_3fe0000000000000,
315             Round::NearestTiesToEven,
316         ),
317         // (0.5 + 0) * (1 + epsilon) = 0.5
318         (
319             0x3fe0000000000000,
320             0x0000000000000001_3ff0000000000000,
321             0x3fe0000000000000,
322             Round::NearestTiesToEven,
323         ),
324         // __LDBL_MAX__ * (1 + 1 << 106) = inf
325         (
326             0x7c8ffffffffffffe_7fefffffffffffff,
327             0x3950000000000000_3ff0000000000000,
328             0x7ff0000000000000,
329             Round::NearestTiesToEven,
330         ),
331         // __LDBL_MAX__ * (1 + 1 << 107) > __LDBL_MAX__, but not inf, yes =_=|||
332         (
333             0x7c8ffffffffffffe_7fefffffffffffff,
334             0x3940000000000000_3ff0000000000000,
335             0x7c8fffffffffffff_7fefffffffffffff,
336             Round::NearestTiesToEven,
337         ),
338         // __LDBL_MAX__ * (1 + 1 << 108) = __LDBL_MAX__
339         (
340             0x7c8ffffffffffffe_7fefffffffffffff,
341             0x3930000000000000_3ff0000000000000,
342             0x7c8ffffffffffffe_7fefffffffffffff,
343             Round::NearestTiesToEven,
344         ),
345     ];
346
347     for &(op1, op2, expected, round) in &data {
348         {
349             let mut a1 = DoubleDouble::from_bits(op1);
350             let a2 = DoubleDouble::from_bits(op2);
351             a1 = a1.mul_r(a2, round).value;
352
353             assert_eq!(expected, a1.to_bits(), "{:#x} * {:#x}", op1, op2);
354         }
355         {
356             let a1 = DoubleDouble::from_bits(op1);
357             let mut a2 = DoubleDouble::from_bits(op2);
358             a2 = a2.mul_r(a1, round).value;
359
360             assert_eq!(expected, a2.to_bits(), "{:#x} * {:#x}", op2, op1);
361         }
362     }
363 }
364
365 #[test]
366 fn ppc_double_double_divide() {
367     // FIXME: Only a sanity check for now. Add more edge cases when the
368     // double-double algorithm is implemented.
369     let data = [
370         // 1 / 3 = 1/3
371         (
372             0x3ff0000000000000,
373             0x4008000000000000,
374             0x3c75555555555556_3fd5555555555555,
375             Round::NearestTiesToEven,
376         ),
377     ];
378
379     for &(op1, op2, expected, round) in &data {
380         let mut a1 = DoubleDouble::from_bits(op1);
381         let a2 = DoubleDouble::from_bits(op2);
382         a1 = a1.div_r(a2, round).value;
383
384         assert_eq!(expected, a1.to_bits(), "{:#x} / {:#x}", op1, op2);
385     }
386 }
387
388 #[test]
389 fn ppc_double_double_remainder() {
390     let data = [
391         // ieee_rem(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
392         (
393             0x3cb8000000000000_4008000000000000,
394             0x3ca4000000000000_3ff4000000000000,
395             0x3c90000000000000_3fe0000000000000,
396         ),
397         // ieee_rem(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (-0.5 - 0.5 << 53)
398         (
399             0x3cb8000000000000_4008000000000000,
400             0x3cac000000000000_3ffc000000000000,
401             0xbc90000000000000_bfe0000000000000,
402         ),
403     ];
404
405     for &(op1, op2, expected) in &data {
406         let a1 = DoubleDouble::from_bits(op1);
407         let a2 = DoubleDouble::from_bits(op2);
408         let result = a1.ieee_rem(a2).value;
409
410         assert_eq!(
411             expected,
412             result.to_bits(),
413             "ieee_rem({:#x}, {:#x})",
414             op1,
415             op2
416         );
417     }
418 }
419
420 #[test]
421 fn ppc_double_double_mod() {
422     let data = [
423         // mod(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
424         (
425             0x3cb8000000000000_4008000000000000,
426             0x3ca4000000000000_3ff4000000000000,
427             0x3c90000000000000_3fe0000000000000,
428         ),
429         // mod(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (1.25 + 1.25 << 53)
430         // 0xbc98000000000000 doesn't seem right, but it's what we currently have.
431         // FIXME: investigate
432         (
433             0x3cb8000000000000_4008000000000000,
434             0x3cac000000000000_3ffc000000000000,
435             0xbc98000000000000_3ff4000000000001,
436         ),
437     ];
438
439     for &(op1, op2, expected) in &data {
440         let a1 = DoubleDouble::from_bits(op1);
441         let a2 = DoubleDouble::from_bits(op2);
442         let r = (a1 % a2).value;
443
444         assert_eq!(expected, r.to_bits(), "fmod({:#x}, {:#x})", op1, op2);
445     }
446 }
447
448 #[test]
449 fn ppc_double_double_fma() {
450     // Sanity check for now.
451     let mut a = "2".parse::<DoubleDouble>().unwrap();
452     a = a.mul_add(
453         "3".parse::<DoubleDouble>().unwrap(),
454         "4".parse::<DoubleDouble>().unwrap(),
455     ).value;
456     assert_eq!(
457         Some(Ordering::Equal),
458         "10".parse::<DoubleDouble>().unwrap().partial_cmp(&a)
459     );
460 }
461
462 #[test]
463 fn ppc_double_double_round_to_integral() {
464     {
465         let a = "1.5".parse::<DoubleDouble>().unwrap();
466         let a = a.round_to_integral(Round::NearestTiesToEven).value;
467         assert_eq!(
468             Some(Ordering::Equal),
469             "2".parse::<DoubleDouble>().unwrap().partial_cmp(&a)
470         );
471     }
472     {
473         let a = "2.5".parse::<DoubleDouble>().unwrap();
474         let a = a.round_to_integral(Round::NearestTiesToEven).value;
475         assert_eq!(
476             Some(Ordering::Equal),
477             "2".parse::<DoubleDouble>().unwrap().partial_cmp(&a)
478         );
479     }
480 }
481
482 #[test]
483 fn ppc_double_double_compare() {
484     let data = [
485         // (1 + 0) = (1 + 0)
486         (
487             0x3ff0000000000000,
488             0x3ff0000000000000,
489             Some(Ordering::Equal),
490         ),
491         // (1 + 0) < (1.00...1 + 0)
492         (0x3ff0000000000000, 0x3ff0000000000001, Some(Ordering::Less)),
493         // (1.00...1 + 0) > (1 + 0)
494         (
495             0x3ff0000000000001,
496             0x3ff0000000000000,
497             Some(Ordering::Greater),
498         ),
499         // (1 + 0) < (1 + epsilon)
500         (
501             0x3ff0000000000000,
502             0x0000000000000001_3ff0000000000001,
503             Some(Ordering::Less),
504         ),
505         // NaN != NaN
506         (0x7ff8000000000000, 0x7ff8000000000000, None),
507         // (1 + 0) != NaN
508         (0x3ff0000000000000, 0x7ff8000000000000, None),
509         // Inf = Inf
510         (
511             0x7ff0000000000000,
512             0x7ff0000000000000,
513             Some(Ordering::Equal),
514         ),
515     ];
516
517     for &(op1, op2, expected) in &data {
518         let a1 = DoubleDouble::from_bits(op1);
519         let a2 = DoubleDouble::from_bits(op2);
520         assert_eq!(
521             expected,
522             a1.partial_cmp(&a2),
523             "compare({:#x}, {:#x})",
524             op1,
525             op2,
526         );
527     }
528 }
529
530 #[test]
531 fn ppc_double_double_bitwise_eq() {
532     let data = [
533         // (1 + 0) = (1 + 0)
534         (0x3ff0000000000000, 0x3ff0000000000000, true),
535         // (1 + 0) != (1.00...1 + 0)
536         (0x3ff0000000000000, 0x3ff0000000000001, false),
537         // NaN = NaN
538         (0x7ff8000000000000, 0x7ff8000000000000, true),
539         // NaN != NaN with a different bit pattern
540         (
541             0x7ff8000000000000,
542             0x3ff0000000000000_7ff8000000000000,
543             false,
544         ),
545         // Inf = Inf
546         (0x7ff0000000000000, 0x7ff0000000000000, true),
547     ];
548
549     for &(op1, op2, expected) in &data {
550         let a1 = DoubleDouble::from_bits(op1);
551         let a2 = DoubleDouble::from_bits(op2);
552         assert_eq!(expected, a1.bitwise_eq(a2), "{:#x} = {:#x}", op1, op2);
553     }
554 }
555
556 #[test]
557 fn ppc_double_double_change_sign() {
558     let float = DoubleDouble::from_bits(0xbcb0000000000000_400f000000000000);
559     {
560         let actual = float.copy_sign("1".parse::<DoubleDouble>().unwrap());
561         assert_eq!(0xbcb0000000000000_400f000000000000, actual.to_bits());
562     }
563     {
564         let actual = float.copy_sign("-1".parse::<DoubleDouble>().unwrap());
565         assert_eq!(0x3cb0000000000000_c00f000000000000, actual.to_bits());
566     }
567 }
568
569 #[test]
570 fn ppc_double_double_factories() {
571     assert_eq!(0, DoubleDouble::ZERO.to_bits());
572     assert_eq!(
573         0x7c8ffffffffffffe_7fefffffffffffff,
574         DoubleDouble::largest().to_bits()
575     );
576     assert_eq!(0x0000000000000001, DoubleDouble::SMALLEST.to_bits());
577     assert_eq!(
578         0x0360000000000000,
579         DoubleDouble::smallest_normalized().to_bits()
580     );
581     assert_eq!(
582         0x0000000000000000_8000000000000000,
583         (-DoubleDouble::ZERO).to_bits()
584     );
585     assert_eq!(
586         0xfc8ffffffffffffe_ffefffffffffffff,
587         (-DoubleDouble::largest()).to_bits()
588     );
589     assert_eq!(
590         0x0000000000000000_8000000000000001,
591         (-DoubleDouble::SMALLEST).to_bits()
592     );
593     assert_eq!(
594         0x0000000000000000_8360000000000000,
595         (-DoubleDouble::smallest_normalized()).to_bits()
596     );
597     assert!(DoubleDouble::SMALLEST.is_smallest());
598     assert!(DoubleDouble::largest().is_largest());
599 }
600
601 #[test]
602 fn ppc_double_double_is_denormal() {
603     assert!(DoubleDouble::SMALLEST.is_denormal());
604     assert!(!DoubleDouble::largest().is_denormal());
605     assert!(!DoubleDouble::smallest_normalized().is_denormal());
606     {
607         // (4 + 3) is not normalized
608         let data = 0x4008000000000000_4010000000000000;
609         assert!(DoubleDouble::from_bits(data).is_denormal());
610     }
611 }
612
613 #[test]
614 fn ppc_double_double_exact_inverse() {
615     assert!(
616         "2.0"
617             .parse::<DoubleDouble>()
618             .unwrap()
619             .get_exact_inverse()
620             .unwrap()
621             .bitwise_eq("0.5".parse::<DoubleDouble>().unwrap())
622     );
623 }
624
625 #[test]
626 fn ppc_double_double_scalbn() {
627     // 3.0 + 3.0 << 53
628     let input = 0x3cb8000000000000_4008000000000000;
629     let result = DoubleDouble::from_bits(input).scalbn(1);
630     // 6.0 + 6.0 << 53
631     assert_eq!(0x3cc8000000000000_4018000000000000, result.to_bits());
632 }
633
634 #[test]
635 fn ppc_double_double_frexp() {
636     // 3.0 + 3.0 << 53
637     let input = 0x3cb8000000000000_4008000000000000;
638     let mut exp = 0;
639     // 0.75 + 0.75 << 53
640     let result = DoubleDouble::from_bits(input).frexp(&mut exp);
641     assert_eq!(2, exp);
642     assert_eq!(0x3c98000000000000_3fe8000000000000, result.to_bits());
643 }