1use crate::defs::SignedWord;
4use crate::defs::DEFAULT_P;
5use crate::num::BigFloatNumber;
6use crate::Consts;
7use crate::Error;
8use crate::Exponent;
9use crate::Radix;
10use crate::RoundingMode;
11use crate::Sign;
12use crate::Word;
13use core::num::FpCategory;
14use lazy_static::lazy_static;
15
16#[cfg(feature = "std")]
17use core::fmt::Write;
18
19#[cfg(not(feature = "std"))]
20use alloc::{string::String, vec::Vec};
21
22pub const NAN: BigFloat = BigFloat {
24 inner: Flavor::NaN(None),
25};
26
27pub const INF_POS: BigFloat = BigFloat {
29 inner: Flavor::Inf(Sign::Pos),
30};
31
32pub const INF_NEG: BigFloat = BigFloat {
34 inner: Flavor::Inf(Sign::Neg),
35};
36
37lazy_static! {
38
39 pub static ref ONE: BigFloat = BigFloat { inner: Flavor::Value(BigFloatNumber::from_word(1, DEFAULT_P).expect("Constant ONE initialized")) };
41
42 pub static ref TWO: BigFloat = BigFloat { inner: Flavor::Value(BigFloatNumber::from_word(2, DEFAULT_P).expect("Constant TWO initialized")) };
44}
45
46#[derive(Debug)]
48pub struct BigFloat {
49 inner: Flavor,
50}
51
52#[derive(Debug)]
53enum Flavor {
54 Value(BigFloatNumber),
55 NaN(Option<Error>),
56 Inf(Sign), }
58
59impl BigFloat {
60 pub fn new(p: usize) -> Self {
63 Self::result_to_ext(BigFloatNumber::new(p), false, true)
64 }
65
66 pub fn from_f64(f: f64, p: usize) -> Self {
70 Self::result_to_ext(BigFloatNumber::from_f64(p, f), false, true)
71 }
72
73 pub fn nan(err: Option<Error>) -> Self {
75 BigFloat {
76 inner: Flavor::NaN(err),
77 }
78 }
79
80 pub fn from_f32(f: f32, p: usize) -> Self {
84 Self::result_to_ext(BigFloatNumber::from_f64(p, f as f64), false, true)
85 }
86
87 pub fn is_inf_pos(&self) -> bool {
89 matches!(self.inner, Flavor::Inf(Sign::Pos))
90 }
91
92 pub fn is_inf_neg(&self) -> bool {
94 matches!(self.inner, Flavor::Inf(Sign::Neg))
95 }
96
97 pub fn is_inf(&self) -> bool {
99 matches!(self.inner, Flavor::Inf(_))
100 }
101
102 pub fn is_nan(&self) -> bool {
104 matches!(self.inner, Flavor::NaN(_))
105 }
106
107 pub fn is_int(&self) -> bool {
109 match &self.inner {
110 Flavor::Value(v) => v.is_int(),
111 Flavor::NaN(_) => false,
112 Flavor::Inf(_) => false,
113 }
114 }
115
116 pub fn err(&self) -> Option<Error> {
118 match &self.inner {
119 Flavor::NaN(Some(e)) => Some(*e),
120 _ => None,
121 }
122 }
123
124 pub fn add(&self, d2: &Self, p: usize, rm: RoundingMode) -> Self {
128 self.add_op(d2, p, rm, false)
129 }
130
131 pub fn add_full_prec(&self, d2: &Self) -> Self {
135 self.add_op(d2, 0, RoundingMode::None, true)
136 }
137
138 fn add_op(&self, d2: &Self, p: usize, rm: RoundingMode, full_prec: bool) -> Self {
139 match &self.inner {
140 Flavor::Value(v1) => match &d2.inner {
141 Flavor::Value(v2) => Self::result_to_ext(
142 if full_prec { v1.add_full_prec(v2) } else { v1.add(v2, p, rm) },
143 v1.is_zero(),
144 v1.sign() == v2.sign(),
145 ),
146 Flavor::Inf(s2) => BigFloat {
147 inner: Flavor::Inf(*s2),
148 },
149 Flavor::NaN(err) => Self::nan(*err),
150 },
151 Flavor::Inf(s1) => match &d2.inner {
152 Flavor::Value(_) => BigFloat {
153 inner: Flavor::Inf(*s1),
154 },
155 Flavor::Inf(s2) => {
156 if *s1 != *s2 {
157 NAN
158 } else {
159 BigFloat {
160 inner: Flavor::Inf(*s2),
161 }
162 }
163 }
164 Flavor::NaN(err) => Self::nan(*err),
165 },
166 Flavor::NaN(err) => Self::nan(*err),
167 }
168 }
169
170 pub fn sub(&self, d2: &Self, p: usize, rm: RoundingMode) -> Self {
174 self.sub_op(d2, p, rm, false)
175 }
176
177 pub fn sub_full_prec(&self, d2: &Self) -> Self {
181 self.sub_op(d2, 0, RoundingMode::None, true)
182 }
183
184 fn sub_op(&self, d2: &Self, p: usize, rm: RoundingMode, full_prec: bool) -> Self {
185 match &self.inner {
186 Flavor::Value(v1) => match &d2.inner {
187 Flavor::Value(v2) => Self::result_to_ext(
188 if full_prec { v1.sub_full_prec(v2) } else { v1.sub(v2, p, rm) },
189 v1.is_zero(),
190 v1.sign() == v2.sign(),
191 ),
192 Flavor::Inf(s2) => {
193 if s2.is_positive() {
194 INF_NEG
195 } else {
196 INF_POS
197 }
198 }
199 Flavor::NaN(err) => Self::nan(*err),
200 },
201 Flavor::Inf(s1) => match &d2.inner {
202 Flavor::Value(_) => BigFloat {
203 inner: Flavor::Inf(*s1),
204 },
205 Flavor::Inf(s2) => {
206 if *s1 == *s2 {
207 NAN
208 } else {
209 BigFloat {
210 inner: Flavor::Inf(*s1),
211 }
212 }
213 }
214 Flavor::NaN(err) => Self::nan(*err),
215 },
216 Flavor::NaN(err) => Self::nan(*err),
217 }
218 }
219
220 pub fn mul(&self, d2: &Self, p: usize, rm: RoundingMode) -> Self {
224 self.mul_op(d2, p, rm, false)
225 }
226
227 pub fn mul_full_prec(&self, d2: &Self) -> Self {
231 self.mul_op(d2, 0, RoundingMode::None, true)
232 }
233
234 fn mul_op(&self, d2: &Self, p: usize, rm: RoundingMode, full_prec: bool) -> Self {
235 match &self.inner {
236 Flavor::Value(v1) => {
237 match &d2.inner {
238 Flavor::Value(v2) => Self::result_to_ext(
239 if full_prec { v1.mul_full_prec(v2) } else { v1.mul(v2, p, rm) },
240 v1.is_zero(),
241 v1.sign() == v2.sign(),
242 ),
243 Flavor::Inf(s2) => {
244 if v1.is_zero() {
245 NAN
247 } else {
248 let s = if v1.sign() == *s2 { Sign::Pos } else { Sign::Neg };
249 BigFloat {
250 inner: Flavor::Inf(s),
251 }
252 }
253 }
254 Flavor::NaN(err) => Self::nan(*err),
255 }
256 }
257 Flavor::Inf(s1) => {
258 match &d2.inner {
259 Flavor::Value(v2) => {
260 if v2.is_zero() {
261 NAN
263 } else {
264 let s = if v2.sign() == *s1 { Sign::Pos } else { Sign::Neg };
265 BigFloat {
266 inner: Flavor::Inf(s),
267 }
268 }
269 }
270 Flavor::Inf(s2) => {
271 let s = if s1 == s2 { Sign::Pos } else { Sign::Neg };
272 BigFloat {
273 inner: Flavor::Inf(s),
274 }
275 }
276 Flavor::NaN(err) => Self::nan(*err),
277 }
278 }
279 Flavor::NaN(err) => Self::nan(*err),
280 }
281 }
282
283 pub fn div(&self, d2: &Self, p: usize, rm: RoundingMode) -> Self {
287 match &self.inner {
288 Flavor::Value(v1) => match &d2.inner {
289 Flavor::Value(v2) => {
290 Self::result_to_ext(v1.div(v2, p, rm), v1.is_zero(), v1.sign() == v2.sign())
291 }
292 Flavor::Inf(_) => Self::new(v1.mantissa_max_bit_len()),
293 Flavor::NaN(err) => Self::nan(*err),
294 },
295 Flavor::Inf(s1) => match &d2.inner {
296 Flavor::Value(v) => {
297 if *s1 == v.sign() {
298 INF_POS
299 } else {
300 INF_NEG
301 }
302 }
303 Flavor::Inf(_) => NAN,
304 Flavor::NaN(err) => Self::nan(*err),
305 },
306 Flavor::NaN(err) => Self::nan(*err),
307 }
308 }
309
310 pub fn rem(&self, d2: &Self) -> Self {
312 match &self.inner {
313 Flavor::Value(v1) => match &d2.inner {
314 Flavor::Value(v2) => {
315 Self::result_to_ext(v1.rem(v2), v1.is_zero(), v1.sign() == v2.sign())
316 }
317 Flavor::Inf(_) => self.clone(),
318 Flavor::NaN(err) => Self::nan(*err),
319 },
320 Flavor::Inf(_) => NAN,
321 Flavor::NaN(err) => Self::nan(*err),
322 }
323 }
324
325 #[allow(clippy::should_implement_trait)]
328 pub fn cmp(&self, d2: &BigFloat) -> Option<SignedWord> {
329 match &self.inner {
330 Flavor::Value(v1) => match &d2.inner {
331 Flavor::Value(v2) => Some(v1.cmp(v2)),
332 Flavor::Inf(s2) => {
333 if *s2 == Sign::Pos {
334 Some(-1)
335 } else {
336 Some(1)
337 }
338 }
339 Flavor::NaN(_) => None,
340 },
341 Flavor::Inf(s1) => match &d2.inner {
342 Flavor::Value(_) => Some(*s1 as SignedWord),
343 Flavor::Inf(s2) => Some(*s1 as SignedWord - *s2 as SignedWord),
344 Flavor::NaN(_) => None,
345 },
346 Flavor::NaN(_) => None,
347 }
348 }
349
350 pub fn abs_cmp(&self, d2: &Self) -> Option<SignedWord> {
353 match &self.inner {
354 Flavor::Value(v1) => match &d2.inner {
355 Flavor::Value(v2) => Some(v1.cmp(v2)),
356 Flavor::Inf(_) => Some(-1),
357 Flavor::NaN(_) => None,
358 },
359 Flavor::Inf(_) => match &d2.inner {
360 Flavor::Value(_) => Some(1),
361 Flavor::Inf(_) => Some(0),
362 Flavor::NaN(_) => None,
363 },
364 Flavor::NaN(_) => None,
365 }
366 }
367
368 pub fn inv_sign(&mut self) {
370 match &mut self.inner {
371 Flavor::Value(v1) => v1.inv_sign(),
372 Flavor::Inf(s) => self.inner = Flavor::Inf(s.invert()),
373 Flavor::NaN(_) => {}
374 }
375 }
376
377 pub fn pow(&self, n: &Self, p: usize, rm: RoundingMode, cc: &mut Consts) -> Self {
382 match &self.inner {
383 Flavor::Value(v1) => {
384 match &n.inner {
385 Flavor::Value(v2) => Self::result_to_ext(
386 v1.pow(v2, p, rm, cc),
387 v1.is_zero(),
388 v1.sign() == v2.sign(),
389 ),
390 Flavor::Inf(s2) => {
391 let val = v1.cmp(&crate::common::consts::ONE);
393 if val > 0 {
394 BigFloat {
395 inner: Flavor::Inf(*s2),
396 }
397 } else if val < 0 {
398 Self::new(p)
399 } else {
400 Self::from_u8(1, p)
401 }
402 }
403 Flavor::NaN(err) => Self::nan(*err),
404 }
405 }
406 Flavor::Inf(s1) => {
407 match &n.inner {
408 Flavor::Value(v2) => {
409 if v2.is_zero() {
411 Self::from_u8(1, p)
412 } else if v2.is_positive() {
413 if s1.is_negative() && v2.is_odd_int() {
414 INF_NEG
416 } else {
417 INF_POS
418 }
419 } else {
420 Self::new(p)
421 }
422 }
423 Flavor::Inf(s2) => {
424 if s2.is_positive() {
426 INF_POS
427 } else {
428 Self::new(p)
429 }
430 }
431 Flavor::NaN(err) => Self::nan(*err),
432 }
433 }
434 Flavor::NaN(err) => Self::nan(*err),
435 }
436 }
437
438 pub fn powi(&self, n: usize, p: usize, rm: RoundingMode) -> Self {
442 match &self.inner {
443 Flavor::Value(v1) => Self::result_to_ext(v1.powi(n, p, rm), false, true),
444 Flavor::Inf(s1) => {
445 if n == 0 {
447 Self::from_u8(1, p)
448 } else if s1.is_negative() && (n & 1 == 1) {
449 INF_NEG
450 } else {
451 INF_POS
452 }
453 }
454 Flavor::NaN(err) => Self::nan(*err),
455 }
456 }
457
458 pub fn log(&self, n: &Self, p: usize, rm: RoundingMode, cc: &mut Consts) -> Self {
463 match &self.inner {
464 Flavor::Value(v1) => {
465 match &n.inner {
466 Flavor::Value(v2) => {
467 if v2.is_zero() {
468 return INF_NEG;
469 }
470 Self::result_to_ext(v1.log(v2, p, rm, cc), false, true)
471 }
472 Flavor::Inf(s2) => {
473 if s2.is_positive() {
475 Self::new(p)
476 } else {
477 NAN
478 }
479 }
480 Flavor::NaN(err) => Self::nan(*err),
481 }
482 }
483 Flavor::Inf(s1) => {
484 if *s1 == Sign::Neg {
485 NAN
487 } else {
488 match &n.inner {
489 Flavor::Value(v2) => {
490 if v2.exponent() <= 0 {
492 INF_NEG
493 } else {
494 INF_POS
495 }
496 }
497 Flavor::Inf(_) => NAN, Flavor::NaN(err) => Self::nan(*err),
499 }
500 }
501 }
502 Flavor::NaN(err) => Self::nan(*err),
503 }
504 }
505
506 pub fn is_positive(&self) -> bool {
509 match &self.inner {
510 Flavor::Value(v) => v.is_positive(),
511 Flavor::Inf(s) => *s == Sign::Pos,
512 Flavor::NaN(_) => false,
513 }
514 }
515
516 pub fn is_negative(&self) -> bool {
519 match &self.inner {
520 Flavor::Value(v) => v.is_negative(),
521 Flavor::Inf(s) => *s == Sign::Neg,
522 Flavor::NaN(_) => false,
523 }
524 }
525
526 pub fn is_subnormal(&self) -> bool {
528 if let Flavor::Value(v) = &self.inner {
529 return v.is_subnormal();
530 }
531 false
532 }
533
534 pub fn is_zero(&self) -> bool {
536 match &self.inner {
537 Flavor::Value(v) => v.is_zero(),
538 Flavor::Inf(_) => false,
539 Flavor::NaN(_) => false,
540 }
541 }
542
543 pub fn clamp(&self, min: &Self, max: &Self) -> Self {
547 if self.is_nan() || min.is_nan() || max.is_nan() || max.cmp(min).unwrap() < 0 {
548 NAN
550 } else if self.cmp(min).unwrap() < 0 {
551 min.clone()
553 } else if self.cmp(max).unwrap() > 0 {
554 max.clone()
556 } else {
557 self.clone()
558 }
559 }
560
561 pub fn max(&self, d1: &Self) -> Self {
564 if self.is_nan() || d1.is_nan() {
565 NAN
566 } else if self.cmp(d1).unwrap() < 0 {
567 d1.clone()
569 } else {
570 self.clone()
571 }
572 }
573
574 pub fn min(&self, d1: &Self) -> Self {
577 if self.is_nan() || d1.is_nan() {
578 NAN
579 } else if self.cmp(d1).unwrap() > 0 {
580 d1.clone()
582 } else {
583 self.clone()
584 }
585 }
586
587 pub fn signum(&self) -> Self {
590 if self.is_nan() {
591 NAN
592 } else if self.is_negative() {
593 let mut ret = Self::from_u8(1, DEFAULT_P);
594 ret.inv_sign();
595 ret
596 } else {
597 Self::from_u8(1, DEFAULT_P)
598 }
599 }
600
601 pub fn parse(s: &str, rdx: Radix, p: usize, rm: RoundingMode, cc: &mut Consts) -> Self {
627 match crate::parser::parse(s, rdx) {
628 Ok(ps) => {
629 if ps.is_inf() {
630 if ps.sign() == Sign::Pos {
631 INF_POS
632 } else {
633 INF_NEG
634 }
635 } else if ps.is_nan() {
636 NAN
637 } else {
638 let (m, s, e) = ps.raw_parts();
639 Self::result_to_ext(
640 BigFloatNumber::convert_from_radix(s, m, e, rdx, p, rm, cc),
641 false,
642 true,
643 )
644 }
645 }
646 Err(e) => Self::nan(Some(e)),
647 }
648 }
649
650 #[cfg(feature = "std")]
651 pub(crate) fn write_str<T: Write>(
652 &self,
653 w: &mut T,
654 rdx: Radix,
655 rm: RoundingMode,
656 cc: &mut Consts,
657 ) -> Result<(), core::fmt::Error> {
658 match &self.inner {
659 Flavor::Value(v) => match v.format(rdx, rm, cc) {
660 Ok(s) => w.write_str(&s),
661 Err(e) => match e {
662 Error::ExponentOverflow(s) => {
663 if s.is_positive() {
664 w.write_str("Inf")
665 } else {
666 w.write_str("-Inf")
667 }
668 }
669 _ => w.write_str("Err"),
670 },
671 },
672 Flavor::Inf(sign) => {
673 let s = if sign.is_negative() { "-Inf" } else { "Inf" };
674 w.write_str(s)
675 }
676 crate::ext::Flavor::NaN(_) => w.write_str("NaN"),
677 }
678 }
679
680 pub fn format(&self, rdx: Radix, rm: RoundingMode, cc: &mut Consts) -> Result<String, Error> {
690 let s = match &self.inner {
691 Flavor::Value(v) => match v.format(rdx, rm, cc) {
692 Ok(s) => return Ok(s),
693 Err(e) => match e {
694 Error::ExponentOverflow(s) => {
695 if s.is_positive() {
696 "Inf"
697 } else {
698 "-Inf"
699 }
700 }
701 _ => "Err",
702 },
703 },
704 Flavor::Inf(sign) => {
705 if sign.is_negative() {
706 "-Inf"
707 } else {
708 "Inf"
709 }
710 }
711 crate::ext::Flavor::NaN(_) => "NaN",
712 };
713
714 let mut ret = String::new();
715 ret.try_reserve_exact(s.len())?;
716 ret.push_str(s);
717
718 Ok(ret)
719 }
720
721 #[cfg(feature = "random")]
728 pub fn random_normal(p: usize, exp_from: Exponent, exp_to: Exponent) -> Self {
729 Self::result_to_ext(
730 BigFloatNumber::random_normal(p, exp_from, exp_to),
731 false,
732 true,
733 )
734 }
735
736 pub fn classify(&self) -> FpCategory {
738 match &self.inner {
739 Flavor::Value(v) => {
740 if v.is_subnormal() {
741 FpCategory::Subnormal
742 } else if v.is_zero() {
743 FpCategory::Zero
744 } else {
745 FpCategory::Normal
746 }
747 }
748 Flavor::Inf(_) => FpCategory::Infinite,
749 Flavor::NaN(_) => FpCategory::Nan,
750 }
751 }
752
753 pub fn atan(&self, p: usize, rm: RoundingMode, cc: &mut Consts) -> Self {
758 match &self.inner {
759 Flavor::Value(v) => Self::result_to_ext(v.atan(p, rm, cc), v.is_zero(), true),
760 Flavor::Inf(s) => Self::result_to_ext(Self::half_pi(*s, p, rm, cc), false, true),
761 Flavor::NaN(err) => Self::nan(*err),
762 }
763 }
764
765 pub fn tanh(&self, p: usize, rm: RoundingMode, cc: &mut Consts) -> Self {
770 match &self.inner {
771 Flavor::Value(v) => Self::result_to_ext(v.tanh(p, rm, cc), v.is_zero(), true),
772 Flavor::Inf(s) => Self::from_i8(s.to_int(), p),
773 Flavor::NaN(err) => Self::nan(*err),
774 }
775 }
776
777 fn half_pi(
778 s: Sign,
779 p: usize,
780 rm: RoundingMode,
781 cc: &mut Consts,
782 ) -> Result<BigFloatNumber, Error> {
783 let mut half_pi = cc.pi_num(p, rm)?;
784
785 half_pi.set_exponent(1);
786 half_pi.set_sign(s);
787
788 Ok(half_pi)
789 }
790
791 fn result_to_ext(
792 res: Result<BigFloatNumber, Error>,
793 is_dividend_zero: bool,
794 is_same_sign: bool,
795 ) -> BigFloat {
796 match res {
797 Err(e) => match e {
798 Error::ExponentOverflow(s) => {
799 if s.is_positive() {
800 INF_POS
801 } else {
802 INF_NEG
803 }
804 }
805 Error::DivisionByZero => {
806 if is_dividend_zero {
807 NAN
808 } else if is_same_sign {
809 INF_POS
810 } else {
811 INF_NEG
812 }
813 }
814 Error::MemoryAllocation => Self::nan(Some(Error::MemoryAllocation)),
815 Error::InvalidArgument => Self::nan(Some(Error::InvalidArgument)),
816 },
817 Ok(v) => BigFloat {
818 inner: Flavor::Value(v),
819 },
820 }
821 }
822
823 pub fn exponent(&self) -> Option<Exponent> {
825 match &self.inner {
826 Flavor::Value(v) => Some(v.exponent()),
827 _ => None,
828 }
829 }
830
831 pub fn precision(&self) -> Option<usize> {
835 match &self.inner {
836 Flavor::Value(v) => Some(v.precision()),
837 _ => None,
838 }
839 }
840
841 pub fn max_value(p: usize) -> Self {
846 Self::result_to_ext(BigFloatNumber::max_value(p), false, true)
847 }
848
849 pub fn min_value(p: usize) -> Self {
852 Self::result_to_ext(BigFloatNumber::min_value(p), false, true)
853 }
854
855 pub fn min_positive(p: usize) -> Self {
861 Self::result_to_ext(BigFloatNumber::min_positive(p), false, true)
862 }
863
864 pub fn min_positive_normal(p: usize) -> Self {
870 Self::result_to_ext(BigFloatNumber::min_positive_normal(p), false, true)
871 }
872
873 pub fn from_word(d: Word, p: usize) -> Self {
876 Self::result_to_ext(BigFloatNumber::from_word(d, p), false, true)
877 }
878
879 pub fn neg(&self) -> Self {
881 let mut ret = self.clone();
882 ret.inv_sign();
883 ret
884 }
885
886 pub fn as_raw_parts(&self) -> Option<(&[Word], usize, Sign, Exponent, bool)> {
891 if let Flavor::Value(v) = &self.inner {
892 Some(v.as_raw_parts())
893 } else {
894 None
895 }
896 }
897
898 pub fn from_raw_parts(m: &[Word], n: usize, s: Sign, e: Exponent, inexact: bool) -> Self {
914 Self::result_to_ext(
915 BigFloatNumber::from_raw_parts(m, n, s, e, inexact),
916 false,
917 true,
918 )
919 }
920
921 pub fn from_words(m: &[Word], s: Sign, e: Exponent) -> Self {
929 Self::result_to_ext(BigFloatNumber::from_words(m, s, e), false, true)
930 }
931
932 pub fn sign(&self) -> Option<Sign> {
934 match &self.inner {
935 Flavor::Value(v) => Some(v.sign()),
936 Flavor::Inf(s) => Some(*s),
937 Flavor::NaN(_) => None,
938 }
939 }
940
941 pub fn set_exponent(&mut self, e: Exponent) {
966 if let Flavor::Value(v) = &mut self.inner {
967 v.set_exponent(e)
968 }
969 }
970
971 pub fn mantissa_max_bit_len(&self) -> Option<usize> {
973 if let Flavor::Value(v) = &self.inner {
974 Some(v.mantissa_max_bit_len())
975 } else {
976 None
977 }
978 }
979
980 pub fn set_precision(&mut self, p: usize, rm: RoundingMode) -> Result<(), Error> {
988 if let Flavor::Value(v) = &mut self.inner {
989 v.set_precision(p, rm)
990 } else {
991 Ok(())
992 }
993 }
994
995 pub fn reciprocal(&self, p: usize, rm: RoundingMode) -> Self {
1000 match &self.inner {
1001 Flavor::Value(v) => Self::result_to_ext(v.reciprocal(p, rm), false, v.is_positive()),
1002 Flavor::Inf(s) => {
1003 let mut ret = Self::new(p);
1004 ret.set_sign(*s);
1005 ret
1006 }
1007 Flavor::NaN(err) => Self::nan(*err),
1008 }
1009 }
1010
1011 pub fn set_sign(&mut self, s: Sign) {
1013 match &mut self.inner {
1014 Flavor::Value(v) => v.set_sign(s),
1015 Flavor::Inf(_) => self.inner = Flavor::Inf(s),
1016 Flavor::NaN(_) => {}
1017 };
1018 }
1019
1020 pub fn mantissa_digits(&self) -> Option<&[Word]> {
1022 if let Flavor::Value(v) = &self.inner {
1023 Some(v.mantissa().digits())
1024 } else {
1025 None
1026 }
1027 }
1028
1029 pub fn convert_from_radix(
1067 sign: Sign,
1068 digits: &[u8],
1069 e: Exponent,
1070 rdx: Radix,
1071 p: usize,
1072 rm: RoundingMode,
1073 cc: &mut Consts,
1074 ) -> Self {
1075 Self::result_to_ext(
1076 BigFloatNumber::convert_from_radix(sign, digits, e, rdx, p, rm, cc),
1077 false,
1078 true,
1079 )
1080 }
1081
1082 pub fn convert_to_radix(
1108 &self,
1109 rdx: Radix,
1110 rm: RoundingMode,
1111 cc: &mut Consts,
1112 ) -> Result<(Sign, Vec<u8>, Exponent), Error> {
1113 match &self.inner {
1114 Flavor::Value(v) => v.convert_to_radix(rdx, rm, cc),
1115 Flavor::NaN(_) => Err(Error::InvalidArgument),
1116 Flavor::Inf(_) => Err(Error::InvalidArgument),
1117 }
1118 }
1119
1120 pub fn inexact(&self) -> bool {
1122 if let Flavor::Value(v) = &self.inner {
1123 v.inexact()
1124 } else {
1125 false
1126 }
1127 }
1128
1129 pub fn set_inexact(&mut self, inexact: bool) {
1132 if let Flavor::Value(v) = &mut self.inner {
1133 v.set_inexact(inexact);
1134 }
1135 }
1136
1137 pub fn try_set_precision(&mut self, p: usize, rm: RoundingMode, s: usize) -> bool {
1143 if let Flavor::Value(v) = &mut self.inner {
1144 v.try_set_precision(p, rm, s).unwrap_or_else(|e| {
1145 self.inner = Flavor::NaN(Some(e));
1146 true
1147 })
1148 } else {
1149 true
1150 }
1151 }
1152}
1153
1154impl Clone for BigFloat {
1155 fn clone(&self) -> Self {
1156 match &self.inner {
1157 Flavor::Value(v) => Self::result_to_ext(v.clone(), false, true),
1158 Flavor::Inf(s) => {
1159 if s.is_positive() {
1160 INF_POS
1161 } else {
1162 INF_NEG
1163 }
1164 }
1165 Flavor::NaN(err) => Self::nan(*err),
1166 }
1167 }
1168}
1169
1170macro_rules! gen_wrapper_arg {
1171 ($comment:literal, $fname:ident, $ret:ty, $pos_inf:block, $neg_inf:block, $($arg:ident, $arg_type:ty),*) => {
1173 #[doc=$comment]
1174 pub fn $fname(&self$(,$arg: $arg_type)*) -> $ret {
1175 match &self.inner {
1176 Flavor::Value(v) => Self::result_to_ext(v.$fname($($arg,)*), v.is_zero(), true),
1177 Flavor::Inf(s) => if s.is_positive() $pos_inf else $neg_inf,
1178 Flavor::NaN(err) => Self::nan(*err),
1179 }
1180 }
1181 };
1182}
1183
1184macro_rules! gen_wrapper_arg_rm {
1185 ($comment:literal, $fname:ident, $ret:ty, $pos_inf:block, $neg_inf:block, $($arg:ident, $arg_type:ty),*) => {
1187 #[doc=$comment]
1188 pub fn $fname(&self$(,$arg: $arg_type)*, rm: RoundingMode) -> $ret {
1189 match &self.inner {
1190 Flavor::Value(v) => {
1191 Self::result_to_ext(v.$fname($($arg,)* rm), v.is_zero(), true)
1192 },
1193 Flavor::Inf(s) => if s.is_positive() $pos_inf else $neg_inf,
1194 Flavor::NaN(err) => Self::nan(*err),
1195 }
1196 }
1197 };
1198}
1199
1200macro_rules! gen_wrapper_arg_rm_cc {
1201 ($comment:literal, $fname:ident, $ret:ty, $pos_inf:block, $neg_inf:block, $($arg:ident, $arg_type:ty),*) => {
1203 #[doc=$comment]
1204 pub fn $fname(&self$(,$arg: $arg_type)*, rm: RoundingMode, cc: &mut Consts) -> $ret {
1205 match &self.inner {
1206 Flavor::Value(v) => {
1207 Self::result_to_ext(v.$fname($($arg,)* rm, cc), v.is_zero(), true)
1208 },
1209 Flavor::Inf(s) => if s.is_positive() $pos_inf else $neg_inf,
1210 Flavor::NaN(err) => Self::nan(*err),
1211 }
1212 }
1213 };
1214}
1215
1216macro_rules! gen_wrapper_log {
1217 ($comment:literal, $fname:ident, $ret:ty, $pos_inf:block, $neg_inf:block, $($arg:ident, $arg_type:ty),*) => {
1218 #[doc=$comment]
1219 pub fn $fname(&self$(,$arg: $arg_type)*, rm: RoundingMode, cc: &mut Consts) -> $ret {
1220 match &self.inner {
1221 Flavor::Value(v) => {
1222 if v.is_zero() {
1223 return INF_NEG;
1224 }
1225 Self::result_to_ext(v.$fname($($arg,)* rm, cc), v.is_zero(), true)
1226 },
1227 Flavor::Inf(s) => if s.is_positive() $pos_inf else $neg_inf,
1228 Flavor::NaN(err) => Self::nan(*err),
1229 }
1230 }
1231 };
1232}
1233
1234impl BigFloat {
1235 gen_wrapper_arg!(
1236 "Returns the absolute value of `self`.",
1237 abs,
1238 Self,
1239 { INF_POS },
1240 { INF_POS },
1241 );
1242 gen_wrapper_arg!("Returns the integer part of `self`.", int, Self, { NAN }, {
1243 NAN
1244 },);
1245 gen_wrapper_arg!(
1246 "Returns the fractional part of `self`.",
1247 fract,
1248 Self,
1249 { NAN },
1250 { NAN },
1251 );
1252 gen_wrapper_arg!(
1253 "Returns the smallest integer greater than or equal to `self`.",
1254 ceil,
1255 Self,
1256 { INF_POS },
1257 { INF_NEG },
1258 );
1259 gen_wrapper_arg!(
1260 "Returns the largest integer less than or equal to `self`.",
1261 floor,
1262 Self,
1263 { INF_POS },
1264 { INF_NEG },
1265 );
1266 gen_wrapper_arg_rm!("Returns the rounded number with `n` binary positions in the fractional part of the number using rounding mode `rm`.",
1267 round,
1268 Self,
1269 { INF_POS },
1270 { INF_NEG },
1271 n,
1272 usize
1273 );
1274 gen_wrapper_arg_rm!(
1275 "Computes the square root of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1276 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1277 sqrt,
1278 Self,
1279 { INF_POS },
1280 { NAN },
1281 p,
1282 usize
1283 );
1284 gen_wrapper_arg_rm!(
1285 "Computes the cube root of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1286 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1287 cbrt,
1288 Self,
1289 { INF_POS },
1290 { INF_NEG },
1291 p,
1292 usize
1293 );
1294 gen_wrapper_log!(
1295 "Computes the natural logarithm of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1296 This function requires constants cache `cc` for computing the result.
1297 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1298 ln,
1299 Self,
1300 { INF_POS },
1301 { NAN },
1302 p,
1303 usize
1304 );
1305 gen_wrapper_log!(
1306 "Computes the logarithm base 2 of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1307 This function requires constants cache `cc` for computing the result.
1308 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1309 log2,
1310 Self,
1311 { INF_POS },
1312 { NAN },
1313 p,
1314 usize
1315 );
1316 gen_wrapper_log!(
1317 "Computes the logarithm base 10 of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1318 This function requires constants cache `cc` for computing the result.
1319 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1320 log10,
1321 Self,
1322 { INF_POS },
1323 { NAN },
1324 p,
1325 usize
1326 );
1327 gen_wrapper_arg_rm_cc!(
1328 "Computes `e` to the power of `self` with precision `p`. The result is rounded using the rounding mode `rm`.
1329 This function requires constants cache `cc` for computing the result.
1330 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1331 exp,
1332 Self,
1333 { INF_POS },
1334 { Self::new(p) },
1335 p,
1336 usize
1337 );
1338
1339 gen_wrapper_arg_rm_cc!(
1340 "Computes the sine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1341 This function requires constants cache `cc` for computing the result.
1342 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1343 sin,
1344 Self,
1345 { NAN },
1346 { NAN },
1347 p,
1348 usize
1349 );
1350 gen_wrapper_arg_rm_cc!(
1351 "Computes the cosine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1352 This function requires constants cache `cc` for computing the result.
1353 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1354 cos,
1355 Self,
1356 { NAN },
1357 { NAN },
1358 p,
1359 usize
1360 );
1361 gen_wrapper_arg_rm_cc!(
1362 "Computes the tangent of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1363 This function requires constants cache `cc` for computing the result.
1364 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1365 tan,
1366 Self,
1367 { NAN },
1368 { NAN },
1369 p,
1370 usize
1371 );
1372 gen_wrapper_arg_rm_cc!(
1373 "Computes the arcsine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1374 This function requires constants cache `cc` for computing the result.
1375 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1376 asin,
1377 Self,
1378 {NAN},
1379 {NAN},
1380 p,
1381 usize
1382 );
1383 gen_wrapper_arg_rm_cc!(
1384 "Computes the arccosine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1385 This function requires constants cache `cc` for computing the result.
1386 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1387 acos,
1388 Self,
1389 { NAN },
1390 { NAN },
1391 p,
1392 usize
1393 );
1394
1395 gen_wrapper_arg_rm_cc!(
1396 "Computes the hyperbolic sine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1397 This function requires constants cache cc for computing the result.
1398 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1399 sinh,
1400 Self,
1401 { INF_POS },
1402 { INF_NEG },
1403 p,
1404 usize
1405 );
1406 gen_wrapper_arg_rm_cc!(
1407 "Computes the hyperbolic cosine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1408 This function requires constants cache cc for computing the result.
1409 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1410 cosh,
1411 Self,
1412 { INF_POS },
1413 { INF_POS },
1414 p,
1415 usize
1416 );
1417 gen_wrapper_arg_rm_cc!(
1418 "Computes the hyperbolic arcsine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1419 This function requires constants cache `cc` for computing the result.
1420 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1421 asinh,
1422 Self,
1423 { INF_POS },
1424 { INF_NEG },
1425 p,
1426 usize
1427 );
1428 gen_wrapper_arg_rm_cc!(
1429 "Computes the hyperbolic arccosine of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1430 This function requires constants cache `cc` for computing the result.
1431 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1432 acosh,
1433 Self,
1434 { INF_POS },
1435 { NAN },
1436 p,
1437 usize
1438 );
1439 gen_wrapper_arg_rm_cc!(
1440 "Computes the hyperbolic arctangent of a number with precision `p`. The result is rounded using the rounding mode `rm`.
1441 This function requires constants cache `cc` for computing the result.
1442 Precision is rounded upwards to the word size. The function returns NaN if the precision `p` is incorrect.",
1443 atanh,
1444 Self,
1445 { NAN },
1446 { NAN },
1447 p,
1448 usize
1449 );
1450}
1451
1452macro_rules! impl_int_conv {
1453 ($s:ty, $from_s:ident) => {
1454 impl BigFloat {
1455 pub fn $from_s(i: $s, p: usize) -> Self {
1459 Self::result_to_ext(BigFloatNumber::$from_s(i, p), false, true)
1460 }
1461 }
1462
1463 };
1471}
1472
1473impl_int_conv!(i8, from_i8);
1474impl_int_conv!(i16, from_i16);
1475impl_int_conv!(i32, from_i32);
1476impl_int_conv!(i64, from_i64);
1477impl_int_conv!(i128, from_i128);
1478
1479impl_int_conv!(u8, from_u8);
1480impl_int_conv!(u16, from_u16);
1481impl_int_conv!(u32, from_u32);
1482impl_int_conv!(u64, from_u64);
1483impl_int_conv!(u128, from_u128);
1484
1485impl From<BigFloatNumber> for BigFloat {
1486 fn from(x: BigFloatNumber) -> Self {
1487 BigFloat {
1488 inner: Flavor::Value(x),
1489 }
1490 }
1491}
1492
1493#[cfg(feature = "std")]
1494use core::{
1495 fmt::{Binary, Display, Formatter, Octal, UpperHex},
1496 str::FromStr,
1497};
1498
1499use core::{cmp::Eq, cmp::Ordering, cmp::PartialEq, cmp::PartialOrd, ops::Neg};
1500
1501impl Neg for BigFloat {
1502 type Output = BigFloat;
1503 fn neg(mut self) -> Self::Output {
1504 self.inv_sign();
1505 self
1506 }
1507}
1508
1509impl Neg for &BigFloat {
1510 type Output = BigFloat;
1511 fn neg(self) -> Self::Output {
1512 let mut ret = self.clone();
1513 ret.inv_sign();
1514 ret
1515 }
1516}
1517
1518impl PartialEq for BigFloat {
1523 fn eq(&self, other: &Self) -> bool {
1524 let cmp_result = BigFloat::cmp(self, other);
1525 matches!(cmp_result, Some(0))
1526 }
1527}
1528
1529impl<'a> PartialEq<&'a BigFloat> for BigFloat {
1530 fn eq(&self, other: &&'a BigFloat) -> bool {
1531 let cmp_result = BigFloat::cmp(self, other);
1532 matches!(cmp_result, Some(0))
1533 }
1534}
1535
1536impl Eq for BigFloat {}
1537
1538impl PartialOrd for BigFloat {
1539 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1540 let cmp_result = BigFloat::cmp(self, other);
1541 match cmp_result {
1542 Some(v) => {
1543 if v > 0 {
1544 Some(Ordering::Greater)
1545 } else if v < 0 {
1546 Some(Ordering::Less)
1547 } else {
1548 Some(Ordering::Equal)
1549 }
1550 }
1551 None => None,
1552 }
1553 }
1554}
1555
1556impl<'a> PartialOrd<&'a BigFloat> for BigFloat {
1557 fn partial_cmp(&self, other: &&'a BigFloat) -> Option<Ordering> {
1558 let cmp_result = BigFloat::cmp(self, other);
1559 match cmp_result {
1560 Some(v) => {
1561 if v > 0 {
1562 Some(Ordering::Greater)
1563 } else if v < 0 {
1564 Some(Ordering::Less)
1565 } else {
1566 Some(Ordering::Equal)
1567 }
1568 }
1569 None => None,
1570 }
1571 }
1572}
1573
1574impl Default for BigFloat {
1575 fn default() -> BigFloat {
1576 BigFloat::new(DEFAULT_P)
1577 }
1578}
1579
1580#[cfg(feature = "std")]
1581impl FromStr for BigFloat {
1582 type Err = Error;
1583
1584 fn from_str(src: &str) -> Result<BigFloat, Self::Err> {
1587 let bf = crate::common::consts::TENPOWERS.with(|tp| {
1588 let cc = &mut tp.borrow_mut();
1589 BigFloat::parse(src, Radix::Dec, usize::MAX, RoundingMode::ToEven, cc)
1590 });
1591
1592 if bf.is_nan() {
1593 if let Some(err) = bf.err() {
1594 return Err(err);
1595 }
1596 }
1597
1598 Ok(bf)
1599 }
1600}
1601
1602macro_rules! impl_from {
1603 ($tt:ty, $fn:ident) => {
1604 impl From<$tt> for BigFloat {
1605 fn from(v: $tt) -> Self {
1606 BigFloat::$fn(v, DEFAULT_P)
1607 }
1608 }
1609 };
1610}
1611
1612impl_from!(f32, from_f32);
1613impl_from!(f64, from_f64);
1614impl_from!(i8, from_i8);
1615impl_from!(i16, from_i16);
1616impl_from!(i32, from_i32);
1617impl_from!(i64, from_i64);
1618impl_from!(i128, from_i128);
1619impl_from!(u8, from_u8);
1620impl_from!(u16, from_u16);
1621impl_from!(u32, from_u32);
1622impl_from!(u64, from_u64);
1623impl_from!(u128, from_u128);
1624
1625#[cfg(feature = "std")]
1626macro_rules! impl_format_rdx {
1627 ($trait:ty, $rdx:path) => {
1628 impl $trait for BigFloat {
1629 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
1632 crate::common::consts::TENPOWERS.with(|tp| {
1633 let cc = &mut tp.borrow_mut();
1634 self.write_str(f, $rdx, RoundingMode::ToEven, cc)
1635 })
1636 }
1637 }
1638 };
1639}
1640
1641#[cfg(feature = "std")]
1642impl_format_rdx!(Binary, Radix::Bin);
1643#[cfg(feature = "std")]
1644impl_format_rdx!(Octal, Radix::Oct);
1645#[cfg(feature = "std")]
1646impl_format_rdx!(Display, Radix::Dec);
1647#[cfg(feature = "std")]
1648impl_format_rdx!(UpperHex, Radix::Hex);
1649
1650pub trait FromExt<T> {
1652 fn from_ext(v: T, p: usize, rm: RoundingMode, cc: &mut Consts) -> Self;
1654}
1655
1656impl<T> FromExt<T> for BigFloat
1657where
1658 BigFloat: From<T>,
1659{
1660 fn from_ext(v: T, p: usize, rm: RoundingMode, _cc: &mut Consts) -> Self {
1661 let mut ret = BigFloat::from(v);
1662 if let Err(err) = ret.set_precision(p, rm) {
1663 BigFloat::nan(Some(err))
1664 } else {
1665 ret
1666 }
1667 }
1668}
1669
1670impl FromExt<&str> for BigFloat {
1671 fn from_ext(v: &str, p: usize, rm: RoundingMode, cc: &mut Consts) -> Self {
1672 BigFloat::parse(v, crate::Radix::Dec, p, rm, cc)
1673 }
1674}
1675
1676#[cfg(test)]
1677mod tests {
1678
1679 use crate::common::util::rand_p;
1680 use crate::defs::DEFAULT_P;
1681 use crate::ext::ONE;
1682 use crate::ext::TWO;
1683 use crate::BigFloat;
1684 use crate::Consts;
1685 use crate::Error;
1686 use crate::Radix;
1687 use crate::Sign;
1688 use crate::Word;
1689 use crate::INF_NEG;
1690 use crate::INF_POS;
1691 use crate::NAN;
1692 use crate::{defs::RoundingMode, WORD_BIT_SIZE};
1693
1694 use core::num::FpCategory;
1695 #[cfg(feature = "std")]
1696 use std::str::FromStr;
1697
1698 #[cfg(not(feature = "std"))]
1699 use alloc::format;
1700
1701 #[cfg(target_pointer_width = "32")]
1702 #[test]
1703 fn test_decimal_formatting_round_trip() {
1704 let mut cc = Consts::new().unwrap();
1707 let p = 53;
1708 let rm = RoundingMode::ToEven;
1709 let value = BigFloat::parse("1.0", Radix::Dec, p, rm, &mut cc);
1710
1711 let formatted = value.format(Radix::Dec, rm, &mut cc).unwrap();
1712 assert_eq!(formatted, "1.e+0");
1713
1714 let reparsed = BigFloat::parse(&formatted, Radix::Dec, p, rm, &mut cc);
1715 assert_eq!(reparsed, value);
1716 }
1717
1718 #[test]
1719 fn test_ext() {
1720 let rm = RoundingMode::ToOdd;
1721 let mut cc = Consts::new().unwrap();
1722
1723 let d1 = BigFloat::from_u8(1, rand_p());
1725 assert!(!d1.is_inf());
1726 assert!(!d1.is_nan());
1727 assert!(!d1.is_inf_pos());
1728 assert!(!d1.is_inf_neg());
1729 assert!(d1.is_positive());
1730
1731 let mut d1 = d1.div(&BigFloat::new(rand_p()), rand_p(), rm);
1732 assert!(d1.is_inf());
1733 assert!(!d1.is_nan());
1734 assert!(d1.is_inf_pos());
1735 assert!(!d1.is_inf_neg());
1736 assert!(d1.is_positive());
1737
1738 d1.inv_sign();
1739 assert!(d1.is_inf());
1740 assert!(!d1.is_nan());
1741 assert!(!d1.is_inf_pos());
1742 assert!(d1.is_inf_neg());
1743 assert!(d1.is_negative());
1744
1745 let d1 = BigFloat::new(rand_p()).div(&BigFloat::new(rand_p()), rand_p(), rm);
1746 assert!(!d1.is_inf());
1747 assert!(d1.is_nan());
1748 assert!(!d1.is_inf_pos());
1749 assert!(!d1.is_inf_neg());
1750 assert!(d1.sign().is_none());
1751
1752 for _ in 0..1000 {
1753 let i = rand::random::<i64>();
1754 let d1 = BigFloat::from_i64(i, rand_p());
1755 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1756 assert!(d1.cmp(&n1) == Some(0));
1757
1758 let i = rand::random::<u64>();
1759 let d1 = BigFloat::from_u64(i, rand_p());
1760 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1761 assert!(d1.cmp(&n1) == Some(0));
1762
1763 let i = rand::random::<i128>();
1764 let d1 = BigFloat::from_i128(i, rand_p());
1765 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1766 assert!(d1.cmp(&n1) == Some(0));
1767
1768 let i = rand::random::<u128>();
1769 let d1 = BigFloat::from_u128(i, rand_p());
1770 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1771 assert!(d1.cmp(&n1) == Some(0));
1772 }
1773
1774 assert!(ONE.exponent().is_some());
1775 assert!(INF_POS.exponent().is_none());
1776 assert!(INF_NEG.exponent().is_none());
1777 assert!(NAN.exponent().is_none());
1778
1779 assert!(ONE.as_raw_parts().is_some());
1780 assert!(INF_POS.as_raw_parts().is_none());
1781 assert!(INF_NEG.as_raw_parts().is_none());
1782 assert!(NAN.as_raw_parts().is_none());
1783
1784 assert!(ONE.add(&ONE, rand_p(), rm).cmp(&TWO) == Some(0));
1785 assert!(ONE.add(&INF_POS, rand_p(), rm).is_inf_pos());
1786 assert!(INF_POS.add(&ONE, rand_p(), rm).is_inf_pos());
1787 assert!(ONE.add(&INF_NEG, rand_p(), rm).is_inf_neg());
1788 assert!(INF_NEG.add(&ONE, rand_p(), rm).is_inf_neg());
1789 assert!(INF_POS.add(&INF_POS, rand_p(), rm).is_inf_pos());
1790 assert!(INF_POS.add(&INF_NEG, rand_p(), rm).is_nan());
1791 assert!(INF_NEG.add(&INF_NEG, rand_p(), rm).is_inf_neg());
1792 assert!(INF_NEG.add(&INF_POS, rand_p(), rm).is_nan());
1793
1794 assert!(ONE.add_full_prec(&ONE).cmp(&TWO) == Some(0));
1795 assert!(ONE.add_full_prec(&INF_POS).is_inf_pos());
1796 assert!(INF_POS.add_full_prec(&ONE).is_inf_pos());
1797 assert!(ONE.add_full_prec(&INF_NEG).is_inf_neg());
1798 assert!(INF_NEG.add_full_prec(&ONE).is_inf_neg());
1799 assert!(INF_POS.add_full_prec(&INF_POS).is_inf_pos());
1800 assert!(INF_POS.add_full_prec(&INF_NEG).is_nan());
1801 assert!(INF_NEG.add_full_prec(&INF_NEG).is_inf_neg());
1802 assert!(INF_NEG.add_full_prec(&INF_POS).is_nan());
1803
1804 assert!(ONE.sub_full_prec(&ONE).is_zero());
1805 assert!(ONE.sub_full_prec(&INF_POS).is_inf_neg());
1806 assert!(INF_POS.sub_full_prec(&ONE).is_inf_pos());
1807 assert!(ONE.sub_full_prec(&INF_NEG).is_inf_pos());
1808 assert!(INF_NEG.sub_full_prec(&ONE).is_inf_neg());
1809 assert!(INF_POS.sub_full_prec(&INF_POS).is_nan());
1810 assert!(INF_POS.sub_full_prec(&INF_NEG).is_inf_pos());
1811 assert!(INF_NEG.sub_full_prec(&INF_NEG).is_nan());
1812 assert!(INF_NEG.sub_full_prec(&INF_POS).is_inf_neg());
1813
1814 assert!(ONE.mul_full_prec(&ONE).cmp(&ONE) == Some(0));
1815 assert!(ONE.mul_full_prec(&INF_POS).is_inf_pos());
1816 assert!(INF_POS.mul_full_prec(&ONE).is_inf_pos());
1817 assert!(ONE.mul_full_prec(&INF_NEG).is_inf_neg());
1818 assert!(INF_NEG.mul_full_prec(&ONE).is_inf_neg());
1819 assert!(INF_POS.mul_full_prec(&INF_POS).is_inf_pos());
1820 assert!(INF_POS.mul_full_prec(&INF_NEG).is_inf_neg());
1821 assert!(INF_NEG.mul_full_prec(&INF_NEG).is_inf_pos());
1822 assert!(INF_NEG.mul_full_prec(&INF_POS).is_inf_neg());
1823
1824 assert!(TWO.sub(&ONE, rand_p(), rm).cmp(&ONE) == Some(0));
1825 assert!(ONE.sub(&INF_POS, rand_p(), rm).is_inf_neg());
1826 assert!(INF_POS.sub(&ONE, rand_p(), rm).is_inf_pos());
1827 assert!(ONE.sub(&INF_NEG, rand_p(), rm).is_inf_pos());
1828 assert!(INF_NEG.sub(&ONE, rand_p(), rm).is_inf_neg());
1829 assert!(INF_POS.sub(&INF_POS, rand_p(), rm).is_nan());
1830 assert!(INF_POS.sub(&INF_NEG, rand_p(), rm).is_inf_pos());
1831 assert!(INF_NEG.sub(&INF_NEG, rand_p(), rm).is_nan());
1832 assert!(INF_NEG.sub(&INF_POS, rand_p(), rm).is_inf_neg());
1833
1834 assert!(TWO.mul(&ONE, rand_p(), rm).cmp(&TWO) == Some(0));
1835 assert!(ONE.mul(&INF_POS, rand_p(), rm).is_inf_pos());
1836 assert!(INF_POS.mul(&ONE, rand_p(), rm).is_inf_pos());
1837 assert!(ONE.mul(&INF_NEG, rand_p(), rm).is_inf_neg());
1838 assert!(INF_NEG.mul(&ONE, rand_p(), rm).is_inf_neg());
1839 assert!(ONE.neg().mul(&INF_POS, rand_p(), rm).is_inf_neg());
1840 assert!(ONE.neg().mul(&INF_NEG, rand_p(), rm).is_inf_pos());
1841 assert!(INF_POS.mul(&ONE.neg(), rand_p(), rm).is_inf_neg());
1842 assert!(INF_NEG.mul(&ONE.neg(), rand_p(), rm).is_inf_pos());
1843 assert!(INF_POS.mul(&INF_POS, rand_p(), rm).is_inf_pos());
1844 assert!(INF_POS.mul(&INF_NEG, rand_p(), rm).is_inf_neg());
1845 assert!(INF_NEG.mul(&INF_NEG, rand_p(), rm).is_inf_pos());
1846 assert!(INF_NEG.mul(&INF_POS, rand_p(), rm).is_inf_neg());
1847 assert!(INF_POS.mul(&BigFloat::new(rand_p()), rand_p(), rm).is_nan());
1848 assert!(INF_NEG.mul(&BigFloat::new(rand_p()), rand_p(), rm).is_nan());
1849 assert!(BigFloat::new(rand_p()).mul(&INF_POS, rand_p(), rm).is_nan());
1850 assert!(BigFloat::new(rand_p()).mul(&INF_NEG, rand_p(), rm).is_nan());
1851
1852 assert!(TWO.div(&TWO, rand_p(), rm).cmp(&ONE) == Some(0));
1853 assert!(TWO.div(&INF_POS, rand_p(), rm).is_zero());
1854 assert!(INF_POS.div(&TWO, rand_p(), rm).is_inf_pos());
1855 assert!(TWO.div(&INF_NEG, rand_p(), rm).is_zero());
1856 assert!(INF_NEG.div(&TWO, rand_p(), rm).is_inf_neg());
1857 assert!(TWO.neg().div(&INF_POS, rand_p(), rm).is_zero());
1858 assert!(TWO.neg().div(&INF_NEG, rand_p(), rm).is_zero());
1859 assert!(INF_POS.div(&TWO.neg(), rand_p(), rm).is_inf_neg());
1860 assert!(INF_NEG.div(&TWO.neg(), rand_p(), rm).is_inf_pos());
1861 assert!(INF_POS.div(&INF_POS, rand_p(), rm).is_nan());
1862 assert!(INF_POS.div(&INF_NEG, rand_p(), rm).is_nan());
1863 assert!(INF_NEG.div(&INF_NEG, rand_p(), rm).is_nan());
1864 assert!(INF_NEG.div(&INF_POS, rand_p(), rm).is_nan());
1865 assert!(INF_POS
1866 .div(&BigFloat::new(rand_p()), rand_p(), rm)
1867 .is_inf_pos());
1868 assert!(INF_NEG
1869 .div(&BigFloat::new(rand_p()), rand_p(), rm)
1870 .is_inf_neg());
1871 assert!(BigFloat::new(rand_p())
1872 .div(&INF_POS, rand_p(), rm)
1873 .is_zero());
1874 assert!(BigFloat::new(rand_p())
1875 .div(&INF_NEG, rand_p(), rm)
1876 .is_zero());
1877
1878 assert!(TWO.rem(&TWO).is_zero());
1879 assert!(TWO.rem(&INF_POS).cmp(&TWO) == Some(0));
1880 assert!(INF_POS.rem(&TWO).is_nan());
1881 assert!(TWO.rem(&INF_NEG).cmp(&TWO) == Some(0));
1882 assert!(INF_NEG.rem(&TWO).is_nan());
1883 assert!(TWO.neg().rem(&INF_POS).cmp(&TWO.neg()) == Some(0));
1884 assert!(TWO.neg().rem(&INF_NEG).cmp(&TWO.neg()) == Some(0));
1885 assert!(INF_POS.rem(&TWO.neg()).is_nan());
1886 assert!(INF_NEG.rem(&TWO.neg()).is_nan());
1887 assert!(INF_POS.rem(&INF_POS).is_nan());
1888 assert!(INF_POS.rem(&INF_NEG).is_nan());
1889 assert!(INF_NEG.rem(&INF_NEG).is_nan());
1890 assert!(INF_NEG.rem(&INF_POS).is_nan());
1891 assert!(INF_POS.rem(&BigFloat::new(rand_p())).is_nan());
1892 assert!(INF_NEG.rem(&BigFloat::new(rand_p())).is_nan());
1893 assert!(BigFloat::new(rand_p()).rem(&INF_POS).is_zero());
1894 assert!(BigFloat::new(rand_p()).rem(&INF_NEG).is_zero());
1895
1896 for op in [BigFloat::add, BigFloat::sub, BigFloat::mul, BigFloat::div] {
1897 assert!(op(&NAN, &ONE, rand_p(), rm).is_nan());
1898 assert!(op(&ONE, &NAN, rand_p(), rm).is_nan());
1899 assert!(op(&NAN, &INF_POS, rand_p(), rm).is_nan());
1900 assert!(op(&INF_POS, &NAN, rand_p(), rm).is_nan());
1901 assert!(op(&NAN, &INF_NEG, rand_p(), rm).is_nan());
1902 assert!(op(&INF_NEG, &NAN, rand_p(), rm).is_nan());
1903 assert!(op(&NAN, &NAN, rand_p(), rm).is_nan());
1904 }
1905
1906 assert!(BigFloat::rem(&NAN, &ONE).is_nan());
1907 assert!(BigFloat::rem(&ONE, &NAN).is_nan());
1908 assert!(BigFloat::rem(&NAN, &INF_POS).is_nan());
1909 assert!(BigFloat::rem(&INF_POS, &NAN).is_nan());
1910 assert!(BigFloat::rem(&NAN, &INF_NEG).is_nan());
1911 assert!(BigFloat::rem(&INF_NEG, &NAN).is_nan());
1912 assert!(BigFloat::rem(&NAN, &NAN).is_nan());
1913
1914 for op in [BigFloat::add_full_prec, BigFloat::sub_full_prec, BigFloat::mul_full_prec] {
1915 assert!(op(&NAN, &ONE).is_nan());
1916 assert!(op(&ONE, &NAN).is_nan());
1917 assert!(op(&NAN, &INF_POS).is_nan());
1918 assert!(op(&INF_POS, &NAN).is_nan());
1919 assert!(op(&NAN, &INF_NEG).is_nan());
1920 assert!(op(&INF_NEG, &NAN).is_nan());
1921 assert!(op(&NAN, &NAN).is_nan());
1922 }
1923
1924 assert!(ONE.cmp(&ONE).unwrap() == 0);
1925 assert!(ONE.cmp(&INF_POS).unwrap() < 0);
1926 assert!(INF_POS.cmp(&ONE).unwrap() > 0);
1927 assert!(INF_POS.cmp(&INF_POS).unwrap() == 0);
1928 assert!(ONE.cmp(&INF_NEG).unwrap() > 0);
1929 assert!(INF_NEG.cmp(&ONE).unwrap() < 0);
1930 assert!(INF_NEG.cmp(&INF_NEG).unwrap() == 0);
1931 assert!(INF_POS.cmp(&INF_NEG).unwrap() > 0);
1932 assert!(INF_NEG.cmp(&INF_POS).unwrap() < 0);
1933 assert!(INF_POS.cmp(&INF_POS).unwrap() == 0);
1934 assert!(ONE.cmp(&NAN).is_none());
1935 assert!(NAN.cmp(&ONE).is_none());
1936 assert!(INF_POS.cmp(&NAN).is_none());
1937 assert!(NAN.cmp(&INF_POS).is_none());
1938 assert!(INF_NEG.cmp(&NAN).is_none());
1939 assert!(NAN.cmp(&INF_NEG).is_none());
1940 assert!(NAN.cmp(&NAN).is_none());
1941
1942 assert!(ONE.abs_cmp(&ONE).unwrap() == 0);
1943 assert!(ONE.abs_cmp(&INF_POS).unwrap() < 0);
1944 assert!(INF_POS.abs_cmp(&ONE).unwrap() > 0);
1945 assert!(INF_POS.abs_cmp(&INF_POS).unwrap() == 0);
1946 assert!(ONE.abs_cmp(&INF_NEG).unwrap() < 0);
1947 assert!(INF_NEG.abs_cmp(&ONE).unwrap() > 0);
1948 assert!(INF_NEG.abs_cmp(&INF_NEG).unwrap() == 0);
1949 assert!(INF_POS.abs_cmp(&INF_NEG).unwrap() == 0);
1950 assert!(INF_NEG.abs_cmp(&INF_POS).unwrap() == 0);
1951 assert!(INF_POS.abs_cmp(&INF_POS).unwrap() == 0);
1952 assert!(ONE.abs_cmp(&NAN).is_none());
1953 assert!(NAN.abs_cmp(&ONE).is_none());
1954 assert!(INF_POS.abs_cmp(&NAN).is_none());
1955 assert!(NAN.abs_cmp(&INF_POS).is_none());
1956 assert!(INF_NEG.abs_cmp(&NAN).is_none());
1957 assert!(NAN.abs_cmp(&INF_NEG).is_none());
1958 assert!(NAN.abs_cmp(&NAN).is_none());
1959
1960 assert!(ONE.is_positive());
1961 assert!(!ONE.is_negative());
1962
1963 assert!(ONE.neg().is_negative());
1964 assert!(!ONE.neg().is_positive());
1965 assert!(!INF_POS.is_negative());
1966 assert!(INF_POS.is_positive());
1967 assert!(INF_NEG.is_negative());
1968 assert!(!INF_NEG.is_positive());
1969 assert!(!NAN.is_positive());
1970 assert!(!NAN.is_negative());
1971
1972 assert!(ONE.pow(&ONE, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
1973 assert!(BigFloat::new(DEFAULT_P)
1974 .pow(&INF_POS, rand_p(), rm, &mut cc)
1975 .is_zero());
1976 assert!(BigFloat::new(DEFAULT_P)
1977 .pow(&INF_NEG, rand_p(), rm, &mut cc)
1978 .is_zero());
1979 assert!(ONE.pow(&INF_POS, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
1980 assert!(ONE.pow(&INF_NEG, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
1981 assert!(TWO.pow(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
1982 assert!(TWO.pow(&INF_NEG, rand_p(), rm, &mut cc).is_inf_neg());
1983 assert!(INF_POS.pow(&ONE, rand_p(), rm, &mut cc).is_inf_pos());
1984 assert!(INF_NEG.pow(&ONE, rand_p(), rm, &mut cc).is_inf_neg());
1985 assert!(INF_NEG.pow(&TWO, rand_p(), rm, &mut cc).is_inf_pos());
1986 assert!(INF_NEG
1987 .pow(&BigFloat::from_f64(10.2, DEFAULT_P), rand_p(), rm, &mut cc)
1988 .is_inf_pos());
1989 assert!(INF_NEG
1990 .pow(&BigFloat::from_f64(3.0, DEFAULT_P), rand_p(), rm, &mut cc)
1991 .is_inf_neg());
1992 assert!(INF_POS.pow(&ONE.neg(), rand_p(), rm, &mut cc).is_zero());
1993 assert!(INF_NEG.pow(&ONE.neg(), rand_p(), rm, &mut cc).is_zero());
1994 assert!(
1995 INF_POS
1996 .pow(&BigFloat::new(DEFAULT_P), rand_p(), rm, &mut cc)
1997 .cmp(&ONE)
1998 == Some(0)
1999 );
2000 assert!(
2001 INF_NEG
2002 .pow(&BigFloat::new(DEFAULT_P), rand_p(), rm, &mut cc)
2003 .cmp(&ONE)
2004 == Some(0)
2005 );
2006 assert!(INF_POS.pow(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
2007 assert!(INF_NEG.pow(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
2008 assert!(INF_POS.pow(&INF_NEG, rand_p(), rm, &mut cc).is_zero());
2009 assert!(INF_NEG.pow(&INF_NEG, rand_p(), rm, &mut cc).is_zero());
2010
2011 let half = ONE.div(&TWO, rand_p(), rm);
2012 assert!(TWO.log(&TWO, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
2013 assert!(TWO.log(&INF_POS, rand_p(), rm, &mut cc).is_zero());
2014 assert!(TWO.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2015 assert!(INF_POS.log(&TWO, rand_p(), rm, &mut cc).is_inf_pos());
2016 assert!(INF_NEG.log(&TWO, rand_p(), rm, &mut cc).is_nan());
2017 assert!(half.log(&half, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
2018 assert!(half.log(&INF_POS, rand_p(), rm, &mut cc).is_zero());
2019 assert!(half.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2020 assert!(INF_POS.log(&half, rand_p(), rm, &mut cc).is_inf_neg());
2021 assert!(INF_NEG.log(&half, rand_p(), rm, &mut cc).is_nan());
2022 assert!(INF_POS.log(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2023 assert!(INF_POS.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2024 assert!(INF_NEG.log(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2025 assert!(INF_NEG.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2026 assert!(TWO.log(&ONE, rand_p(), rm, &mut cc).is_inf_pos());
2027 assert!(half.log(&ONE, rand_p(), rm, &mut cc).is_inf_pos());
2028 assert!(ONE.log(&ONE, rand_p(), rm, &mut cc).is_nan());
2029
2030 assert!(BigFloat::from_f32(f32::NAN, DEFAULT_P).is_nan());
2031 assert!(BigFloat::from_f32(f32::INFINITY, DEFAULT_P).is_inf_pos());
2032 assert!(BigFloat::from_f32(f32::NEG_INFINITY, DEFAULT_P).is_inf_neg());
2033 assert!(!BigFloat::from_f32(1.0, DEFAULT_P).is_nan());
2034 assert!(BigFloat::from_f64(f64::NAN, DEFAULT_P).is_nan());
2035 assert!(BigFloat::from_f64(f64::INFINITY, DEFAULT_P).is_inf_pos());
2036 assert!(BigFloat::from_f64(f64::NEG_INFINITY, DEFAULT_P).is_inf_neg());
2037 assert!(!BigFloat::from_f64(1.0, DEFAULT_P).is_nan());
2038
2039 assert!(ONE.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2040 assert!(NAN.pow(&ONE, rand_p(), rm, &mut cc).is_nan());
2041 assert!(INF_POS.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2042 assert!(NAN.pow(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2043 assert!(INF_NEG.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2044 assert!(NAN.pow(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2045 assert!(NAN.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2046
2047 assert!(NAN.powi(2, rand_p(), rm).is_nan());
2048 assert!(NAN.powi(0, rand_p(), rm).is_nan());
2049 assert!(INF_POS.powi(2, rand_p(), rm).is_inf_pos());
2050 assert!(INF_POS.powi(3, rand_p(), rm).is_inf_pos());
2051 assert!(INF_NEG.powi(4, rand_p(), rm).is_inf_pos());
2052 assert!(INF_NEG.powi(5, rand_p(), rm).is_inf_neg());
2053 assert!(INF_POS.powi(0, rand_p(), rm).cmp(&ONE) == Some(0));
2054 assert!(INF_NEG.powi(0, rand_p(), rm).cmp(&ONE) == Some(0));
2055
2056 assert!(TWO.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2057 assert!(NAN.log(&TWO, rand_p(), rm, &mut cc).is_nan());
2058 assert!(INF_POS.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2059 assert!(NAN.log(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2060 assert!(INF_NEG.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2061 assert!(NAN.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2062 assert!(NAN.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2063
2064 assert!(INF_NEG.abs().is_inf_pos());
2065 assert!(INF_POS.abs().is_inf_pos());
2066 assert!(NAN.abs().is_nan());
2067
2068 assert!(INF_NEG.int().is_nan());
2069 assert!(INF_POS.int().is_nan());
2070 assert!(NAN.int().is_nan());
2071
2072 assert!(INF_NEG.fract().is_nan());
2073 assert!(INF_POS.fract().is_nan());
2074 assert!(NAN.fract().is_nan());
2075
2076 assert!(INF_NEG.ceil().is_inf_neg());
2077 assert!(INF_POS.ceil().is_inf_pos());
2078 assert!(NAN.ceil().is_nan());
2079
2080 assert!(INF_NEG.floor().is_inf_neg());
2081 assert!(INF_POS.floor().is_inf_pos());
2082 assert!(NAN.floor().is_nan());
2083
2084 for rm in [
2085 RoundingMode::Up,
2086 RoundingMode::Down,
2087 RoundingMode::ToZero,
2088 RoundingMode::FromZero,
2089 RoundingMode::ToEven,
2090 RoundingMode::ToOdd,
2091 ] {
2092 assert!(INF_NEG.round(0, rm).is_inf_neg());
2093 assert!(INF_POS.round(0, rm).is_inf_pos());
2094 assert!(NAN.round(0, rm).is_nan());
2095 }
2096
2097 assert!(INF_NEG.sqrt(rand_p(), rm).is_nan());
2098 assert!(INF_POS.sqrt(rand_p(), rm).is_inf_pos());
2099 assert!(NAN.sqrt(rand_p(), rm).is_nan());
2100
2101 assert!(INF_NEG.cbrt(rand_p(), rm).is_inf_neg());
2102 assert!(INF_POS.cbrt(rand_p(), rm).is_inf_pos());
2103 assert!(NAN.cbrt(rand_p(), rm).is_nan());
2104
2105 for op in [BigFloat::ln, BigFloat::log2, BigFloat::log10] {
2106 assert!(op(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2107 assert!(op(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
2108 assert!(op(&NAN, rand_p(), rm, &mut cc).is_nan());
2109 }
2110
2111 assert!(INF_NEG.exp(rand_p(), rm, &mut cc).is_zero());
2112 assert!(INF_POS.exp(rand_p(), rm, &mut cc).is_inf_pos());
2113 assert!(NAN.exp(rand_p(), rm, &mut cc).is_nan());
2114
2115 assert!(INF_NEG.sin(rand_p(), rm, &mut cc).is_nan());
2116 assert!(INF_POS.sin(rand_p(), rm, &mut cc).is_nan());
2117 assert!(NAN.sin(rand_p(), rm, &mut cc).is_nan());
2118
2119 assert!(INF_NEG.cos(rand_p(), rm, &mut cc).is_nan());
2120 assert!(INF_POS.cos(rand_p(), rm, &mut cc).is_nan());
2121 assert!(NAN.cos(rand_p(), rm, &mut cc).is_nan());
2122
2123 assert!(INF_NEG.tan(rand_p(), rm, &mut cc).is_nan());
2124 assert!(INF_POS.tan(rand_p(), rm, &mut cc).is_nan());
2125 assert!(NAN.tan(rand_p(), rm, &mut cc).is_nan());
2126
2127 assert!(INF_NEG.asin(rand_p(), rm, &mut cc).is_nan());
2128 assert!(INF_POS.asin(rand_p(), rm, &mut cc).is_nan());
2129 assert!(NAN.asin(rand_p(), rm, &mut cc).is_nan());
2130
2131 assert!(INF_NEG.acos(rand_p(), rm, &mut cc).is_nan());
2132 assert!(INF_POS.acos(rand_p(), rm, &mut cc).is_nan());
2133 assert!(NAN.acos(rand_p(), rm, &mut cc).is_nan());
2134
2135 let p = rand_p();
2136 let mut half_pi: BigFloat = cc.pi_num(p, rm).unwrap().into();
2137 half_pi.set_exponent(1);
2138 assert!(INF_NEG.atan(p, rm, &mut cc).cmp(&half_pi.neg()) == Some(0));
2139 assert!(INF_POS.atan(p, rm, &mut cc).cmp(&half_pi) == Some(0));
2140 assert!(NAN.atan(rand_p(), rm, &mut cc).is_nan());
2141
2142 assert!(INF_NEG.sinh(rand_p(), rm, &mut cc).is_inf_neg());
2143 assert!(INF_POS.sinh(rand_p(), rm, &mut cc).is_inf_pos());
2144 assert!(NAN.sinh(rand_p(), rm, &mut cc).is_nan());
2145
2146 assert!(INF_NEG.cosh(rand_p(), rm, &mut cc).is_inf_pos());
2147 assert!(INF_POS.cosh(rand_p(), rm, &mut cc).is_inf_pos());
2148 assert!(NAN.cosh(rand_p(), rm, &mut cc).is_nan());
2149
2150 assert!(INF_NEG.tanh(rand_p(), rm, &mut cc).cmp(&ONE.neg()) == Some(0));
2151 assert!(INF_POS.tanh(rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
2152 assert!(NAN.tanh(rand_p(), rm, &mut cc).is_nan());
2153
2154 assert!(INF_NEG.asinh(rand_p(), rm, &mut cc).is_inf_neg());
2155 assert!(INF_POS.asinh(rand_p(), rm, &mut cc).is_inf_pos());
2156 assert!(NAN.asinh(rand_p(), rm, &mut cc).is_nan());
2157
2158 assert!(INF_NEG.acosh(rand_p(), rm, &mut cc).is_nan());
2159 assert!(INF_POS.acosh(rand_p(), rm, &mut cc).is_inf_pos());
2160 assert!(NAN.acosh(rand_p(), rm, &mut cc).is_nan());
2161
2162 assert!(INF_NEG.atanh(rand_p(), rm, &mut cc).is_nan());
2163 assert!(INF_POS.atanh(rand_p(), rm, &mut cc).is_nan());
2164 assert!(NAN.atanh(rand_p(), rm, &mut cc).is_nan());
2165
2166 assert!(INF_NEG.reciprocal(rand_p(), rm).is_zero());
2167 assert!(INF_POS.reciprocal(rand_p(), rm).is_zero());
2168 assert!(NAN.reciprocal(rand_p(), rm).is_nan());
2169
2170 assert!(TWO.signum().cmp(&ONE) == Some(0));
2171 assert!(TWO.neg().signum().cmp(&ONE.neg()) == Some(0));
2172 assert!(INF_POS.signum().cmp(&ONE) == Some(0));
2173 assert!(INF_NEG.signum().cmp(&ONE.neg()) == Some(0));
2174 assert!(NAN.signum().is_nan());
2175
2176 let d1 = ONE.clone();
2177 assert!(d1.exponent() == Some(1));
2178 let words: &[Word] = {
2179 #[cfg(not(target_pointer_width = "32"))]
2180 {
2181 &[0, 0x8000000000000000]
2182 }
2183 #[cfg(target_pointer_width = "32")]
2184 {
2185 &[0, 0, 0, 0x80000000]
2186 }
2187 };
2188
2189 assert!(d1.mantissa_digits() == Some(words));
2190 assert!(d1.mantissa_max_bit_len() == Some(DEFAULT_P));
2191 assert!(d1.precision() == Some(DEFAULT_P));
2192 assert!(d1.sign() == Some(Sign::Pos));
2193
2194 assert!(INF_POS.exponent().is_none());
2195 assert!(INF_POS.mantissa_digits().is_none());
2196 assert!(INF_POS.mantissa_max_bit_len().is_none());
2197 assert!(INF_POS.precision().is_none());
2198 assert!(INF_POS.sign() == Some(Sign::Pos));
2199
2200 assert!(INF_NEG.exponent().is_none());
2201 assert!(INF_NEG.mantissa_digits().is_none());
2202 assert!(INF_NEG.mantissa_max_bit_len().is_none());
2203 assert!(INF_NEG.precision().is_none());
2204 assert!(INF_NEG.sign() == Some(Sign::Neg));
2205
2206 assert!(NAN.exponent().is_none());
2207 assert!(NAN.mantissa_digits().is_none());
2208 assert!(NAN.mantissa_max_bit_len().is_none());
2209 assert!(NAN.precision().is_none());
2210 assert!(NAN.sign().is_none());
2211
2212 INF_POS.clone().set_exponent(1);
2213 INF_POS.clone().set_precision(1, rm).unwrap();
2214 INF_POS.clone().set_sign(Sign::Pos);
2215
2216 INF_NEG.clone().set_exponent(1);
2217 INF_NEG.clone().set_precision(1, rm).unwrap();
2218 INF_NEG.clone().set_sign(Sign::Pos);
2219
2220 NAN.clone().set_exponent(1);
2221 NAN.clone().set_precision(1, rm).unwrap();
2222 NAN.clone().set_sign(Sign::Pos);
2223
2224 assert!(INF_POS.min(&ONE).cmp(&ONE) == Some(0));
2225 assert!(INF_NEG.min(&ONE).is_inf_neg());
2226 assert!(NAN.min(&ONE).is_nan());
2227 assert!(ONE.min(&INF_POS).cmp(&ONE) == Some(0));
2228 assert!(ONE.min(&INF_NEG).is_inf_neg());
2229 assert!(ONE.min(&NAN).is_nan());
2230 assert!(NAN.min(&INF_POS).is_nan());
2231 assert!(NAN.min(&INF_NEG).is_nan());
2232 assert!(NAN.min(&NAN).is_nan());
2233 assert!(INF_NEG.min(&INF_POS).is_inf_neg());
2234 assert!(INF_POS.min(&INF_NEG).is_inf_neg());
2235 assert!(INF_POS.min(&INF_POS).is_inf_pos());
2236 assert!(INF_NEG.min(&INF_NEG).is_inf_neg());
2237
2238 assert!(INF_POS.max(&ONE).is_inf_pos());
2239 assert!(INF_NEG.max(&ONE).cmp(&ONE) == Some(0));
2240 assert!(NAN.max(&ONE).is_nan());
2241 assert!(ONE.max(&INF_POS).is_inf_pos());
2242 assert!(ONE.max(&INF_NEG).cmp(&ONE) == Some(0));
2243 assert!(ONE.max(&NAN).is_nan());
2244 assert!(NAN.max(&INF_POS).is_nan());
2245 assert!(NAN.max(&INF_NEG).is_nan());
2246 assert!(NAN.max(&NAN).is_nan());
2247 assert!(INF_NEG.max(&INF_POS).is_inf_pos());
2248 assert!(INF_POS.max(&INF_NEG).is_inf_pos());
2249 assert!(INF_POS.max(&INF_POS).is_inf_pos());
2250 assert!(INF_NEG.max(&INF_NEG).is_inf_neg());
2251
2252 assert!(ONE.clamp(&ONE.neg(), &TWO).cmp(&ONE) == Some(0));
2253 assert!(ONE.clamp(&TWO, &ONE).is_nan());
2254 assert!(ONE.clamp(&INF_POS, &ONE).is_nan());
2255 assert!(ONE.clamp(&TWO, &INF_NEG).is_nan());
2256 assert!(ONE.neg().clamp(&ONE, &TWO).cmp(&ONE) == Some(0));
2257 assert!(TWO.clamp(&ONE.neg(), &ONE).cmp(&ONE) == Some(0));
2258 assert!(INF_POS.clamp(&ONE, &TWO).cmp(&TWO) == Some(0));
2259 assert!(INF_POS.clamp(&ONE, &INF_POS).is_inf_pos());
2260 assert!(INF_POS.clamp(&INF_NEG, &ONE).cmp(&ONE) == Some(0));
2261 assert!(INF_POS.clamp(&NAN, &INF_POS).is_nan());
2262 assert!(INF_POS.clamp(&ONE, &NAN).is_nan());
2263 assert!(INF_POS.clamp(&NAN, &NAN).is_nan());
2264 assert!(INF_NEG.clamp(&ONE, &TWO).cmp(&ONE) == Some(0));
2265 assert!(INF_NEG.clamp(&ONE, &INF_POS).cmp(&ONE) == Some(0));
2266 assert!(INF_NEG.clamp(&INF_NEG, &ONE).is_inf_neg());
2267 assert!(INF_NEG.clamp(&NAN, &INF_POS).is_nan());
2268 assert!(INF_NEG.clamp(&ONE, &NAN).is_nan());
2269 assert!(INF_NEG.clamp(&NAN, &NAN).is_nan());
2270 assert!(NAN.clamp(&ONE, &TWO).is_nan());
2271 assert!(NAN.clamp(&NAN, &TWO).is_nan());
2272 assert!(NAN.clamp(&ONE, &NAN).is_nan());
2273 assert!(NAN.clamp(&NAN, &NAN).is_nan());
2274 assert!(NAN.clamp(&INF_NEG, &INF_POS).is_nan());
2275
2276 assert!(BigFloat::min_positive(DEFAULT_P).classify() == FpCategory::Subnormal);
2277 assert!(INF_POS.classify() == FpCategory::Infinite);
2278 assert!(INF_NEG.classify() == FpCategory::Infinite);
2279 assert!(NAN.classify() == FpCategory::Nan);
2280 assert!(ONE.classify() == FpCategory::Normal);
2281
2282 assert!(!INF_POS.is_subnormal());
2283 assert!(!INF_NEG.is_subnormal());
2284 assert!(!NAN.is_subnormal());
2285 assert!(BigFloat::min_positive(DEFAULT_P).is_subnormal());
2286 assert!(!BigFloat::min_positive_normal(DEFAULT_P).is_subnormal());
2287 assert!(!BigFloat::max_value(DEFAULT_P).is_subnormal());
2288 assert!(!BigFloat::min_value(DEFAULT_P).is_subnormal());
2289
2290 let n1 = BigFloat::convert_from_radix(
2291 Sign::Pos,
2292 &[],
2293 0,
2294 Radix::Dec,
2295 usize::MAX - 1,
2296 RoundingMode::None,
2297 &mut cc,
2298 );
2299 assert!(n1.is_nan());
2300 assert!(n1.err() == Some(Error::InvalidArgument));
2301
2302 assert!(
2303 n1.convert_to_radix(Radix::Dec, RoundingMode::None, &mut cc)
2304 == Err(Error::InvalidArgument)
2305 );
2306 assert!(
2307 INF_POS.convert_to_radix(Radix::Dec, RoundingMode::None, &mut cc)
2308 == Err(Error::InvalidArgument)
2309 );
2310 assert!(
2311 INF_NEG.convert_to_radix(Radix::Dec, RoundingMode::None, &mut cc)
2312 == Err(Error::InvalidArgument)
2313 );
2314 }
2315
2316 #[cfg(feature = "std")]
2317 #[test]
2318 fn test_ops_std() {
2319 let mut cc = Consts::new().unwrap();
2320
2321 let d1 = BigFloat::parse(
2322 "0.0123456789012345678901234567890123456789",
2323 Radix::Dec,
2324 DEFAULT_P,
2325 RoundingMode::None,
2326 &mut cc,
2327 );
2328
2329 let d1str = format!("{}", d1);
2330 assert_eq!(&d1str, "1.23456789012345678901234567890123456789e-2");
2331 let mut d2 = BigFloat::from_str(&d1str).unwrap();
2332 d2.set_precision(DEFAULT_P, RoundingMode::ToEven).unwrap();
2333 assert_eq!(d2, d1);
2334
2335 let d1 = BigFloat::parse(
2336 "-123.456789012345678901234567890123456789",
2337 Radix::Dec,
2338 DEFAULT_P,
2339 RoundingMode::None,
2340 &mut cc,
2341 );
2342 let d1str = format!("{}", d1);
2343 assert_eq!(&d1str, "-1.23456789012345678901234567890123456789e+2");
2344 let mut d2 = BigFloat::from_str(&d1str).unwrap();
2345 d2.set_precision(DEFAULT_P, RoundingMode::ToEven).unwrap();
2346 assert_eq!(d2, d1);
2347
2348 let d1str = format!("{}", INF_POS);
2349 assert_eq!(d1str, "Inf");
2350
2351 let d1str = format!("{}", INF_NEG);
2352 assert_eq!(d1str, "-Inf");
2353
2354 let d1str = format!("{}", NAN);
2355 assert_eq!(d1str, "NaN");
2356
2357 assert!(BigFloat::from_str("abc").is_ok());
2358 assert!(BigFloat::from_str("abc").unwrap().is_nan());
2359 }
2360
2361 #[test]
2362 pub fn test_ops() {
2363 let mut cc = Consts::new().unwrap();
2364
2365 let d1 = -&(TWO.clone());
2366 assert!(d1.is_negative());
2367
2368 let p = DEFAULT_P;
2369 let rm = RoundingMode::ToEven;
2370 assert!(
2371 BigFloat::from_i8(-123, p) == BigFloat::parse("-1.23e+2", Radix::Dec, p, rm, &mut cc)
2372 );
2373 assert!(
2374 BigFloat::from_u8(123, p) == BigFloat::parse("1.23e+2", Radix::Dec, p, rm, &mut cc)
2375 );
2376 assert!(
2377 BigFloat::from_i16(-12312, p)
2378 == BigFloat::parse("-1.2312e+4", Radix::Dec, p, rm, &mut cc)
2379 );
2380 assert!(
2381 BigFloat::from_u16(12312, p)
2382 == BigFloat::parse("1.2312e+4", Radix::Dec, p, rm, &mut cc)
2383 );
2384 assert!(
2385 BigFloat::from_i32(-123456789, p)
2386 == BigFloat::parse("-1.23456789e+8", Radix::Dec, p, rm, &mut cc)
2387 );
2388 assert!(
2389 BigFloat::from_u32(123456789, p)
2390 == BigFloat::parse("1.23456789e+8", Radix::Dec, p, rm, &mut cc)
2391 );
2392 assert!(
2393 BigFloat::from_i64(-1234567890123456789, p)
2394 == BigFloat::parse("-1.234567890123456789e+18", Radix::Dec, p, rm, &mut cc)
2395 );
2396 assert!(
2397 BigFloat::from_u64(1234567890123456789, p)
2398 == BigFloat::parse("1.234567890123456789e+18", Radix::Dec, p, rm, &mut cc)
2399 );
2400 assert!(
2401 BigFloat::from_i128(-123456789012345678901234567890123456789, p)
2402 == BigFloat::parse(
2403 "-1.23456789012345678901234567890123456789e+38",
2404 Radix::Dec,
2405 p,
2406 rm,
2407 &mut cc
2408 )
2409 );
2410 assert!(
2411 BigFloat::from_u128(123456789012345678901234567890123456789, p)
2412 == BigFloat::parse(
2413 "1.23456789012345678901234567890123456789e+38",
2414 Radix::Dec,
2415 p,
2416 rm,
2417 &mut cc
2418 )
2419 );
2420
2421 let neg = BigFloat::from_i8(-3, WORD_BIT_SIZE);
2422 let pos = BigFloat::from_i8(5, WORD_BIT_SIZE);
2423
2424 assert!(pos > neg);
2425 assert!(neg < pos);
2426 assert!(!(pos < neg));
2427 assert!(!(neg > pos));
2428 assert!(INF_NEG < neg);
2429 assert!(INF_NEG < pos);
2430 assert!(INF_NEG < INF_POS);
2431 assert!(!(INF_NEG > neg));
2432 assert!(!(INF_NEG > pos));
2433 assert!(!(INF_NEG > INF_POS));
2434 assert!(INF_POS > neg);
2435 assert!(INF_POS > pos);
2436 assert!(INF_POS > INF_NEG);
2437 assert!(!(INF_POS < neg));
2438 assert!(!(INF_POS < pos));
2439 assert!(!(INF_POS < INF_NEG));
2440 assert!(!(INF_POS > INF_POS));
2441 assert!(!(INF_POS < INF_POS));
2442 assert!(!(INF_NEG > INF_NEG));
2443 assert!(!(INF_NEG < INF_NEG));
2444 assert!(!(INF_POS > NAN));
2445 assert!(!(INF_POS < NAN));
2446 assert!(!(INF_NEG > NAN));
2447 assert!(!(INF_NEG < NAN));
2448 assert!(!(NAN > INF_POS));
2449 assert!(!(NAN < INF_POS));
2450 assert!(!(NAN > INF_NEG));
2451 assert!(!(NAN < INF_NEG));
2452 assert!(!(NAN > NAN));
2453 assert!(!(NAN < NAN));
2454 assert!(!(neg > NAN));
2455 assert!(!(neg < NAN));
2456 assert!(!(pos > NAN));
2457 assert!(!(pos < NAN));
2458 assert!(!(NAN > neg));
2459 assert!(!(NAN < neg));
2460 assert!(!(NAN > pos));
2461 assert!(!(NAN < pos));
2462
2463 assert!(!(NAN == NAN));
2464 assert!(!(NAN == INF_POS));
2465 assert!(!(NAN == INF_NEG));
2466 assert!(!(INF_POS == NAN));
2467 assert!(!(INF_NEG == NAN));
2468 assert!(!(INF_NEG == INF_POS));
2469 assert!(!(INF_POS == INF_NEG));
2470 assert!(!(INF_POS == neg));
2471 assert!(!(INF_POS == pos));
2472 assert!(!(INF_NEG == neg));
2473 assert!(!(INF_NEG == pos));
2474 assert!(!(neg == INF_POS));
2475 assert!(!(pos == INF_POS));
2476 assert!(!(neg == INF_NEG));
2477 assert!(!(pos == INF_NEG));
2478 assert!(!(pos == neg));
2479 assert!(!(neg == pos));
2480 assert!(neg == neg);
2481 assert!(pos == pos);
2482 assert!(INF_NEG == INF_NEG);
2483 assert!(INF_POS == INF_POS);
2484 }
2485}
2486
2487#[cfg(feature = "random")]
2488#[cfg(test)]
2489mod rand_tests {
2490
2491 use super::*;
2492 use crate::defs::EXPONENT_MAX;
2493
2494 #[test]
2495 fn test_rand() {
2496 for _ in 0..1000 {
2497 let p = rand::random::<usize>() % 1000 + DEFAULT_P;
2498 let exp_from;
2499 #[cfg(not(target_pointer_width = "32"))]
2500 {
2501 exp_from = rand::random::<Exponent>().abs();
2502 }
2503 #[cfg(target_pointer_width = "32")]
2504 {
2505 use crate::defs::EXPONENT_MIN;
2506 exp_from =
2507 rand::random::<Exponent>().abs() % (EXPONENT_MAX - EXPONENT_MIN) + EXPONENT_MIN;
2508 }
2509 let exp_shift = if EXPONENT_MAX > exp_from {
2510 rand::random::<Exponent>().abs()
2511 % (EXPONENT_MAX as isize - exp_from as isize) as Exponent
2512 } else {
2513 0
2514 };
2515 let exp_to = (exp_from as isize + exp_shift as isize) as Exponent;
2516
2517 let n = BigFloat::random_normal(p, exp_from, exp_to);
2518
2519 assert!(!n.is_subnormal());
2520 assert!(n.exponent().unwrap() >= exp_from && n.exponent().unwrap() <= exp_to);
2521 assert!(n.precision().unwrap() >= p);
2522 }
2523 }
2524}