1use crate::{
22 special::{bessel_j0, catalan, digamma, erf, erfc, euler_gamma, gamma, ln_gamma},
23 DBig,
24};
25use std::{
26 fmt,
27 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
28 str::FromStr,
29};
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
39pub enum Round {
40 #[default]
42 Nearest,
43 Up,
45 Down,
47 Zero,
49}
50
51#[derive(Clone, Debug)]
61pub struct MpFloat {
62 value: DBig,
63 bits: u32,
64}
65
66impl MpFloat {
67 pub fn with_val(bits: u32, v: f64) -> Self {
81 let prec = bits_to_decimal_prec(bits);
82 let s = format!("{:.prec$e}", v, prec = prec + 5);
83 let d = DBig::from_str(&s)
84 .unwrap_or_else(|_| DBig::from_str(&format!("{v}")).expect("f64 to DBig: fallback"))
85 .with_precision(prec)
86 .value();
87 Self { value: d, bits }
88 }
89
90 pub fn with_val_from(bits: u32, other: &MpFloat) -> Self {
93 let prec = bits_to_decimal_prec(bits);
94 Self {
95 value: other.value.clone().with_precision(prec).value(),
96 bits,
97 }
98 }
99
100 pub fn from_dbig(d: &DBig, bits: u32) -> Self {
102 let prec = bits_to_decimal_prec(bits);
103 Self {
104 value: d.clone().with_precision(prec).value(),
105 bits,
106 }
107 }
108
109 pub fn prec(&self) -> u32 {
115 self.bits
116 }
117
118 pub fn decimal_prec(&self) -> usize {
120 bits_to_decimal_prec(self.bits)
121 }
122
123 pub fn to_f64(&self) -> f64 {
125 self.value.to_string().parse::<f64>().unwrap_or(0.0)
126 }
127
128 pub fn as_dbig(&self) -> &DBig {
130 &self.value
131 }
132
133 pub fn is_zero(&self) -> bool {
139 is_zero_dbig(&self.value)
140 }
141
142 pub fn is_finite(&self) -> bool {
144 true
146 }
147
148 pub fn is_integer(&self) -> bool {
150 is_integer_dbig(&self.value)
151 }
152
153 pub fn is_sign_positive(&self) -> bool {
155 !self.value.to_string().starts_with('-') && !self.is_zero()
156 }
157
158 pub fn is_sign_negative(&self) -> bool {
160 self.value.to_string().starts_with('-') && !self.is_zero()
161 }
162
163 pub fn abs(self) -> Self {
169 let s = self.value.to_string();
170 let positive = s.trim_start_matches('-');
171 let d = DBig::from_str(positive)
172 .unwrap_or_else(|_| self.value.clone())
173 .with_precision(self.decimal_prec())
174 .value();
175 Self {
176 value: d,
177 bits: self.bits,
178 }
179 }
180
181 pub fn sqrt(self) -> Self {
183 if self.is_sign_negative() {
184 return Self::with_val(self.bits, 0.0);
185 }
186 let prec = self.decimal_prec();
187 match crate::elementary::sqrt(&self.value, prec) {
188 Ok(v) => Self {
189 value: v,
190 bits: self.bits,
191 },
192 Err(_) => Self::with_val(self.bits, 0.0),
193 }
194 }
195
196 pub fn exp(self) -> Self {
198 let prec = self.decimal_prec();
199 match crate::elementary::exp(&self.value, prec) {
200 Ok(v) => Self {
201 value: v,
202 bits: self.bits,
203 },
204 Err(_) => Self::with_val(self.bits, 0.0),
205 }
206 }
207
208 pub fn ln(self) -> Self {
210 let prec = self.decimal_prec();
211 match crate::elementary::ln(&self.value, prec) {
212 Ok(v) => Self {
213 value: v,
214 bits: self.bits,
215 },
216 Err(_) => Self::with_val(self.bits, 0.0),
217 }
218 }
219
220 pub fn sin(self) -> Self {
222 let prec = self.decimal_prec();
223 match crate::trig::sin(&self.value, prec) {
224 Ok(v) => Self {
225 value: v,
226 bits: self.bits,
227 },
228 Err(_) => Self::with_val(self.bits, 0.0),
229 }
230 }
231
232 pub fn cos(self) -> Self {
234 let prec = self.decimal_prec();
235 match crate::trig::cos(&self.value, prec) {
236 Ok(v) => Self {
237 value: v,
238 bits: self.bits,
239 },
240 Err(_) => Self::with_val(self.bits, 0.0),
241 }
242 }
243
244 pub fn gamma(self) -> Self {
246 let prec = self.decimal_prec();
247 match gamma(&self.value, prec) {
248 Ok(v) => Self {
249 value: v,
250 bits: self.bits,
251 },
252 Err(_) => Self::with_val(self.bits, f64::NAN),
253 }
254 }
255
256 pub fn gamma_mut(&mut self) {
258 let prec = self.decimal_prec();
259 if let Ok(v) = gamma(&self.value, prec) {
260 self.value = v;
261 }
262 }
263
264 pub fn ln_gamma(self) -> Self {
266 let prec = self.decimal_prec();
267 match ln_gamma(&self.value, prec) {
268 Ok(v) => Self {
269 value: v,
270 bits: self.bits,
271 },
272 Err(_) => Self::with_val(self.bits, f64::NAN),
273 }
274 }
275
276 pub fn ln_gamma_mut(&mut self) {
278 let prec = self.decimal_prec();
279 if let Ok(v) = ln_gamma(&self.value, prec) {
280 self.value = v;
281 }
282 }
283
284 pub fn digamma(self) -> Self {
286 let prec = self.decimal_prec();
287 match digamma(&self.value, prec) {
288 Ok(v) => Self {
289 value: v,
290 bits: self.bits,
291 },
292 Err(_) => Self::with_val(self.bits, f64::NAN),
293 }
294 }
295
296 pub fn digamma_mut(&mut self) {
298 let prec = self.decimal_prec();
299 if let Ok(v) = digamma(&self.value, prec) {
300 self.value = v;
301 }
302 }
303
304 pub fn erf(self) -> Self {
306 let prec = self.decimal_prec();
307 match erf(&self.value, prec) {
308 Ok(v) => Self {
309 value: v,
310 bits: self.bits,
311 },
312 Err(_) => Self::with_val(self.bits, 0.0),
313 }
314 }
315
316 pub fn erf_mut(&mut self) {
318 let prec = self.decimal_prec();
319 if let Ok(v) = erf(&self.value, prec) {
320 self.value = v;
321 }
322 }
323
324 pub fn erfc(self) -> Self {
326 let prec = self.decimal_prec();
327 match erfc(&self.value, prec) {
328 Ok(v) => Self {
329 value: v,
330 bits: self.bits,
331 },
332 Err(_) => Self::with_val(self.bits, 0.0),
333 }
334 }
335
336 pub fn erfc_mut(&mut self) {
338 let prec = self.decimal_prec();
339 if let Ok(v) = erfc(&self.value, prec) {
340 self.value = v;
341 }
342 }
343
344 pub fn j0(self) -> Self {
346 let prec = self.decimal_prec();
347 match bessel_j0(&self.value, prec) {
348 Ok(v) => Self {
349 value: v,
350 bits: self.bits,
351 },
352 Err(_) => Self::with_val(self.bits, 0.0),
353 }
354 }
355
356 pub fn j0_mut(&mut self) {
358 let prec = self.decimal_prec();
359 if let Ok(v) = bessel_j0(&self.value, prec) {
360 self.value = v;
361 }
362 }
363
364 pub fn pow_float(self, exp: &MpFloat) -> Self {
366 let prec = self.decimal_prec();
367 match crate::elementary::pow(&self.value, &exp.value, prec) {
368 Ok(v) => Self {
369 value: v,
370 bits: self.bits,
371 },
372 Err(_) => Self::with_val(self.bits, 0.0),
373 }
374 }
375
376 pub fn pow_i32(self, exp: i32) -> Self {
378 let prec = self.decimal_prec();
379 let exp_d = dbig_f64(exp as f64, prec);
380 match crate::elementary::pow(&self.value, &exp_d, prec) {
381 Ok(v) => Self {
382 value: v,
383 bits: self.bits,
384 },
385 Err(_) => Self::with_val(self.bits, 0.0),
386 }
387 }
388
389 pub fn pow_f64(self, exp: f64) -> Self {
391 let prec = self.decimal_prec();
392 let exp_d = dbig_f64(exp, prec);
393 match crate::elementary::pow(&self.value, &exp_d, prec) {
394 Ok(v) => Self {
395 value: v,
396 bits: self.bits,
397 },
398 Err(_) => Self::with_val(self.bits, 0.0),
399 }
400 }
401}
402
403impl fmt::Display for MpFloat {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 if let Some(prec) = f.precision() {
412 write!(f, "{:.prec$}", self.to_f64(), prec = prec)
413 } else {
414 write!(f, "{}", self.value)
415 }
416 }
417}
418
419impl fmt::LowerExp for MpFloat {
420 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421 if let Some(prec) = f.precision() {
422 write!(f, "{:.prec$e}", self.to_f64(), prec = prec)
423 } else {
424 write!(f, "{:e}", self.to_f64())
425 }
426 }
427}
428
429impl fmt::UpperExp for MpFloat {
430 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
431 if let Some(prec) = f.precision() {
432 write!(f, "{:.prec$E}", self.to_f64(), prec = prec)
433 } else {
434 write!(f, "{:E}", self.to_f64())
435 }
436 }
437}
438
439impl PartialEq for MpFloat {
444 fn eq(&self, other: &Self) -> bool {
445 self.value == other.value
446 }
447}
448
449impl PartialOrd for MpFloat {
450 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
451 self.value.partial_cmp(&other.value)
452 }
453}
454
455impl PartialEq<f64> for MpFloat {
456 fn eq(&self, other: &f64) -> bool {
457 (self.to_f64() - other).abs() < 1e-300
458 }
459}
460
461impl PartialOrd<f64> for MpFloat {
462 fn partial_cmp(&self, other: &f64) -> Option<std::cmp::Ordering> {
463 self.to_f64().partial_cmp(other)
464 }
465}
466
467impl Add for MpFloat {
472 type Output = MpFloat;
473 fn add(self, rhs: MpFloat) -> MpFloat {
474 let prec = self.bits.max(rhs.bits);
475 let d = (&self.value + &rhs.value)
476 .with_precision(bits_to_decimal_prec(prec))
477 .value();
478 MpFloat {
479 value: d,
480 bits: prec,
481 }
482 }
483}
484
485impl Sub for MpFloat {
486 type Output = MpFloat;
487 fn sub(self, rhs: MpFloat) -> MpFloat {
488 let prec = self.bits.max(rhs.bits);
489 let d = (&self.value - &rhs.value)
490 .with_precision(bits_to_decimal_prec(prec))
491 .value();
492 MpFloat {
493 value: d,
494 bits: prec,
495 }
496 }
497}
498
499impl Mul for MpFloat {
500 type Output = MpFloat;
501 fn mul(self, rhs: MpFloat) -> MpFloat {
502 let prec = self.bits.max(rhs.bits);
503 let d = (&self.value * &rhs.value)
504 .with_precision(bits_to_decimal_prec(prec))
505 .value();
506 MpFloat {
507 value: d,
508 bits: prec,
509 }
510 }
511}
512
513impl Div for MpFloat {
514 type Output = MpFloat;
515 fn div(self, rhs: MpFloat) -> MpFloat {
516 let prec = self.bits.max(rhs.bits);
517 let d = (&self.value / &rhs.value)
518 .with_precision(bits_to_decimal_prec(prec))
519 .value();
520 MpFloat {
521 value: d,
522 bits: prec,
523 }
524 }
525}
526
527impl Add<&MpFloat> for MpFloat {
532 type Output = MpFloat;
533 fn add(self, rhs: &MpFloat) -> MpFloat {
534 let prec = self.bits.max(rhs.bits);
535 let d = (&self.value + &rhs.value)
536 .with_precision(bits_to_decimal_prec(prec))
537 .value();
538 MpFloat {
539 value: d,
540 bits: prec,
541 }
542 }
543}
544
545impl Sub<&MpFloat> for MpFloat {
546 type Output = MpFloat;
547 fn sub(self, rhs: &MpFloat) -> MpFloat {
548 let prec = self.bits.max(rhs.bits);
549 let d = (&self.value - &rhs.value)
550 .with_precision(bits_to_decimal_prec(prec))
551 .value();
552 MpFloat {
553 value: d,
554 bits: prec,
555 }
556 }
557}
558
559impl Mul<&MpFloat> for MpFloat {
560 type Output = MpFloat;
561 fn mul(self, rhs: &MpFloat) -> MpFloat {
562 let prec = self.bits.max(rhs.bits);
563 let d = (&self.value * &rhs.value)
564 .with_precision(bits_to_decimal_prec(prec))
565 .value();
566 MpFloat {
567 value: d,
568 bits: prec,
569 }
570 }
571}
572
573impl Div<&MpFloat> for MpFloat {
574 type Output = MpFloat;
575 fn div(self, rhs: &MpFloat) -> MpFloat {
576 let prec = self.bits.max(rhs.bits);
577 let d = (&self.value / &rhs.value)
578 .with_precision(bits_to_decimal_prec(prec))
579 .value();
580 MpFloat {
581 value: d,
582 bits: prec,
583 }
584 }
585}
586
587impl Add<&MpFloat> for &MpFloat {
592 type Output = MpFloat;
593 fn add(self, rhs: &MpFloat) -> MpFloat {
594 let prec = self.bits.max(rhs.bits);
595 let d = (&self.value + &rhs.value)
596 .with_precision(bits_to_decimal_prec(prec))
597 .value();
598 MpFloat {
599 value: d,
600 bits: prec,
601 }
602 }
603}
604
605impl Sub<&MpFloat> for &MpFloat {
606 type Output = MpFloat;
607 fn sub(self, rhs: &MpFloat) -> MpFloat {
608 let prec = self.bits.max(rhs.bits);
609 let d = (&self.value - &rhs.value)
610 .with_precision(bits_to_decimal_prec(prec))
611 .value();
612 MpFloat {
613 value: d,
614 bits: prec,
615 }
616 }
617}
618
619impl Mul<&MpFloat> for &MpFloat {
620 type Output = MpFloat;
621 fn mul(self, rhs: &MpFloat) -> MpFloat {
622 let prec = self.bits.max(rhs.bits);
623 let d = (&self.value * &rhs.value)
624 .with_precision(bits_to_decimal_prec(prec))
625 .value();
626 MpFloat {
627 value: d,
628 bits: prec,
629 }
630 }
631}
632
633impl Div<&MpFloat> for &MpFloat {
634 type Output = MpFloat;
635 fn div(self, rhs: &MpFloat) -> MpFloat {
636 let prec = self.bits.max(rhs.bits);
637 let d = (&self.value / &rhs.value)
638 .with_precision(bits_to_decimal_prec(prec))
639 .value();
640 MpFloat {
641 value: d,
642 bits: prec,
643 }
644 }
645}
646
647impl Add<f64> for MpFloat {
652 type Output = MpFloat;
653 fn add(self, rhs: f64) -> MpFloat {
654 let rhs_mp = MpFloat::with_val(self.bits, rhs);
655 self + rhs_mp
656 }
657}
658
659impl Sub<f64> for MpFloat {
660 type Output = MpFloat;
661 fn sub(self, rhs: f64) -> MpFloat {
662 let rhs_mp = MpFloat::with_val(self.bits, rhs);
663 self - rhs_mp
664 }
665}
666
667impl Mul<f64> for MpFloat {
668 type Output = MpFloat;
669 fn mul(self, rhs: f64) -> MpFloat {
670 let rhs_mp = MpFloat::with_val(self.bits, rhs);
671 self * rhs_mp
672 }
673}
674
675impl Div<f64> for MpFloat {
676 type Output = MpFloat;
677 fn div(self, rhs: f64) -> MpFloat {
678 let rhs_mp = MpFloat::with_val(self.bits, rhs);
679 self / rhs_mp
680 }
681}
682
683impl Add<f64> for &MpFloat {
684 type Output = MpFloat;
685 fn add(self, rhs: f64) -> MpFloat {
686 let rhs_mp = MpFloat::with_val(self.bits, rhs);
687 self + &rhs_mp
688 }
689}
690
691impl Sub<f64> for &MpFloat {
692 type Output = MpFloat;
693 fn sub(self, rhs: f64) -> MpFloat {
694 let rhs_mp = MpFloat::with_val(self.bits, rhs);
695 self - &rhs_mp
696 }
697}
698
699impl Mul<f64> for &MpFloat {
700 type Output = MpFloat;
701 fn mul(self, rhs: f64) -> MpFloat {
702 let rhs_mp = MpFloat::with_val(self.bits, rhs);
703 self * &rhs_mp
704 }
705}
706
707impl Div<f64> for &MpFloat {
708 type Output = MpFloat;
709 fn div(self, rhs: f64) -> MpFloat {
710 let rhs_mp = MpFloat::with_val(self.bits, rhs);
711 self / &rhs_mp
712 }
713}
714
715impl Neg for MpFloat {
720 type Output = MpFloat;
721 fn neg(self) -> MpFloat {
722 let bits = self.bits;
723 let s = self.value.to_string();
724 let neg_s = if let Some(stripped) = s.strip_prefix('-') {
725 stripped.to_string()
726 } else if s == "0" || s == "0.0" {
727 s
728 } else {
729 format!("-{s}")
730 };
731 let d = DBig::from_str(&neg_s)
732 .unwrap_or_else(|_| DBig::from_str("0.0").expect("zero"))
733 .with_precision(bits_to_decimal_prec(bits))
734 .value();
735 MpFloat { value: d, bits }
736 }
737}
738
739impl Neg for &MpFloat {
740 type Output = MpFloat;
741 fn neg(self) -> MpFloat {
742 self.clone().neg()
743 }
744}
745
746impl AddAssign<&MpFloat> for MpFloat {
751 fn add_assign(&mut self, rhs: &MpFloat) {
752 let new = &*self + rhs;
753 *self = new;
754 }
755}
756
757impl AddAssign<MpFloat> for MpFloat {
758 fn add_assign(&mut self, rhs: MpFloat) {
759 let new = &*self + &rhs;
760 *self = new;
761 }
762}
763
764impl AddAssign<f64> for MpFloat {
765 fn add_assign(&mut self, rhs: f64) {
766 let new = self.clone() + rhs;
767 *self = new;
768 }
769}
770
771impl SubAssign<&MpFloat> for MpFloat {
772 fn sub_assign(&mut self, rhs: &MpFloat) {
773 let new = &*self - rhs;
774 *self = new;
775 }
776}
777
778impl SubAssign<MpFloat> for MpFloat {
779 fn sub_assign(&mut self, rhs: MpFloat) {
780 let new = &*self - &rhs;
781 *self = new;
782 }
783}
784
785impl SubAssign<f64> for MpFloat {
786 fn sub_assign(&mut self, rhs: f64) {
787 let new = self.clone() - rhs;
788 *self = new;
789 }
790}
791
792impl MulAssign<&MpFloat> for MpFloat {
793 fn mul_assign(&mut self, rhs: &MpFloat) {
794 let new = &*self * rhs;
795 *self = new;
796 }
797}
798
799impl MulAssign<MpFloat> for MpFloat {
800 fn mul_assign(&mut self, rhs: MpFloat) {
801 let new = &*self * &rhs;
802 *self = new;
803 }
804}
805
806impl MulAssign<f64> for MpFloat {
807 fn mul_assign(&mut self, rhs: f64) {
808 let new = self.clone() * rhs;
809 *self = new;
810 }
811}
812
813impl DivAssign<f64> for MpFloat {
814 fn div_assign(&mut self, rhs: f64) {
815 let new = self.clone() / rhs;
816 *self = new;
817 }
818}
819
820impl DivAssign<MpFloat> for MpFloat {
821 fn div_assign(&mut self, rhs: MpFloat) {
822 let new = self.clone() / rhs;
823 *self = new;
824 }
825}
826
827impl DivAssign<&MpFloat> for MpFloat {
828 fn div_assign(&mut self, rhs: &MpFloat) {
829 let new = self.clone() / rhs;
830 *self = new;
831 }
832}
833
834pub trait MpPow<T> {
840 fn pow(self, exp: T) -> MpFloat;
841}
842
843impl MpPow<&MpFloat> for MpFloat {
844 fn pow(self, exp: &MpFloat) -> MpFloat {
845 self.pow_float(exp)
846 }
847}
848
849impl MpPow<MpFloat> for MpFloat {
850 fn pow(self, exp: MpFloat) -> MpFloat {
851 self.pow_float(&exp)
852 }
853}
854
855impl MpPow<f64> for MpFloat {
856 fn pow(self, exp: f64) -> MpFloat {
857 self.pow_f64(exp)
858 }
859}
860
861impl MpPow<i32> for MpFloat {
862 fn pow(self, exp: i32) -> MpFloat {
863 self.pow_i32(exp)
864 }
865}
866
867#[derive(Clone, Debug)]
877pub struct MpComplex {
878 re: MpFloat,
879 im: MpFloat,
880 bits: u32,
881}
882
883impl MpComplex {
884 pub fn with_val(bits: u32, (re, im): (f64, f64)) -> Self {
895 Self {
896 re: MpFloat::with_val(bits, re),
897 im: MpFloat::with_val(bits, im),
898 bits,
899 }
900 }
901
902 pub fn real(&self) -> &MpFloat {
904 &self.re
905 }
906
907 pub fn imag(&self) -> &MpFloat {
909 &self.im
910 }
911
912 pub fn into_real_imag(self) -> (MpFloat, MpFloat) {
915 (self.re, self.im)
916 }
917
918 pub fn prec(&self) -> u32 {
920 self.bits
921 }
922}
923
924pub fn bits_to_decimal_prec(bits: u32) -> usize {
932 let digits = (bits as f64 * std::f64::consts::LOG2_10.recip()).ceil() as usize;
933 digits.max(10) + 5
934}
935
936pub fn euler_gamma_at_bits(bits: u32) -> MpFloat {
940 let prec = bits_to_decimal_prec(bits);
941 let d = euler_gamma(prec);
942 MpFloat { value: d, bits }
943}
944
945pub fn catalan_at_bits(bits: u32) -> MpFloat {
947 let prec = bits_to_decimal_prec(bits);
948 let d = catalan(prec);
949 MpFloat { value: d, bits }
950}
951
952fn is_zero_dbig(v: &DBig) -> bool {
957 let s = v.to_string().trim_start_matches('-').to_string();
958 s == "0" || s == "0.0" || {
959 if let Some(dot) = s.find('.') {
960 let int = &s[..dot];
961 let frac = &s[dot + 1..];
962 int == "0" && frac.chars().all(|c| c == '0')
963 } else {
964 s.chars().all(|c| c == '0')
965 }
966 }
967}
968
969fn is_integer_dbig(v: &DBig) -> bool {
970 let s = v.to_string().trim_start_matches('-').to_string();
971 if let Some(dot) = s.find('.') {
972 let frac = &s[dot + 1..];
973 frac.chars().all(|c| c == '0')
974 } else {
975 true
976 }
977}
978
979fn dbig_f64(v: f64, precision: usize) -> DBig {
980 let s = format!("{:.prec$e}", v, prec = precision + 5);
981 DBig::from_str(&s)
982 .unwrap_or_else(|_| DBig::from_str(&format!("{v}")).expect("f64 to DBig fallback"))
983 .with_precision(precision)
984 .value()
985}
986
987#[cfg(test)]
992mod tests {
993 use super::*;
994
995 #[test]
996 fn with_val_pi() {
997 let x = MpFloat::with_val(256, std::f64::consts::PI);
998 let v = x.to_f64();
999 assert!((v - std::f64::consts::PI).abs() < 1e-10, "pi = {v}");
1000 }
1001
1002 #[test]
1003 fn arithmetic_ops() {
1004 let a = MpFloat::with_val(128, 3.0);
1005 let b = MpFloat::with_val(128, 2.0);
1006 assert!(((&a + &b).to_f64() - 5.0).abs() < 1e-10);
1007 assert!(((&a - &b).to_f64() - 1.0).abs() < 1e-10);
1008 assert!(((&a * &b).to_f64() - 6.0).abs() < 1e-10);
1009 assert!(((&a / &b).to_f64() - 1.5).abs() < 1e-10);
1010 }
1011
1012 #[test]
1013 fn sqrt_exp_ln() {
1014 let x = MpFloat::with_val(128, 4.0);
1015 let s = x.sqrt();
1016 assert!((s.to_f64() - 2.0).abs() < 1e-8, "sqrt(4) = {}", s.to_f64());
1017
1018 let e = MpFloat::with_val(128, 1.0).exp();
1019 assert!((e.to_f64() - std::f64::consts::E).abs() < 1e-8);
1020
1021 let l = MpFloat::with_val(128, std::f64::consts::E).ln();
1022 assert!((l.to_f64() - 1.0).abs() < 1e-8);
1023 }
1024
1025 #[test]
1026 fn is_zero_predicate() {
1027 let z = MpFloat::with_val(128, 0.0);
1028 let nz = MpFloat::with_val(128, 1.0);
1029 assert!(z.is_zero());
1030 assert!(!nz.is_zero());
1031 }
1032
1033 #[test]
1034 fn is_integer_predicate() {
1035 let i = MpFloat::with_val(128, 5.0);
1036 let f = MpFloat::with_val(128, 5.5);
1037 assert!(i.is_integer());
1038 assert!(!f.is_integer());
1039 }
1040
1041 #[test]
1042 fn gamma_mut_test() {
1043 let mut x = MpFloat::with_val(128, 5.0);
1044 x.gamma_mut();
1045 assert!(
1047 (x.to_f64() - 24.0).abs() < 1e-5,
1048 "gamma(5) = {}",
1049 x.to_f64()
1050 );
1051 }
1052
1053 #[test]
1054 fn erf_mut_test() {
1055 let mut x = MpFloat::with_val(128, 0.0);
1056 x.erf_mut();
1057 assert!(x.is_zero());
1058 }
1059
1060 #[test]
1061 fn neg_operator() {
1062 let x = MpFloat::with_val(128, 3.0);
1063 let neg_x = -x;
1064 assert!(neg_x.is_sign_negative());
1065 assert!((neg_x.to_f64() + 3.0).abs() < 1e-10);
1066 }
1067
1068 #[test]
1069 fn complex_into_parts() {
1070 let z = MpComplex::with_val(128, (1.5_f64, 2.5_f64));
1071 let (re, im) = z.into_real_imag();
1072 assert!((re.to_f64() - 1.5).abs() < 1e-10);
1073 assert!((im.to_f64() - 2.5).abs() < 1e-10);
1074 }
1075
1076 #[test]
1077 fn euler_gamma_const() {
1078 let g = euler_gamma_at_bits(256);
1079 let v = g.to_f64();
1080 assert!((v - 0.5772156649_f64).abs() < 1e-8, "euler_gamma = {v}");
1081 }
1082
1083 #[test]
1084 fn catalan_const() {
1085 let g = catalan_at_bits(256);
1086 let v = g.to_f64();
1087 assert!((v - 0.9159655942_f64).abs() < 1e-8, "catalan = {v}");
1088 }
1089}