1 use rustc_apfloat::ppc::DoubleDouble;
2 use rustc_apfloat::{Category, Float, Round};
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".parse::<DoubleDouble>().unwrap();
27 assert_eq!(0x7c8ffffffffffffe_7fefffffffffffff, test.to_bits());
30 let test = "2.00416836000897277799610805135016e-292".parse::<DoubleDouble>().unwrap();
31 assert_eq!(0x0000000000000000_0360000000000000, test.to_bits());
35 fn ppc_double_double_add_special() {
37 // (1 + 0) + (-1 + 0) = Category::Zero
38 (0x3ff0000000000000, 0xbff0000000000000, Category::Zero, Round::NearestTiesToEven),
39 // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = Category::Infinity
41 0x7c8ffffffffffffe_7fefffffffffffff,
44 Round::NearestTiesToEven,
46 // FIXME: change the 4th 0x75effffffffffffe to 0x75efffffffffffff when
47 // DoubleDouble's fallback is gone.
48 // LDBL_MAX + (1.011111... >> (1023 - 106) + (1.1111111...0 >> (1023 -
49 // 160))) = Category::Normal
51 0x7c8ffffffffffffe_7fefffffffffffff,
52 0x75effffffffffffe_7947ffffffffffff,
54 Round::NearestTiesToEven,
56 // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = Category::Infinity
58 0x7c8ffffffffffffe_7fefffffffffffff,
59 0x7c8ffffffffffffe_7fefffffffffffff,
61 Round::NearestTiesToEven,
63 // NaN + (1 + 0) = Category::NaN
64 (0x7ff8000000000000, 0x3ff0000000000000, Category::NaN, Round::NearestTiesToEven),
67 for &(op1, op2, expected, round) in &data {
69 let mut a1 = DoubleDouble::from_bits(op1);
70 let a2 = DoubleDouble::from_bits(op2);
71 a1 = a1.add_r(a2, round).value;
73 assert_eq!(expected, a1.category(), "{:#x} + {:#x}", op1, op2);
76 let a1 = DoubleDouble::from_bits(op1);
77 let mut a2 = DoubleDouble::from_bits(op2);
78 a2 = a2.add_r(a1, round).value;
80 assert_eq!(expected, a2.category(), "{:#x} + {:#x}", op2, op1);
86 fn ppc_double_double_add() {
88 // (1 + 0) + (1e-105 + 0) = (1 + 1e-105)
92 0x3960000000000000_3ff0000000000000,
93 Round::NearestTiesToEven,
95 // (1 + 0) + (1e-106 + 0) = (1 + 1e-106)
99 0x3950000000000000_3ff0000000000000,
100 Round::NearestTiesToEven,
102 // (1 + 1e-106) + (1e-106 + 0) = (1 + 1e-105)
104 0x3950000000000000_3ff0000000000000,
106 0x3960000000000000_3ff0000000000000,
107 Round::NearestTiesToEven,
109 // (1 + 0) + (epsilon + 0) = (1 + epsilon)
113 0x0000000000000001_3ff0000000000000,
114 Round::NearestTiesToEven,
116 // FIXME: change 0xf950000000000000 to 0xf940000000000000, when
117 // DoubleDouble's fallback is gone.
118 // (DBL_MAX - 1 << (1023 - 105)) + (1 << (1023 - 53) + 0) = DBL_MAX +
119 // 1.11111... << (1023 - 52)
121 0xf950000000000000_7fefffffffffffff,
123 0x7c8ffffffffffffe_7fefffffffffffff,
124 Round::NearestTiesToEven,
126 // FIXME: change 0xf950000000000000 to 0xf940000000000000, when
127 // DoubleDouble's fallback is gone.
128 // (1 << (1023 - 53) + 0) + (DBL_MAX - 1 << (1023 - 105)) = DBL_MAX +
129 // 1.11111... << (1023 - 52)
132 0xf950000000000000_7fefffffffffffff,
133 0x7c8ffffffffffffe_7fefffffffffffff,
134 Round::NearestTiesToEven,
138 for &(op1, op2, expected, round) in &data {
140 let mut a1 = DoubleDouble::from_bits(op1);
141 let a2 = DoubleDouble::from_bits(op2);
142 a1 = a1.add_r(a2, round).value;
144 assert_eq!(expected, a1.to_bits(), "{:#x} + {:#x}", op1, op2);
147 let a1 = DoubleDouble::from_bits(op1);
148 let mut a2 = DoubleDouble::from_bits(op2);
149 a2 = a2.add_r(a1, round).value;
151 assert_eq!(expected, a2.to_bits(), "{:#x} + {:#x}", op2, op1);
157 fn ppc_double_double_subtract() {
159 // (1 + 0) - (-1e-105 + 0) = (1 + 1e-105)
163 0x3960000000000000_3ff0000000000000,
164 Round::NearestTiesToEven,
166 // (1 + 0) - (-1e-106 + 0) = (1 + 1e-106)
170 0x3950000000000000_3ff0000000000000,
171 Round::NearestTiesToEven,
175 for &(op1, op2, expected, round) in &data {
176 let mut a1 = DoubleDouble::from_bits(op1);
177 let a2 = DoubleDouble::from_bits(op2);
178 a1 = a1.sub_r(a2, round).value;
180 assert_eq!(expected, a1.to_bits(), "{:#x} - {:#x}", op1, op2);
185 fn ppc_double_double_multiply_special() {
187 // Category::NaN * Category::NaN = Category::NaN
188 (0x7ff8000000000000, 0x7ff8000000000000, Category::NaN, Round::NearestTiesToEven),
189 // Category::NaN * Category::Zero = Category::NaN
190 (0x7ff8000000000000, 0, Category::NaN, Round::NearestTiesToEven),
191 // Category::NaN * Category::Infinity = Category::NaN
192 (0x7ff8000000000000, 0x7ff0000000000000, Category::NaN, Round::NearestTiesToEven),
193 // Category::NaN * Category::Normal = Category::NaN
194 (0x7ff8000000000000, 0x3ff0000000000000, Category::NaN, Round::NearestTiesToEven),
195 // Category::Infinity * Category::Infinity = Category::Infinity
196 (0x7ff0000000000000, 0x7ff0000000000000, Category::Infinity, Round::NearestTiesToEven),
197 // Category::Infinity * Category::Zero = Category::NaN
198 (0x7ff0000000000000, 0, Category::NaN, Round::NearestTiesToEven),
199 // Category::Infinity * Category::Normal = Category::Infinity
200 (0x7ff0000000000000, 0x3ff0000000000000, Category::Infinity, Round::NearestTiesToEven),
201 // Category::Zero * Category::Zero = Category::Zero
202 (0, 0, Category::Zero, Round::NearestTiesToEven),
203 // Category::Zero * Category::Normal = Category::Zero
204 (0, 0x3ff0000000000000, Category::Zero, Round::NearestTiesToEven),
207 for &(op1, op2, expected, round) in &data {
209 let mut a1 = DoubleDouble::from_bits(op1);
210 let a2 = DoubleDouble::from_bits(op2);
211 a1 = a1.mul_r(a2, round).value;
213 assert_eq!(expected, a1.category(), "{:#x} * {:#x}", op1, op2);
216 let a1 = DoubleDouble::from_bits(op1);
217 let mut a2 = DoubleDouble::from_bits(op2);
218 a2 = a2.mul_r(a1, round).value;
220 assert_eq!(expected, a2.category(), "{:#x} * {:#x}", op2, op1);
226 fn ppc_double_double_multiply() {
230 0x3c75555555555556_3fd5555555555555,
233 Round::NearestTiesToEven,
235 // (1 + epsilon) * (1 + 0) = Category::Zero
237 0x0000000000000001_3ff0000000000000,
239 0x0000000000000001_3ff0000000000000,
240 Round::NearestTiesToEven,
242 // (1 + epsilon) * (1 + epsilon) = 1 + 2 * epsilon
244 0x0000000000000001_3ff0000000000000,
245 0x0000000000000001_3ff0000000000000,
246 0x0000000000000002_3ff0000000000000,
247 Round::NearestTiesToEven,
249 // -(1 + epsilon) * (1 + epsilon) = -1
251 0x0000000000000001_bff0000000000000,
252 0x0000000000000001_3ff0000000000000,
254 Round::NearestTiesToEven,
256 // (0.5 + 0) * (1 + 2 * epsilon) = 0.5 + epsilon
259 0x0000000000000002_3ff0000000000000,
260 0x0000000000000001_3fe0000000000000,
261 Round::NearestTiesToEven,
263 // (0.5 + 0) * (1 + epsilon) = 0.5
266 0x0000000000000001_3ff0000000000000,
268 Round::NearestTiesToEven,
270 // __LDBL_MAX__ * (1 + 1 << 106) = inf
272 0x7c8ffffffffffffe_7fefffffffffffff,
273 0x3950000000000000_3ff0000000000000,
275 Round::NearestTiesToEven,
277 // __LDBL_MAX__ * (1 + 1 << 107) > __LDBL_MAX__, but not inf, yes =_=|||
279 0x7c8ffffffffffffe_7fefffffffffffff,
280 0x3940000000000000_3ff0000000000000,
281 0x7c8fffffffffffff_7fefffffffffffff,
282 Round::NearestTiesToEven,
284 // __LDBL_MAX__ * (1 + 1 << 108) = __LDBL_MAX__
286 0x7c8ffffffffffffe_7fefffffffffffff,
287 0x3930000000000000_3ff0000000000000,
288 0x7c8ffffffffffffe_7fefffffffffffff,
289 Round::NearestTiesToEven,
293 for &(op1, op2, expected, round) in &data {
295 let mut a1 = DoubleDouble::from_bits(op1);
296 let a2 = DoubleDouble::from_bits(op2);
297 a1 = a1.mul_r(a2, round).value;
299 assert_eq!(expected, a1.to_bits(), "{:#x} * {:#x}", op1, op2);
302 let a1 = DoubleDouble::from_bits(op1);
303 let mut a2 = DoubleDouble::from_bits(op2);
304 a2 = a2.mul_r(a1, round).value;
306 assert_eq!(expected, a2.to_bits(), "{:#x} * {:#x}", op2, op1);
312 fn ppc_double_double_divide() {
313 // FIXME: Only a sanity check for now. Add more edge cases when the
314 // double-double algorithm is implemented.
320 0x3c75555555555556_3fd5555555555555,
321 Round::NearestTiesToEven,
325 for &(op1, op2, expected, round) in &data {
326 let mut a1 = DoubleDouble::from_bits(op1);
327 let a2 = DoubleDouble::from_bits(op2);
328 a1 = a1.div_r(a2, round).value;
330 assert_eq!(expected, a1.to_bits(), "{:#x} / {:#x}", op1, op2);
335 fn ppc_double_double_remainder() {
337 // ieee_rem(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
339 0x3cb8000000000000_4008000000000000,
340 0x3ca4000000000000_3ff4000000000000,
341 0x3c90000000000000_3fe0000000000000,
343 // ieee_rem(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (-0.5 - 0.5 << 53)
345 0x3cb8000000000000_4008000000000000,
346 0x3cac000000000000_3ffc000000000000,
347 0xbc90000000000000_bfe0000000000000,
351 for &(op1, op2, expected) in &data {
352 let a1 = DoubleDouble::from_bits(op1);
353 let a2 = DoubleDouble::from_bits(op2);
354 let result = a1.ieee_rem(a2).value;
356 assert_eq!(expected, result.to_bits(), "ieee_rem({:#x}, {:#x})", op1, op2);
361 fn ppc_double_double_mod() {
363 // mod(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
365 0x3cb8000000000000_4008000000000000,
366 0x3ca4000000000000_3ff4000000000000,
367 0x3c90000000000000_3fe0000000000000,
369 // mod(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (1.25 + 1.25 << 53)
370 // 0xbc98000000000000 doesn't seem right, but it's what we currently have.
371 // FIXME: investigate
373 0x3cb8000000000000_4008000000000000,
374 0x3cac000000000000_3ffc000000000000,
375 0xbc98000000000000_3ff4000000000001,
379 for &(op1, op2, expected) in &data {
380 let a1 = DoubleDouble::from_bits(op1);
381 let a2 = DoubleDouble::from_bits(op2);
382 let r = (a1 % a2).value;
384 assert_eq!(expected, r.to_bits(), "fmod({:#x}, {:#x})", op1, op2);
389 fn ppc_double_double_fma() {
390 // Sanity check for now.
391 let mut a = "2".parse::<DoubleDouble>().unwrap();
392 a = a.mul_add("3".parse::<DoubleDouble>().unwrap(), "4".parse::<DoubleDouble>().unwrap()).value;
393 assert_eq!(Some(Ordering::Equal), "10".parse::<DoubleDouble>().unwrap().partial_cmp(&a));
397 fn ppc_double_double_round_to_integral() {
399 let a = "1.5".parse::<DoubleDouble>().unwrap();
400 let a = a.round_to_integral(Round::NearestTiesToEven).value;
401 assert_eq!(Some(Ordering::Equal), "2".parse::<DoubleDouble>().unwrap().partial_cmp(&a));
404 let a = "2.5".parse::<DoubleDouble>().unwrap();
405 let a = a.round_to_integral(Round::NearestTiesToEven).value;
406 assert_eq!(Some(Ordering::Equal), "2".parse::<DoubleDouble>().unwrap().partial_cmp(&a));
411 fn ppc_double_double_compare() {
414 (0x3ff0000000000000, 0x3ff0000000000000, Some(Ordering::Equal)),
415 // (1 + 0) < (1.00...1 + 0)
416 (0x3ff0000000000000, 0x3ff0000000000001, Some(Ordering::Less)),
417 // (1.00...1 + 0) > (1 + 0)
418 (0x3ff0000000000001, 0x3ff0000000000000, Some(Ordering::Greater)),
419 // (1 + 0) < (1 + epsilon)
420 (0x3ff0000000000000, 0x0000000000000001_3ff0000000000001, Some(Ordering::Less)),
422 (0x7ff8000000000000, 0x7ff8000000000000, None),
424 (0x3ff0000000000000, 0x7ff8000000000000, None),
426 (0x7ff0000000000000, 0x7ff0000000000000, Some(Ordering::Equal)),
429 for &(op1, op2, expected) in &data {
430 let a1 = DoubleDouble::from_bits(op1);
431 let a2 = DoubleDouble::from_bits(op2);
432 assert_eq!(expected, a1.partial_cmp(&a2), "compare({:#x}, {:#x})", op1, op2,);
437 fn ppc_double_double_bitwise_eq() {
440 (0x3ff0000000000000, 0x3ff0000000000000, true),
441 // (1 + 0) != (1.00...1 + 0)
442 (0x3ff0000000000000, 0x3ff0000000000001, false),
444 (0x7ff8000000000000, 0x7ff8000000000000, true),
445 // NaN != NaN with a different bit pattern
446 (0x7ff8000000000000, 0x3ff0000000000000_7ff8000000000000, false),
448 (0x7ff0000000000000, 0x7ff0000000000000, true),
451 for &(op1, op2, expected) in &data {
452 let a1 = DoubleDouble::from_bits(op1);
453 let a2 = DoubleDouble::from_bits(op2);
454 assert_eq!(expected, a1.bitwise_eq(a2), "{:#x} = {:#x}", op1, op2);
459 fn ppc_double_double_change_sign() {
460 let float = DoubleDouble::from_bits(0xbcb0000000000000_400f000000000000);
462 let actual = float.copy_sign("1".parse::<DoubleDouble>().unwrap());
463 assert_eq!(0xbcb0000000000000_400f000000000000, actual.to_bits());
466 let actual = float.copy_sign("-1".parse::<DoubleDouble>().unwrap());
467 assert_eq!(0x3cb0000000000000_c00f000000000000, actual.to_bits());
472 fn ppc_double_double_factories() {
473 assert_eq!(0, DoubleDouble::ZERO.to_bits());
474 assert_eq!(0x7c8ffffffffffffe_7fefffffffffffff, DoubleDouble::largest().to_bits());
475 assert_eq!(0x0000000000000001, DoubleDouble::SMALLEST.to_bits());
476 assert_eq!(0x0360000000000000, DoubleDouble::smallest_normalized().to_bits());
477 assert_eq!(0x0000000000000000_8000000000000000, (-DoubleDouble::ZERO).to_bits());
478 assert_eq!(0xfc8ffffffffffffe_ffefffffffffffff, (-DoubleDouble::largest()).to_bits());
479 assert_eq!(0x0000000000000000_8000000000000001, (-DoubleDouble::SMALLEST).to_bits());
481 0x0000000000000000_8360000000000000,
482 (-DoubleDouble::smallest_normalized()).to_bits()
484 assert!(DoubleDouble::SMALLEST.is_smallest());
485 assert!(DoubleDouble::largest().is_largest());
489 fn ppc_double_double_is_denormal() {
490 assert!(DoubleDouble::SMALLEST.is_denormal());
491 assert!(!DoubleDouble::largest().is_denormal());
492 assert!(!DoubleDouble::smallest_normalized().is_denormal());
494 // (4 + 3) is not normalized
495 let data = 0x4008000000000000_4010000000000000;
496 assert!(DoubleDouble::from_bits(data).is_denormal());
501 fn ppc_double_double_exact_inverse() {
504 .parse::<DoubleDouble>()
508 .bitwise_eq("0.5".parse::<DoubleDouble>().unwrap())
513 fn ppc_double_double_scalbn() {
515 let input = 0x3cb8000000000000_4008000000000000;
516 let result = DoubleDouble::from_bits(input).scalbn(1);
518 assert_eq!(0x3cc8000000000000_4018000000000000, result.to_bits());
522 fn ppc_double_double_frexp() {
524 let input = 0x3cb8000000000000_4008000000000000;
527 let result = DoubleDouble::from_bits(input).frexp(&mut exp);
529 assert_eq!(0x3c98000000000000_3fe8000000000000, result.to_bits());