1 use rustc_apfloat::{Category, Float, Round};
2 use rustc_apfloat::ppc::DoubleDouble;
4 use std::cmp::Ordering;
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());
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());
22 let test = "1.0".parse::<DoubleDouble>().unwrap();
23 assert_eq!(0x3ff0000000000000, test.to_bits());
26 let test = "1.79769313486231580793728971405301e+308"
27 .parse::<DoubleDouble>()
29 assert_eq!(0x7c8ffffffffffffe_7fefffffffffffff, test.to_bits());
32 let test = "2.00416836000897277799610805135016e-292"
33 .parse::<DoubleDouble>()
35 assert_eq!(0x0000000000000000_0360000000000000, test.to_bits());
39 fn ppc_double_double_add_special() {
41 // (1 + 0) + (-1 + 0) = Category::Zero
46 Round::NearestTiesToEven,
48 // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = Category::Infinity
50 0x7c8ffffffffffffe_7fefffffffffffff,
53 Round::NearestTiesToEven,
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
60 0x7c8ffffffffffffe_7fefffffffffffff,
61 0x75effffffffffffe_7947ffffffffffff,
63 Round::NearestTiesToEven,
65 // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = Category::Infinity
67 0x7c8ffffffffffffe_7fefffffffffffff,
68 0x7c8ffffffffffffe_7fefffffffffffff,
70 Round::NearestTiesToEven,
72 // NaN + (1 + 0) = Category::NaN
77 Round::NearestTiesToEven,
81 for &(op1, op2, expected, round) in &data {
83 let mut a1 = DoubleDouble::from_bits(op1);
84 let a2 = DoubleDouble::from_bits(op2);
85 a1 = a1.add_r(a2, round).value;
87 assert_eq!(expected, a1.category(), "{:#x} + {:#x}", op1, op2);
90 let a1 = DoubleDouble::from_bits(op1);
91 let mut a2 = DoubleDouble::from_bits(op2);
92 a2 = a2.add_r(a1, round).value;
94 assert_eq!(expected, a2.category(), "{:#x} + {:#x}", op2, op1);
100 fn ppc_double_double_add() {
102 // (1 + 0) + (1e-105 + 0) = (1 + 1e-105)
106 0x3960000000000000_3ff0000000000000,
107 Round::NearestTiesToEven,
109 // (1 + 0) + (1e-106 + 0) = (1 + 1e-106)
113 0x3950000000000000_3ff0000000000000,
114 Round::NearestTiesToEven,
116 // (1 + 1e-106) + (1e-106 + 0) = (1 + 1e-105)
118 0x3950000000000000_3ff0000000000000,
120 0x3960000000000000_3ff0000000000000,
121 Round::NearestTiesToEven,
123 // (1 + 0) + (epsilon + 0) = (1 + epsilon)
127 0x0000000000000001_3ff0000000000000,
128 Round::NearestTiesToEven,
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)
135 0xf950000000000000_7fefffffffffffff,
137 0x7c8ffffffffffffe_7fefffffffffffff,
138 Round::NearestTiesToEven,
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)
146 0xf950000000000000_7fefffffffffffff,
147 0x7c8ffffffffffffe_7fefffffffffffff,
148 Round::NearestTiesToEven,
152 for &(op1, op2, expected, round) in &data {
154 let mut a1 = DoubleDouble::from_bits(op1);
155 let a2 = DoubleDouble::from_bits(op2);
156 a1 = a1.add_r(a2, round).value;
158 assert_eq!(expected, a1.to_bits(), "{:#x} + {:#x}", op1, op2);
161 let a1 = DoubleDouble::from_bits(op1);
162 let mut a2 = DoubleDouble::from_bits(op2);
163 a2 = a2.add_r(a1, round).value;
165 assert_eq!(expected, a2.to_bits(), "{:#x} + {:#x}", op2, op1);
171 fn ppc_double_double_subtract() {
173 // (1 + 0) - (-1e-105 + 0) = (1 + 1e-105)
177 0x3960000000000000_3ff0000000000000,
178 Round::NearestTiesToEven,
180 // (1 + 0) - (-1e-106 + 0) = (1 + 1e-106)
184 0x3950000000000000_3ff0000000000000,
185 Round::NearestTiesToEven,
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;
194 assert_eq!(expected, a1.to_bits(), "{:#x} - {:#x}", op1, op2);
199 fn ppc_double_double_multiply_special() {
201 // Category::NaN * Category::NaN = Category::NaN
206 Round::NearestTiesToEven,
208 // Category::NaN * Category::Zero = Category::NaN
213 Round::NearestTiesToEven,
215 // Category::NaN * Category::Infinity = Category::NaN
220 Round::NearestTiesToEven,
222 // Category::NaN * Category::Normal = Category::NaN
227 Round::NearestTiesToEven,
229 // Category::Infinity * Category::Infinity = Category::Infinity
234 Round::NearestTiesToEven,
236 // Category::Infinity * Category::Zero = Category::NaN
241 Round::NearestTiesToEven,
243 // Category::Infinity * Category::Normal = Category::Infinity
248 Round::NearestTiesToEven,
250 // Category::Zero * Category::Zero = Category::Zero
251 (0, 0, Category::Zero, Round::NearestTiesToEven),
252 // Category::Zero * Category::Normal = Category::Zero
257 Round::NearestTiesToEven,
261 for &(op1, op2, expected, round) in &data {
263 let mut a1 = DoubleDouble::from_bits(op1);
264 let a2 = DoubleDouble::from_bits(op2);
265 a1 = a1.mul_r(a2, round).value;
267 assert_eq!(expected, a1.category(), "{:#x} * {:#x}", op1, op2);
270 let a1 = DoubleDouble::from_bits(op1);
271 let mut a2 = DoubleDouble::from_bits(op2);
272 a2 = a2.mul_r(a1, round).value;
274 assert_eq!(expected, a2.category(), "{:#x} * {:#x}", op2, op1);
280 fn ppc_double_double_multiply() {
284 0x3c75555555555556_3fd5555555555555,
287 Round::NearestTiesToEven,
289 // (1 + epsilon) * (1 + 0) = Category::Zero
291 0x0000000000000001_3ff0000000000000,
293 0x0000000000000001_3ff0000000000000,
294 Round::NearestTiesToEven,
296 // (1 + epsilon) * (1 + epsilon) = 1 + 2 * epsilon
298 0x0000000000000001_3ff0000000000000,
299 0x0000000000000001_3ff0000000000000,
300 0x0000000000000002_3ff0000000000000,
301 Round::NearestTiesToEven,
303 // -(1 + epsilon) * (1 + epsilon) = -1
305 0x0000000000000001_bff0000000000000,
306 0x0000000000000001_3ff0000000000000,
308 Round::NearestTiesToEven,
310 // (0.5 + 0) * (1 + 2 * epsilon) = 0.5 + epsilon
313 0x0000000000000002_3ff0000000000000,
314 0x0000000000000001_3fe0000000000000,
315 Round::NearestTiesToEven,
317 // (0.5 + 0) * (1 + epsilon) = 0.5
320 0x0000000000000001_3ff0000000000000,
322 Round::NearestTiesToEven,
324 // __LDBL_MAX__ * (1 + 1 << 106) = inf
326 0x7c8ffffffffffffe_7fefffffffffffff,
327 0x3950000000000000_3ff0000000000000,
329 Round::NearestTiesToEven,
331 // __LDBL_MAX__ * (1 + 1 << 107) > __LDBL_MAX__, but not inf, yes =_=|||
333 0x7c8ffffffffffffe_7fefffffffffffff,
334 0x3940000000000000_3ff0000000000000,
335 0x7c8fffffffffffff_7fefffffffffffff,
336 Round::NearestTiesToEven,
338 // __LDBL_MAX__ * (1 + 1 << 108) = __LDBL_MAX__
340 0x7c8ffffffffffffe_7fefffffffffffff,
341 0x3930000000000000_3ff0000000000000,
342 0x7c8ffffffffffffe_7fefffffffffffff,
343 Round::NearestTiesToEven,
347 for &(op1, op2, expected, round) in &data {
349 let mut a1 = DoubleDouble::from_bits(op1);
350 let a2 = DoubleDouble::from_bits(op2);
351 a1 = a1.mul_r(a2, round).value;
353 assert_eq!(expected, a1.to_bits(), "{:#x} * {:#x}", op1, op2);
356 let a1 = DoubleDouble::from_bits(op1);
357 let mut a2 = DoubleDouble::from_bits(op2);
358 a2 = a2.mul_r(a1, round).value;
360 assert_eq!(expected, a2.to_bits(), "{:#x} * {:#x}", op2, op1);
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.
374 0x3c75555555555556_3fd5555555555555,
375 Round::NearestTiesToEven,
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;
384 assert_eq!(expected, a1.to_bits(), "{:#x} / {:#x}", op1, op2);
389 fn ppc_double_double_remainder() {
391 // ieee_rem(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
393 0x3cb8000000000000_4008000000000000,
394 0x3ca4000000000000_3ff4000000000000,
395 0x3c90000000000000_3fe0000000000000,
397 // ieee_rem(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (-0.5 - 0.5 << 53)
399 0x3cb8000000000000_4008000000000000,
400 0x3cac000000000000_3ffc000000000000,
401 0xbc90000000000000_bfe0000000000000,
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;
413 "ieee_rem({:#x}, {:#x})",
421 fn ppc_double_double_mod() {
423 // mod(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
425 0x3cb8000000000000_4008000000000000,
426 0x3ca4000000000000_3ff4000000000000,
427 0x3c90000000000000_3fe0000000000000,
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
433 0x3cb8000000000000_4008000000000000,
434 0x3cac000000000000_3ffc000000000000,
435 0xbc98000000000000_3ff4000000000001,
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;
444 assert_eq!(expected, r.to_bits(), "fmod({:#x}, {:#x})", op1, op2);
449 fn ppc_double_double_fma() {
450 // Sanity check for now.
451 let mut a = "2".parse::<DoubleDouble>().unwrap();
453 "3".parse::<DoubleDouble>().unwrap(),
454 "4".parse::<DoubleDouble>().unwrap(),
457 Some(Ordering::Equal),
458 "10".parse::<DoubleDouble>().unwrap().partial_cmp(&a)
463 fn ppc_double_double_round_to_integral() {
465 let a = "1.5".parse::<DoubleDouble>().unwrap();
466 let a = a.round_to_integral(Round::NearestTiesToEven).value;
468 Some(Ordering::Equal),
469 "2".parse::<DoubleDouble>().unwrap().partial_cmp(&a)
473 let a = "2.5".parse::<DoubleDouble>().unwrap();
474 let a = a.round_to_integral(Round::NearestTiesToEven).value;
476 Some(Ordering::Equal),
477 "2".parse::<DoubleDouble>().unwrap().partial_cmp(&a)
483 fn ppc_double_double_compare() {
489 Some(Ordering::Equal),
491 // (1 + 0) < (1.00...1 + 0)
492 (0x3ff0000000000000, 0x3ff0000000000001, Some(Ordering::Less)),
493 // (1.00...1 + 0) > (1 + 0)
497 Some(Ordering::Greater),
499 // (1 + 0) < (1 + epsilon)
502 0x0000000000000001_3ff0000000000001,
503 Some(Ordering::Less),
506 (0x7ff8000000000000, 0x7ff8000000000000, None),
508 (0x3ff0000000000000, 0x7ff8000000000000, None),
513 Some(Ordering::Equal),
517 for &(op1, op2, expected) in &data {
518 let a1 = DoubleDouble::from_bits(op1);
519 let a2 = DoubleDouble::from_bits(op2);
523 "compare({:#x}, {:#x})",
531 fn ppc_double_double_bitwise_eq() {
534 (0x3ff0000000000000, 0x3ff0000000000000, true),
535 // (1 + 0) != (1.00...1 + 0)
536 (0x3ff0000000000000, 0x3ff0000000000001, false),
538 (0x7ff8000000000000, 0x7ff8000000000000, true),
539 // NaN != NaN with a different bit pattern
542 0x3ff0000000000000_7ff8000000000000,
546 (0x7ff0000000000000, 0x7ff0000000000000, true),
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);
557 fn ppc_double_double_change_sign() {
558 let float = DoubleDouble::from_bits(0xbcb0000000000000_400f000000000000);
560 let actual = float.copy_sign("1".parse::<DoubleDouble>().unwrap());
561 assert_eq!(0xbcb0000000000000_400f000000000000, actual.to_bits());
564 let actual = float.copy_sign("-1".parse::<DoubleDouble>().unwrap());
565 assert_eq!(0x3cb0000000000000_c00f000000000000, actual.to_bits());
570 fn ppc_double_double_factories() {
571 assert_eq!(0, DoubleDouble::ZERO.to_bits());
573 0x7c8ffffffffffffe_7fefffffffffffff,
574 DoubleDouble::largest().to_bits()
576 assert_eq!(0x0000000000000001, DoubleDouble::SMALLEST.to_bits());
579 DoubleDouble::smallest_normalized().to_bits()
582 0x0000000000000000_8000000000000000,
583 (-DoubleDouble::ZERO).to_bits()
586 0xfc8ffffffffffffe_ffefffffffffffff,
587 (-DoubleDouble::largest()).to_bits()
590 0x0000000000000000_8000000000000001,
591 (-DoubleDouble::SMALLEST).to_bits()
594 0x0000000000000000_8360000000000000,
595 (-DoubleDouble::smallest_normalized()).to_bits()
597 assert!(DoubleDouble::SMALLEST.is_smallest());
598 assert!(DoubleDouble::largest().is_largest());
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());
607 // (4 + 3) is not normalized
608 let data = 0x4008000000000000_4010000000000000;
609 assert!(DoubleDouble::from_bits(data).is_denormal());
614 fn ppc_double_double_exact_inverse() {
617 .parse::<DoubleDouble>()
621 .bitwise_eq("0.5".parse::<DoubleDouble>().unwrap())
626 fn ppc_double_double_scalbn() {
628 let input = 0x3cb8000000000000_4008000000000000;
629 let result = DoubleDouble::from_bits(input).scalbn(1);
631 assert_eq!(0x3cc8000000000000_4018000000000000, result.to_bits());
635 fn ppc_double_double_frexp() {
637 let input = 0x3cb8000000000000_4008000000000000;
640 let result = DoubleDouble::from_bits(input).frexp(&mut exp);
642 assert_eq!(0x3c98000000000000_3fe8000000000000, result.to_bits());