1use crate::Float;
10use crate::InnerFloat::{Finite, NaN};
11use crate::float::conversion::primitive_float_from_float::FloatFromFloatError;
12use crate::float::conversion::rational_from_float::RationalFromFloatError;
13use core::cmp::Ordering::{self, *};
14use core::cmp::max;
15use core::mem::swap;
16use core::ops::{Add, Mul, Shl, ShlAssign, Shr, ShrAssign};
17use malachite_base::num::arithmetic::traits::{CeilingLogBase2, Parity, Sqrt, SqrtAssign};
18use malachite_base::num::basic::integers::PrimitiveInt;
19use malachite_base::num::basic::traits::Zero;
20use malachite_base::num::conversion::traits::{ExactFrom, SaturatingInto};
21use malachite_base::num::logic::traits::SignificantBits;
22use malachite_base::rounding_modes::RoundingMode::{self, *};
23use malachite_nz::natural::arithmetic::float_extras::float_can_round;
24use malachite_nz::natural::arithmetic::float_sub::exponent_shift_compare;
25use malachite_nz::platform::Limb;
26use malachite_q::Rational;
27
28pub(crate) fn floor_and_ceiling(
33 (floor, o): (ExtendedFloat, Ordering),
34) -> (ExtendedFloat, ExtendedFloat) {
35 let mut ceiling = floor.clone();
36 if o != Equal {
37 ceiling.increment();
38 }
39 (floor, ceiling)
40}
41
42pub_crate_test_struct! {
43#[derive(Clone)]
44ExtendedFloat {
45 pub(crate) x: Float,
46 pub(crate) exp: i64,
47}}
48
49impl ExtendedFloat {
50 fn is_valid(&self) -> bool {
51 if self.x == 0u32 && self.exp != 0 {
52 return false;
53 }
54 let exp = self.x.get_exponent();
55 exp.is_none() || exp == Some(0)
56 }
57
58 pub(crate) fn from_rational_prec_round(
59 value: Rational,
60 prec: u64,
61 rm: RoundingMode,
62 ) -> (Self, Ordering) {
63 if value == 0 {
64 return (
65 Self {
66 x: Float::ZERO,
67 exp: 0,
68 },
69 Equal,
70 );
71 }
72 let exp = value.floor_log_base_2_abs() + 1;
73 let (x, o) = Float::from_rational_prec_round(value >> exp, prec, rm);
74 let new_exp = x.get_exponent().unwrap();
75 (
76 Self {
77 x: x >> new_exp,
78 exp: i64::from(new_exp) + exp,
79 },
80 o,
81 )
82 }
83
84 pub(crate) fn from_rational_prec_round_ref(
85 value: &Rational,
86 prec: u64,
87 rm: RoundingMode,
88 ) -> (Self, Ordering) {
89 if *value == 0 {
90 return (
91 Self {
92 x: Float::ZERO,
93 exp: 0,
94 },
95 Equal,
96 );
97 }
98 let exp = value.floor_log_base_2_abs() + 1;
99 if exp >= i64::from(Float::MIN_EXPONENT) && exp <= i64::from(Float::MAX_EXPONENT) {
100 let (x, o) = Float::from_rational_prec_round_ref(value, prec, rm);
101 let exp = x.get_exponent().unwrap();
102 return (
103 Self {
104 x: x >> exp,
105 exp: i64::from(exp),
106 },
107 o,
108 );
109 }
110 let (x, o) = Float::from_rational_prec_round(value >> exp, prec, rm);
111 let new_exp = x.get_exponent().unwrap();
112 (
113 Self {
114 x: x >> new_exp,
115 exp: i64::from(new_exp) + exp,
116 },
117 o,
118 )
119 }
120
121 fn add_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) {
122 assert!(self.is_valid());
123 assert!(other.is_valid());
124 assert!(self.x.is_normal());
125 assert!(other.x.is_normal());
126 Self::from_rational_prec_round(
127 Rational::exact_from(self) + Rational::exact_from(other),
128 prec,
129 Nearest,
130 )
131 }
132
133 fn sub_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) {
134 assert!(self.is_valid());
135 assert!(other.is_valid());
136 assert!(self.x.is_normal());
137 assert!(other.x.is_normal());
138 Self::from_rational_prec_round(
139 Rational::exact_from(self) - Rational::exact_from(other),
140 prec,
141 Nearest,
142 )
143 }
144
145 fn sub_prec(self, other: Self, prec: u64) -> (Self, Ordering) {
146 assert!(self.is_valid());
147 assert!(other.is_valid());
148 assert!(self.x.is_normal());
149 assert!(other.x.is_normal());
150 Self::from_rational_prec_round(
151 Rational::exact_from(self) - Rational::exact_from(other),
152 prec,
153 Nearest,
154 )
155 }
156
157 pub(crate) fn mul_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) {
158 assert!(self.is_valid());
159 assert!(other.is_valid());
160 assert!(self.x.is_normal());
161 assert!(other.x.is_normal());
162 let (mut product, o) = self.x.mul_prec_ref_ref(&other.x, prec);
163 let mut product_exp = self.exp + other.exp;
164 let extra_exp = product.get_exponent().unwrap();
165 product >>= extra_exp;
166 product_exp = product_exp.checked_add(i64::from(extra_exp)).unwrap();
167 (
168 Self {
169 x: product,
170 exp: product_exp,
171 },
172 o,
173 )
174 }
175
176 pub(crate) fn div_prec_val_ref(self, other: &Self, prec: u64) -> (Self, Ordering) {
177 assert!(self.is_valid());
178 assert!(other.is_valid());
179 assert!(self.x.is_normal());
180 assert!(other.x.is_normal());
181 let (mut quotient, o) = self.x.div_prec_ref_ref(&other.x, prec);
182 let mut quotient_exp = self.exp - other.exp;
183 let extra_exp = quotient.get_exponent().unwrap();
184 quotient >>= extra_exp;
185 quotient_exp = quotient_exp.checked_add(i64::from(extra_exp)).unwrap();
186 (
187 Self {
188 x: quotient,
189 exp: quotient_exp,
190 },
191 o,
192 )
193 }
194
195 fn div_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering {
196 let mut x = Self {
197 x: Float::ZERO,
198 exp: 0,
199 };
200 swap(self, &mut x);
201 let (q, o) = x.div_prec_val_ref(other, prec);
202 *self = q;
203 o
204 }
205
206 fn square_round_assign(&mut self, rm: RoundingMode) -> Ordering {
207 let mut x = Self {
208 x: Float::ZERO,
209 exp: 0,
210 };
211 swap(self, &mut x);
212 let (mut square, o) = x.x.square_round(rm);
213 let mut square_exp = x.exp << 1;
214 let extra_exp = square.get_exponent().unwrap();
215 square >>= extra_exp;
216 square_exp = square_exp.checked_add(i64::from(extra_exp)).unwrap();
217 *self = Self {
218 x: square,
219 exp: square_exp,
220 };
221 o
222 }
223
224 fn from_extended_float_prec_round(x: Self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
225 if let Ok(x) = Rational::try_from(&x) {
226 Self::from_rational_prec_round(x, prec, rm)
227 } else {
228 (x, Equal)
229 }
230 }
231
232 pub_crate_test! {from_extended_float_prec_round_ref(
233 x: &Self,
234 prec: u64,
235 rm: RoundingMode,
236 ) -> (Self, Ordering) {
237 if let Ok(x) = Rational::try_from(x) {
238 Self::from_rational_prec_round(x, prec, rm)
239 } else {
240 (x.clone(), Equal)
241 }
242 }}
243
244 fn shr_prec_round<T: PrimitiveInt>(
245 self,
246 bits: T,
247 prec: u64,
248 rm: RoundingMode,
249 ) -> (Self, Ordering) {
250 let (out_x, o) = Self::from_extended_float_prec_round(self, prec, rm);
252 let out_exp =
253 i64::exact_from(i128::from(out_x.exp) - SaturatingInto::<i128>::saturating_into(bits));
254 (
255 Self {
256 x: out_x.x,
257 exp: out_exp,
258 },
259 o,
260 )
261 }
262
263 fn shr_round_assign<T: PrimitiveInt>(&mut self, bits: T, _rm: RoundingMode) -> Ordering {
264 if self.x.is_normal() {
266 let out_exp = i64::exact_from(
267 i128::from(self.exp) - SaturatingInto::<i128>::saturating_into(bits),
268 );
269 self.exp = out_exp;
270 }
271 Equal
272 }
273
274 fn shl_round<T: PrimitiveInt>(mut self, bits: T, rm: RoundingMode) -> (Self, Ordering) {
275 let o = self.shl_round_assign(bits, rm);
276 (self, o)
277 }
278
279 fn shl_round_ref<T: PrimitiveInt>(&self, bits: T, _rm: RoundingMode) -> (Self, Ordering) {
280 if self.x.is_normal() {
282 let out_exp = i64::exact_from(
283 i128::from(self.exp) + SaturatingInto::<i128>::saturating_into(bits),
284 );
285 (
286 Self {
287 x: self.x.clone(),
288 exp: out_exp,
289 },
290 Equal,
291 )
292 } else {
293 (self.clone(), Equal)
294 }
295 }
296
297 fn shl_round_assign<T: PrimitiveInt>(&mut self, bits: T, _rm: RoundingMode) -> Ordering {
298 if self.x.is_normal() {
300 let out_exp = i64::exact_from(
301 i128::from(self.exp) + SaturatingInto::<i128>::saturating_into(bits),
302 );
303 self.exp = out_exp;
304 }
305 Equal
306 }
307
308 pub(crate) fn into_float_helper(
309 mut self,
310 prec: u64,
311 rm: RoundingMode,
312 previous_o: Ordering,
313 ) -> (Float, Ordering) {
314 let o = self
315 .x
316 .shl_prec_round_assign_helper(self.exp, prec, rm, previous_o);
317 (self.x, o)
318 }
319
320 pub(crate) fn increment(&mut self) {
321 self.x.increment();
322 if let Some(exp) = self.x.get_exponent()
323 && exp == 1
324 {
325 self.x >>= 1u32;
326 self.exp = 0;
327 }
328 }
329}
330
331impl From<Float> for ExtendedFloat {
332 fn from(value: Float) -> Self {
333 if let Some(exp) = value.get_exponent() {
334 Self {
335 x: value >> exp,
336 exp: i64::from(exp),
337 }
338 } else {
339 Self { x: value, exp: 0 }
340 }
341 }
342}
343
344impl TryFrom<ExtendedFloat> for Float {
345 type Error = FloatFromFloatError;
346
347 fn try_from(value: ExtendedFloat) -> Result<Self, Self::Error> {
348 if value.x.is_normal() {
349 let y = value.x << value.exp;
350 if y.is_normal() {
351 Ok(y)
352 } else {
353 Err(if value.exp > 0 {
354 FloatFromFloatError::Overflow
355 } else {
356 FloatFromFloatError::Underflow
357 })
358 }
359 } else {
360 Ok(value.x)
361 }
362 }
363}
364
365impl TryFrom<ExtendedFloat> for Rational {
366 type Error = RationalFromFloatError;
367
368 #[inline]
369 fn try_from(value: ExtendedFloat) -> Result<Self, Self::Error> {
370 Self::try_from(value.x).map(|x| x << value.exp)
371 }
372}
373
374impl<'a> TryFrom<&'a ExtendedFloat> for Rational {
375 type Error = RationalFromFloatError;
376
377 #[inline]
378 fn try_from(value: &'a ExtendedFloat) -> Result<Self, Self::Error> {
379 Self::try_from(&value.x).map(|x| x << value.exp)
380 }
381}
382
383impl PartialEq for ExtendedFloat {
384 fn eq(&self, other: &Self) -> bool {
385 self.x == other.x && self.exp == other.exp
386 }
387}
388
389impl PartialOrd for ExtendedFloat {
390 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
391 assert!(self.is_valid());
392 assert!(other.is_valid());
393 let self_sign = self.x > 0u32;
394 let other_sign = other.x > 0u32;
395 match self_sign.cmp(&other_sign) {
396 Greater => Some(Greater),
397 Less => Some(Less),
398 Equal => match self.exp.cmp(&other.exp) {
399 Greater => Some(if self_sign { Greater } else { Less }),
400 Less => Some(if self_sign { Less } else { Greater }),
401 Equal => self.x.partial_cmp(&other.x),
402 },
403 }
404 }
405}
406
407impl Add<&ExtendedFloat> for &ExtendedFloat {
408 type Output = ExtendedFloat;
409
410 fn add(self, other: &ExtendedFloat) -> Self::Output {
411 let prec = max(self.x.significant_bits(), other.x.significant_bits());
412 self.add_prec_ref_ref(other, prec).0
413 }
414}
415
416impl Mul<&ExtendedFloat> for &ExtendedFloat {
417 type Output = ExtendedFloat;
418
419 fn mul(self, other: &ExtendedFloat) -> Self::Output {
420 let prec = max(self.x.significant_bits(), other.x.significant_bits());
421 self.mul_prec_ref_ref(other, prec).0
422 }
423}
424
425impl SqrtAssign for ExtendedFloat {
426 fn sqrt_assign(&mut self) {
427 if self.exp.odd() {
428 self.x <<= 1;
429 self.exp = self.exp.checked_sub(1).unwrap();
430 }
431 self.x.sqrt_assign();
432 self.exp >>= 1;
433 if let Some(new_exp) = self.x.get_exponent() {
434 self.exp = self.exp.checked_add(i64::from(new_exp)).unwrap();
435 self.x >>= new_exp;
436 }
437 assert!(self.is_valid());
438 }
439}
440
441impl Sqrt for ExtendedFloat {
442 type Output = Self;
443
444 fn sqrt(mut self) -> Self::Output {
445 self.sqrt_assign();
446 self
447 }
448}
449
450impl Shr<u32> for ExtendedFloat {
451 type Output = Self;
452
453 fn shr(mut self, bits: u32) -> Self::Output {
454 self.shr_round_assign(bits, Nearest);
455 self
456 }
457}
458
459impl ShrAssign<u32> for ExtendedFloat {
460 fn shr_assign(&mut self, bits: u32) {
461 self.shr_round_assign(bits, Nearest);
462 }
463}
464
465impl ShlAssign<u32> for ExtendedFloat {
466 fn shl_assign(&mut self, bits: u32) {
467 self.shl_round_assign(bits, Nearest);
468 }
469}
470
471impl<T: PrimitiveInt> Shl<T> for &ExtendedFloat {
472 type Output = ExtendedFloat;
473
474 fn shl(self, bits: T) -> ExtendedFloat {
475 self.shl_round_ref(bits, Nearest).0
476 }
477}
478
479impl<T: PrimitiveInt> Shl<T> for ExtendedFloat {
480 type Output = Self;
481
482 fn shl(self, bits: T) -> Self {
483 self.shl_round(bits, Nearest).0
484 }
485}
486
487fn cmp2_helper_extended(b: &ExtendedFloat, c: &ExtendedFloat, cancel: &mut u64) -> Ordering {
488 match (&b.x, &c.x) {
489 (
490 Float(Finite {
491 precision: x_prec,
492 significand: x,
493 ..
494 }),
495 Float(Finite {
496 precision: y_prec,
497 significand: y,
498 ..
499 }),
500 ) => {
501 let (o, c) = exponent_shift_compare(
502 x.as_limbs_asc(),
503 b.exp,
504 *x_prec,
505 y.as_limbs_asc(),
506 c.exp,
507 *y_prec,
508 );
509 *cancel = c;
510 o
511 }
512 _ => panic!(),
513 }
514}
515
516pub(crate) fn agm_prec_round_normal_extended(
517 mut a: ExtendedFloat,
518 mut b: ExtendedFloat,
519 prec: u64,
520 rm: RoundingMode,
521) -> (ExtendedFloat, Ordering) {
522 if a.x < 0u32 || b.x < 0u32 {
523 return (
524 ExtendedFloat {
525 x: float_nan!(),
526 exp: 0,
527 },
528 Equal,
529 );
530 }
531 let q = prec;
532 let mut working_prec = q + q.ceiling_log_base_2() + 15;
533 match a.partial_cmp(&b).unwrap() {
535 Equal => return ExtendedFloat::from_extended_float_prec_round(a, prec, rm),
536 Greater => swap(&mut a, &mut b),
537 _ => {}
538 }
539 let mut increment = Limb::WIDTH;
540 let mut v;
541 let mut scaleit;
542 loop {
543 let mut err: u64 = 0;
544 let mut u = a.mul_prec_ref_ref(&b, working_prec).0;
545 v = a.add_prec_ref_ref(&b, working_prec).0;
546 u.sqrt_assign();
547 v >>= 1u32;
548 scaleit = 0;
549 let mut n: u64 = 1;
550 let mut eq = 0;
551 while cmp2_helper_extended(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 {
552 let mut vf;
553 vf = (&u + &v) >> 1;
554 if eq > working_prec >> 2 {
556 let low_p = (working_prec + 1) >> 1;
558 let mut w = v.sub_prec_ref_ref(&u, low_p).0; w.square_round_assign(Nearest); w.shr_round_assign(4, Nearest); w.div_prec_assign_ref(&vf, low_p); let vf_exp = vf.exp;
563 v = vf.sub_prec(w, working_prec).0;
564 err = u64::exact_from(vf_exp - v.exp);
566 break;
567 }
568 let uf = &u * &v;
569 u = uf.sqrt();
570 swap(&mut v, &mut vf);
571 n += 1;
572 }
573 err += (18 * n + 51).ceiling_log_base_2();
578 if (n + 2).ceiling_log_base_2() <= working_prec >> 2
580 && float_can_round(v.x.significand_ref().unwrap(), working_prec - err, q, rm)
581 {
582 break;
583 }
584 working_prec += increment;
585 increment = working_prec >> 1;
586 }
587 v.shr_prec_round(scaleit, prec, rm)
588}
589
590pub_crate_test! {agm_prec_round_normal_ref_ref_extended<'a>(
591 mut a: &'a ExtendedFloat,
592 mut b: &'a ExtendedFloat,
593 prec: u64,
594 rm: RoundingMode,
595) -> (ExtendedFloat, Ordering) {
596 if a.x < 0u32 || b.x < 0u32 {
597 return (
598 ExtendedFloat {
599 x: float_nan!(),
600 exp: 0,
601 },
602 Equal,
603 );
604 }
605 let q = prec;
606 let mut working_prec = q + q.ceiling_log_base_2() + 15;
607 match a.partial_cmp(b).unwrap() {
609 Equal => return ExtendedFloat::from_extended_float_prec_round_ref(a, prec, rm),
610 Greater => swap(&mut a, &mut b),
611 _ => {}
612 }
613 let mut increment = Limb::WIDTH;
614 let mut v;
615 let mut scaleit;
616 loop {
617 let mut err: u64 = 0;
618 let mut u = a.mul_prec_ref_ref(b, working_prec).0;
619 v = a.add_prec_ref_ref(b, working_prec).0;
620 u.sqrt_assign();
621 v >>= 1u32;
622 scaleit = 0;
623 let mut n: u64 = 1;
624 let mut eq = 0;
625 while cmp2_helper_extended(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 {
626 let mut vf;
627 vf = (&u + &v) >> 1;
628 if eq > working_prec >> 2 {
630 let low_p = (working_prec + 1) >> 1;
632 let mut w = v.sub_prec_ref_ref(&u, low_p).0; assert!(w.is_valid());
634 assert!(w.x.is_normal());
635 w.square_round_assign(Nearest); assert!(w.is_valid());
637 assert!(w.x.is_normal());
638 w.shr_round_assign(4, Nearest); assert!(w.is_valid());
640 assert!(w.x.is_normal());
641 w.div_prec_assign_ref(&vf, low_p); let vf_exp = vf.exp;
643 v = vf.sub_prec(w, working_prec).0;
644 err = u64::exact_from(vf_exp - v.exp);
646 break;
647 }
648 let uf = &u * &v;
649 u = uf.sqrt();
650 swap(&mut v, &mut vf);
651 n += 1;
652 }
653 err += (18 * n + 51).ceiling_log_base_2();
658 if (n + 2).ceiling_log_base_2() <= working_prec >> 2
660 && float_can_round(v.x.significand_ref().unwrap(), working_prec - err, q, rm)
661 {
662 break;
663 }
664 working_prec += increment;
665 increment = working_prec >> 1;
666 }
667 v.shr_prec_round(scaleit, prec, rm)
668}}