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 #[test]
1702 fn test_ext() {
1703 let rm = RoundingMode::ToOdd;
1704 let mut cc = Consts::new().unwrap();
1705
1706 let d1 = BigFloat::from_u8(1, rand_p());
1708 assert!(!d1.is_inf());
1709 assert!(!d1.is_nan());
1710 assert!(!d1.is_inf_pos());
1711 assert!(!d1.is_inf_neg());
1712 assert!(d1.is_positive());
1713
1714 let mut d1 = d1.div(&BigFloat::new(rand_p()), rand_p(), rm);
1715 assert!(d1.is_inf());
1716 assert!(!d1.is_nan());
1717 assert!(d1.is_inf_pos());
1718 assert!(!d1.is_inf_neg());
1719 assert!(d1.is_positive());
1720
1721 d1.inv_sign();
1722 assert!(d1.is_inf());
1723 assert!(!d1.is_nan());
1724 assert!(!d1.is_inf_pos());
1725 assert!(d1.is_inf_neg());
1726 assert!(d1.is_negative());
1727
1728 let d1 = BigFloat::new(rand_p()).div(&BigFloat::new(rand_p()), rand_p(), rm);
1729 assert!(!d1.is_inf());
1730 assert!(d1.is_nan());
1731 assert!(!d1.is_inf_pos());
1732 assert!(!d1.is_inf_neg());
1733 assert!(d1.sign().is_none());
1734
1735 for _ in 0..1000 {
1736 let i = rand::random::<i64>();
1737 let d1 = BigFloat::from_i64(i, rand_p());
1738 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1739 assert!(d1.cmp(&n1) == Some(0));
1740
1741 let i = rand::random::<u64>();
1742 let d1 = BigFloat::from_u64(i, rand_p());
1743 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1744 assert!(d1.cmp(&n1) == Some(0));
1745
1746 let i = rand::random::<i128>();
1747 let d1 = BigFloat::from_i128(i, rand_p());
1748 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1749 assert!(d1.cmp(&n1) == Some(0));
1750
1751 let i = rand::random::<u128>();
1752 let d1 = BigFloat::from_u128(i, rand_p());
1753 let n1 = BigFloat::parse(&format!("{}", i), Radix::Dec, rand_p(), rm, &mut cc);
1754 assert!(d1.cmp(&n1) == Some(0));
1755 }
1756
1757 assert!(ONE.exponent().is_some());
1758 assert!(INF_POS.exponent().is_none());
1759 assert!(INF_NEG.exponent().is_none());
1760 assert!(NAN.exponent().is_none());
1761
1762 assert!(ONE.as_raw_parts().is_some());
1763 assert!(INF_POS.as_raw_parts().is_none());
1764 assert!(INF_NEG.as_raw_parts().is_none());
1765 assert!(NAN.as_raw_parts().is_none());
1766
1767 assert!(ONE.add(&ONE, rand_p(), rm).cmp(&TWO) == Some(0));
1768 assert!(ONE.add(&INF_POS, rand_p(), rm).is_inf_pos());
1769 assert!(INF_POS.add(&ONE, rand_p(), rm).is_inf_pos());
1770 assert!(ONE.add(&INF_NEG, rand_p(), rm).is_inf_neg());
1771 assert!(INF_NEG.add(&ONE, rand_p(), rm).is_inf_neg());
1772 assert!(INF_POS.add(&INF_POS, rand_p(), rm).is_inf_pos());
1773 assert!(INF_POS.add(&INF_NEG, rand_p(), rm).is_nan());
1774 assert!(INF_NEG.add(&INF_NEG, rand_p(), rm).is_inf_neg());
1775 assert!(INF_NEG.add(&INF_POS, rand_p(), rm).is_nan());
1776
1777 assert!(ONE.add_full_prec(&ONE).cmp(&TWO) == Some(0));
1778 assert!(ONE.add_full_prec(&INF_POS).is_inf_pos());
1779 assert!(INF_POS.add_full_prec(&ONE).is_inf_pos());
1780 assert!(ONE.add_full_prec(&INF_NEG).is_inf_neg());
1781 assert!(INF_NEG.add_full_prec(&ONE).is_inf_neg());
1782 assert!(INF_POS.add_full_prec(&INF_POS).is_inf_pos());
1783 assert!(INF_POS.add_full_prec(&INF_NEG).is_nan());
1784 assert!(INF_NEG.add_full_prec(&INF_NEG).is_inf_neg());
1785 assert!(INF_NEG.add_full_prec(&INF_POS).is_nan());
1786
1787 assert!(ONE.sub_full_prec(&ONE).is_zero());
1788 assert!(ONE.sub_full_prec(&INF_POS).is_inf_neg());
1789 assert!(INF_POS.sub_full_prec(&ONE).is_inf_pos());
1790 assert!(ONE.sub_full_prec(&INF_NEG).is_inf_pos());
1791 assert!(INF_NEG.sub_full_prec(&ONE).is_inf_neg());
1792 assert!(INF_POS.sub_full_prec(&INF_POS).is_nan());
1793 assert!(INF_POS.sub_full_prec(&INF_NEG).is_inf_pos());
1794 assert!(INF_NEG.sub_full_prec(&INF_NEG).is_nan());
1795 assert!(INF_NEG.sub_full_prec(&INF_POS).is_inf_neg());
1796
1797 assert!(ONE.mul_full_prec(&ONE).cmp(&ONE) == Some(0));
1798 assert!(ONE.mul_full_prec(&INF_POS).is_inf_pos());
1799 assert!(INF_POS.mul_full_prec(&ONE).is_inf_pos());
1800 assert!(ONE.mul_full_prec(&INF_NEG).is_inf_neg());
1801 assert!(INF_NEG.mul_full_prec(&ONE).is_inf_neg());
1802 assert!(INF_POS.mul_full_prec(&INF_POS).is_inf_pos());
1803 assert!(INF_POS.mul_full_prec(&INF_NEG).is_inf_neg());
1804 assert!(INF_NEG.mul_full_prec(&INF_NEG).is_inf_pos());
1805 assert!(INF_NEG.mul_full_prec(&INF_POS).is_inf_neg());
1806
1807 assert!(TWO.sub(&ONE, rand_p(), rm).cmp(&ONE) == Some(0));
1808 assert!(ONE.sub(&INF_POS, rand_p(), rm).is_inf_neg());
1809 assert!(INF_POS.sub(&ONE, rand_p(), rm).is_inf_pos());
1810 assert!(ONE.sub(&INF_NEG, rand_p(), rm).is_inf_pos());
1811 assert!(INF_NEG.sub(&ONE, rand_p(), rm).is_inf_neg());
1812 assert!(INF_POS.sub(&INF_POS, rand_p(), rm).is_nan());
1813 assert!(INF_POS.sub(&INF_NEG, rand_p(), rm).is_inf_pos());
1814 assert!(INF_NEG.sub(&INF_NEG, rand_p(), rm).is_nan());
1815 assert!(INF_NEG.sub(&INF_POS, rand_p(), rm).is_inf_neg());
1816
1817 assert!(TWO.mul(&ONE, rand_p(), rm).cmp(&TWO) == Some(0));
1818 assert!(ONE.mul(&INF_POS, rand_p(), rm).is_inf_pos());
1819 assert!(INF_POS.mul(&ONE, rand_p(), rm).is_inf_pos());
1820 assert!(ONE.mul(&INF_NEG, rand_p(), rm).is_inf_neg());
1821 assert!(INF_NEG.mul(&ONE, rand_p(), rm).is_inf_neg());
1822 assert!(ONE.neg().mul(&INF_POS, rand_p(), rm).is_inf_neg());
1823 assert!(ONE.neg().mul(&INF_NEG, rand_p(), rm).is_inf_pos());
1824 assert!(INF_POS.mul(&ONE.neg(), rand_p(), rm).is_inf_neg());
1825 assert!(INF_NEG.mul(&ONE.neg(), rand_p(), rm).is_inf_pos());
1826 assert!(INF_POS.mul(&INF_POS, rand_p(), rm).is_inf_pos());
1827 assert!(INF_POS.mul(&INF_NEG, rand_p(), rm).is_inf_neg());
1828 assert!(INF_NEG.mul(&INF_NEG, rand_p(), rm).is_inf_pos());
1829 assert!(INF_NEG.mul(&INF_POS, rand_p(), rm).is_inf_neg());
1830 assert!(INF_POS.mul(&BigFloat::new(rand_p()), rand_p(), rm).is_nan());
1831 assert!(INF_NEG.mul(&BigFloat::new(rand_p()), rand_p(), rm).is_nan());
1832 assert!(BigFloat::new(rand_p()).mul(&INF_POS, rand_p(), rm).is_nan());
1833 assert!(BigFloat::new(rand_p()).mul(&INF_NEG, rand_p(), rm).is_nan());
1834
1835 assert!(TWO.div(&TWO, rand_p(), rm).cmp(&ONE) == Some(0));
1836 assert!(TWO.div(&INF_POS, rand_p(), rm).is_zero());
1837 assert!(INF_POS.div(&TWO, rand_p(), rm).is_inf_pos());
1838 assert!(TWO.div(&INF_NEG, rand_p(), rm).is_zero());
1839 assert!(INF_NEG.div(&TWO, rand_p(), rm).is_inf_neg());
1840 assert!(TWO.neg().div(&INF_POS, rand_p(), rm).is_zero());
1841 assert!(TWO.neg().div(&INF_NEG, rand_p(), rm).is_zero());
1842 assert!(INF_POS.div(&TWO.neg(), rand_p(), rm).is_inf_neg());
1843 assert!(INF_NEG.div(&TWO.neg(), rand_p(), rm).is_inf_pos());
1844 assert!(INF_POS.div(&INF_POS, rand_p(), rm).is_nan());
1845 assert!(INF_POS.div(&INF_NEG, rand_p(), rm).is_nan());
1846 assert!(INF_NEG.div(&INF_NEG, rand_p(), rm).is_nan());
1847 assert!(INF_NEG.div(&INF_POS, rand_p(), rm).is_nan());
1848 assert!(INF_POS
1849 .div(&BigFloat::new(rand_p()), rand_p(), rm)
1850 .is_inf_pos());
1851 assert!(INF_NEG
1852 .div(&BigFloat::new(rand_p()), rand_p(), rm)
1853 .is_inf_neg());
1854 assert!(BigFloat::new(rand_p())
1855 .div(&INF_POS, rand_p(), rm)
1856 .is_zero());
1857 assert!(BigFloat::new(rand_p())
1858 .div(&INF_NEG, rand_p(), rm)
1859 .is_zero());
1860
1861 assert!(TWO.rem(&TWO).is_zero());
1862 assert!(TWO.rem(&INF_POS).cmp(&TWO) == Some(0));
1863 assert!(INF_POS.rem(&TWO).is_nan());
1864 assert!(TWO.rem(&INF_NEG).cmp(&TWO) == Some(0));
1865 assert!(INF_NEG.rem(&TWO).is_nan());
1866 assert!(TWO.neg().rem(&INF_POS).cmp(&TWO.neg()) == Some(0));
1867 assert!(TWO.neg().rem(&INF_NEG).cmp(&TWO.neg()) == Some(0));
1868 assert!(INF_POS.rem(&TWO.neg()).is_nan());
1869 assert!(INF_NEG.rem(&TWO.neg()).is_nan());
1870 assert!(INF_POS.rem(&INF_POS).is_nan());
1871 assert!(INF_POS.rem(&INF_NEG).is_nan());
1872 assert!(INF_NEG.rem(&INF_NEG).is_nan());
1873 assert!(INF_NEG.rem(&INF_POS).is_nan());
1874 assert!(INF_POS.rem(&BigFloat::new(rand_p())).is_nan());
1875 assert!(INF_NEG.rem(&BigFloat::new(rand_p())).is_nan());
1876 assert!(BigFloat::new(rand_p()).rem(&INF_POS).is_zero());
1877 assert!(BigFloat::new(rand_p()).rem(&INF_NEG).is_zero());
1878
1879 for op in [BigFloat::add, BigFloat::sub, BigFloat::mul, BigFloat::div] {
1880 assert!(op(&NAN, &ONE, rand_p(), rm).is_nan());
1881 assert!(op(&ONE, &NAN, rand_p(), rm).is_nan());
1882 assert!(op(&NAN, &INF_POS, rand_p(), rm).is_nan());
1883 assert!(op(&INF_POS, &NAN, rand_p(), rm).is_nan());
1884 assert!(op(&NAN, &INF_NEG, rand_p(), rm).is_nan());
1885 assert!(op(&INF_NEG, &NAN, rand_p(), rm).is_nan());
1886 assert!(op(&NAN, &NAN, rand_p(), rm).is_nan());
1887 }
1888
1889 assert!(BigFloat::rem(&NAN, &ONE).is_nan());
1890 assert!(BigFloat::rem(&ONE, &NAN).is_nan());
1891 assert!(BigFloat::rem(&NAN, &INF_POS).is_nan());
1892 assert!(BigFloat::rem(&INF_POS, &NAN).is_nan());
1893 assert!(BigFloat::rem(&NAN, &INF_NEG).is_nan());
1894 assert!(BigFloat::rem(&INF_NEG, &NAN).is_nan());
1895 assert!(BigFloat::rem(&NAN, &NAN).is_nan());
1896
1897 for op in [BigFloat::add_full_prec, BigFloat::sub_full_prec, BigFloat::mul_full_prec] {
1898 assert!(op(&NAN, &ONE).is_nan());
1899 assert!(op(&ONE, &NAN).is_nan());
1900 assert!(op(&NAN, &INF_POS).is_nan());
1901 assert!(op(&INF_POS, &NAN).is_nan());
1902 assert!(op(&NAN, &INF_NEG).is_nan());
1903 assert!(op(&INF_NEG, &NAN).is_nan());
1904 assert!(op(&NAN, &NAN).is_nan());
1905 }
1906
1907 assert!(ONE.cmp(&ONE).unwrap() == 0);
1908 assert!(ONE.cmp(&INF_POS).unwrap() < 0);
1909 assert!(INF_POS.cmp(&ONE).unwrap() > 0);
1910 assert!(INF_POS.cmp(&INF_POS).unwrap() == 0);
1911 assert!(ONE.cmp(&INF_NEG).unwrap() > 0);
1912 assert!(INF_NEG.cmp(&ONE).unwrap() < 0);
1913 assert!(INF_NEG.cmp(&INF_NEG).unwrap() == 0);
1914 assert!(INF_POS.cmp(&INF_NEG).unwrap() > 0);
1915 assert!(INF_NEG.cmp(&INF_POS).unwrap() < 0);
1916 assert!(INF_POS.cmp(&INF_POS).unwrap() == 0);
1917 assert!(ONE.cmp(&NAN).is_none());
1918 assert!(NAN.cmp(&ONE).is_none());
1919 assert!(INF_POS.cmp(&NAN).is_none());
1920 assert!(NAN.cmp(&INF_POS).is_none());
1921 assert!(INF_NEG.cmp(&NAN).is_none());
1922 assert!(NAN.cmp(&INF_NEG).is_none());
1923 assert!(NAN.cmp(&NAN).is_none());
1924
1925 assert!(ONE.abs_cmp(&ONE).unwrap() == 0);
1926 assert!(ONE.abs_cmp(&INF_POS).unwrap() < 0);
1927 assert!(INF_POS.abs_cmp(&ONE).unwrap() > 0);
1928 assert!(INF_POS.abs_cmp(&INF_POS).unwrap() == 0);
1929 assert!(ONE.abs_cmp(&INF_NEG).unwrap() < 0);
1930 assert!(INF_NEG.abs_cmp(&ONE).unwrap() > 0);
1931 assert!(INF_NEG.abs_cmp(&INF_NEG).unwrap() == 0);
1932 assert!(INF_POS.abs_cmp(&INF_NEG).unwrap() == 0);
1933 assert!(INF_NEG.abs_cmp(&INF_POS).unwrap() == 0);
1934 assert!(INF_POS.abs_cmp(&INF_POS).unwrap() == 0);
1935 assert!(ONE.abs_cmp(&NAN).is_none());
1936 assert!(NAN.abs_cmp(&ONE).is_none());
1937 assert!(INF_POS.abs_cmp(&NAN).is_none());
1938 assert!(NAN.abs_cmp(&INF_POS).is_none());
1939 assert!(INF_NEG.abs_cmp(&NAN).is_none());
1940 assert!(NAN.abs_cmp(&INF_NEG).is_none());
1941 assert!(NAN.abs_cmp(&NAN).is_none());
1942
1943 assert!(ONE.is_positive());
1944 assert!(!ONE.is_negative());
1945
1946 assert!(ONE.neg().is_negative());
1947 assert!(!ONE.neg().is_positive());
1948 assert!(!INF_POS.is_negative());
1949 assert!(INF_POS.is_positive());
1950 assert!(INF_NEG.is_negative());
1951 assert!(!INF_NEG.is_positive());
1952 assert!(!NAN.is_positive());
1953 assert!(!NAN.is_negative());
1954
1955 assert!(ONE.pow(&ONE, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
1956 assert!(BigFloat::new(DEFAULT_P)
1957 .pow(&INF_POS, rand_p(), rm, &mut cc)
1958 .is_zero());
1959 assert!(BigFloat::new(DEFAULT_P)
1960 .pow(&INF_NEG, rand_p(), rm, &mut cc)
1961 .is_zero());
1962 assert!(ONE.pow(&INF_POS, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
1963 assert!(ONE.pow(&INF_NEG, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
1964 assert!(TWO.pow(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
1965 assert!(TWO.pow(&INF_NEG, rand_p(), rm, &mut cc).is_inf_neg());
1966 assert!(INF_POS.pow(&ONE, rand_p(), rm, &mut cc).is_inf_pos());
1967 assert!(INF_NEG.pow(&ONE, rand_p(), rm, &mut cc).is_inf_neg());
1968 assert!(INF_NEG.pow(&TWO, rand_p(), rm, &mut cc).is_inf_pos());
1969 assert!(INF_NEG
1970 .pow(&BigFloat::from_f64(10.2, DEFAULT_P), rand_p(), rm, &mut cc)
1971 .is_inf_pos());
1972 assert!(INF_NEG
1973 .pow(&BigFloat::from_f64(3.0, DEFAULT_P), rand_p(), rm, &mut cc)
1974 .is_inf_neg());
1975 assert!(INF_POS.pow(&ONE.neg(), rand_p(), rm, &mut cc).is_zero());
1976 assert!(INF_NEG.pow(&ONE.neg(), rand_p(), rm, &mut cc).is_zero());
1977 assert!(
1978 INF_POS
1979 .pow(&BigFloat::new(DEFAULT_P), rand_p(), rm, &mut cc)
1980 .cmp(&ONE)
1981 == Some(0)
1982 );
1983 assert!(
1984 INF_NEG
1985 .pow(&BigFloat::new(DEFAULT_P), rand_p(), rm, &mut cc)
1986 .cmp(&ONE)
1987 == Some(0)
1988 );
1989 assert!(INF_POS.pow(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
1990 assert!(INF_NEG.pow(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
1991 assert!(INF_POS.pow(&INF_NEG, rand_p(), rm, &mut cc).is_zero());
1992 assert!(INF_NEG.pow(&INF_NEG, rand_p(), rm, &mut cc).is_zero());
1993
1994 let half = ONE.div(&TWO, rand_p(), rm);
1995 assert!(TWO.log(&TWO, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
1996 assert!(TWO.log(&INF_POS, rand_p(), rm, &mut cc).is_zero());
1997 assert!(TWO.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
1998 assert!(INF_POS.log(&TWO, rand_p(), rm, &mut cc).is_inf_pos());
1999 assert!(INF_NEG.log(&TWO, rand_p(), rm, &mut cc).is_nan());
2000 assert!(half.log(&half, rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
2001 assert!(half.log(&INF_POS, rand_p(), rm, &mut cc).is_zero());
2002 assert!(half.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2003 assert!(INF_POS.log(&half, rand_p(), rm, &mut cc).is_inf_neg());
2004 assert!(INF_NEG.log(&half, rand_p(), rm, &mut cc).is_nan());
2005 assert!(INF_POS.log(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2006 assert!(INF_POS.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2007 assert!(INF_NEG.log(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2008 assert!(INF_NEG.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2009 assert!(TWO.log(&ONE, rand_p(), rm, &mut cc).is_inf_pos());
2010 assert!(half.log(&ONE, rand_p(), rm, &mut cc).is_inf_pos());
2011 assert!(ONE.log(&ONE, rand_p(), rm, &mut cc).is_nan());
2012
2013 assert!(BigFloat::from_f32(f32::NAN, DEFAULT_P).is_nan());
2014 assert!(BigFloat::from_f32(f32::INFINITY, DEFAULT_P).is_inf_pos());
2015 assert!(BigFloat::from_f32(f32::NEG_INFINITY, DEFAULT_P).is_inf_neg());
2016 assert!(!BigFloat::from_f32(1.0, DEFAULT_P).is_nan());
2017 assert!(BigFloat::from_f64(f64::NAN, DEFAULT_P).is_nan());
2018 assert!(BigFloat::from_f64(f64::INFINITY, DEFAULT_P).is_inf_pos());
2019 assert!(BigFloat::from_f64(f64::NEG_INFINITY, DEFAULT_P).is_inf_neg());
2020 assert!(!BigFloat::from_f64(1.0, DEFAULT_P).is_nan());
2021
2022 assert!(ONE.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2023 assert!(NAN.pow(&ONE, rand_p(), rm, &mut cc).is_nan());
2024 assert!(INF_POS.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2025 assert!(NAN.pow(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2026 assert!(INF_NEG.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2027 assert!(NAN.pow(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2028 assert!(NAN.pow(&NAN, rand_p(), rm, &mut cc).is_nan());
2029
2030 assert!(NAN.powi(2, rand_p(), rm).is_nan());
2031 assert!(NAN.powi(0, rand_p(), rm).is_nan());
2032 assert!(INF_POS.powi(2, rand_p(), rm).is_inf_pos());
2033 assert!(INF_POS.powi(3, rand_p(), rm).is_inf_pos());
2034 assert!(INF_NEG.powi(4, rand_p(), rm).is_inf_pos());
2035 assert!(INF_NEG.powi(5, rand_p(), rm).is_inf_neg());
2036 assert!(INF_POS.powi(0, rand_p(), rm).cmp(&ONE) == Some(0));
2037 assert!(INF_NEG.powi(0, rand_p(), rm).cmp(&ONE) == Some(0));
2038
2039 assert!(TWO.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2040 assert!(NAN.log(&TWO, rand_p(), rm, &mut cc).is_nan());
2041 assert!(INF_POS.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2042 assert!(NAN.log(&INF_POS, rand_p(), rm, &mut cc).is_nan());
2043 assert!(INF_NEG.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2044 assert!(NAN.log(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2045 assert!(NAN.log(&NAN, rand_p(), rm, &mut cc).is_nan());
2046
2047 assert!(INF_NEG.abs().is_inf_pos());
2048 assert!(INF_POS.abs().is_inf_pos());
2049 assert!(NAN.abs().is_nan());
2050
2051 assert!(INF_NEG.int().is_nan());
2052 assert!(INF_POS.int().is_nan());
2053 assert!(NAN.int().is_nan());
2054
2055 assert!(INF_NEG.fract().is_nan());
2056 assert!(INF_POS.fract().is_nan());
2057 assert!(NAN.fract().is_nan());
2058
2059 assert!(INF_NEG.ceil().is_inf_neg());
2060 assert!(INF_POS.ceil().is_inf_pos());
2061 assert!(NAN.ceil().is_nan());
2062
2063 assert!(INF_NEG.floor().is_inf_neg());
2064 assert!(INF_POS.floor().is_inf_pos());
2065 assert!(NAN.floor().is_nan());
2066
2067 for rm in [
2068 RoundingMode::Up,
2069 RoundingMode::Down,
2070 RoundingMode::ToZero,
2071 RoundingMode::FromZero,
2072 RoundingMode::ToEven,
2073 RoundingMode::ToOdd,
2074 ] {
2075 assert!(INF_NEG.round(0, rm).is_inf_neg());
2076 assert!(INF_POS.round(0, rm).is_inf_pos());
2077 assert!(NAN.round(0, rm).is_nan());
2078 }
2079
2080 assert!(INF_NEG.sqrt(rand_p(), rm).is_nan());
2081 assert!(INF_POS.sqrt(rand_p(), rm).is_inf_pos());
2082 assert!(NAN.sqrt(rand_p(), rm).is_nan());
2083
2084 assert!(INF_NEG.cbrt(rand_p(), rm).is_inf_neg());
2085 assert!(INF_POS.cbrt(rand_p(), rm).is_inf_pos());
2086 assert!(NAN.cbrt(rand_p(), rm).is_nan());
2087
2088 for op in [BigFloat::ln, BigFloat::log2, BigFloat::log10] {
2089 assert!(op(&INF_NEG, rand_p(), rm, &mut cc).is_nan());
2090 assert!(op(&INF_POS, rand_p(), rm, &mut cc).is_inf_pos());
2091 assert!(op(&NAN, rand_p(), rm, &mut cc).is_nan());
2092 }
2093
2094 assert!(INF_NEG.exp(rand_p(), rm, &mut cc).is_zero());
2095 assert!(INF_POS.exp(rand_p(), rm, &mut cc).is_inf_pos());
2096 assert!(NAN.exp(rand_p(), rm, &mut cc).is_nan());
2097
2098 assert!(INF_NEG.sin(rand_p(), rm, &mut cc).is_nan());
2099 assert!(INF_POS.sin(rand_p(), rm, &mut cc).is_nan());
2100 assert!(NAN.sin(rand_p(), rm, &mut cc).is_nan());
2101
2102 assert!(INF_NEG.cos(rand_p(), rm, &mut cc).is_nan());
2103 assert!(INF_POS.cos(rand_p(), rm, &mut cc).is_nan());
2104 assert!(NAN.cos(rand_p(), rm, &mut cc).is_nan());
2105
2106 assert!(INF_NEG.tan(rand_p(), rm, &mut cc).is_nan());
2107 assert!(INF_POS.tan(rand_p(), rm, &mut cc).is_nan());
2108 assert!(NAN.tan(rand_p(), rm, &mut cc).is_nan());
2109
2110 assert!(INF_NEG.asin(rand_p(), rm, &mut cc).is_nan());
2111 assert!(INF_POS.asin(rand_p(), rm, &mut cc).is_nan());
2112 assert!(NAN.asin(rand_p(), rm, &mut cc).is_nan());
2113
2114 assert!(INF_NEG.acos(rand_p(), rm, &mut cc).is_nan());
2115 assert!(INF_POS.acos(rand_p(), rm, &mut cc).is_nan());
2116 assert!(NAN.acos(rand_p(), rm, &mut cc).is_nan());
2117
2118 let p = rand_p();
2119 let mut half_pi: BigFloat = cc.pi_num(p, rm).unwrap().into();
2120 half_pi.set_exponent(1);
2121 assert!(INF_NEG.atan(p, rm, &mut cc).cmp(&half_pi.neg()) == Some(0));
2122 assert!(INF_POS.atan(p, rm, &mut cc).cmp(&half_pi) == Some(0));
2123 assert!(NAN.atan(rand_p(), rm, &mut cc).is_nan());
2124
2125 assert!(INF_NEG.sinh(rand_p(), rm, &mut cc).is_inf_neg());
2126 assert!(INF_POS.sinh(rand_p(), rm, &mut cc).is_inf_pos());
2127 assert!(NAN.sinh(rand_p(), rm, &mut cc).is_nan());
2128
2129 assert!(INF_NEG.cosh(rand_p(), rm, &mut cc).is_inf_pos());
2130 assert!(INF_POS.cosh(rand_p(), rm, &mut cc).is_inf_pos());
2131 assert!(NAN.cosh(rand_p(), rm, &mut cc).is_nan());
2132
2133 assert!(INF_NEG.tanh(rand_p(), rm, &mut cc).cmp(&ONE.neg()) == Some(0));
2134 assert!(INF_POS.tanh(rand_p(), rm, &mut cc).cmp(&ONE) == Some(0));
2135 assert!(NAN.tanh(rand_p(), rm, &mut cc).is_nan());
2136
2137 assert!(INF_NEG.asinh(rand_p(), rm, &mut cc).is_inf_neg());
2138 assert!(INF_POS.asinh(rand_p(), rm, &mut cc).is_inf_pos());
2139 assert!(NAN.asinh(rand_p(), rm, &mut cc).is_nan());
2140
2141 assert!(INF_NEG.acosh(rand_p(), rm, &mut cc).is_nan());
2142 assert!(INF_POS.acosh(rand_p(), rm, &mut cc).is_inf_pos());
2143 assert!(NAN.acosh(rand_p(), rm, &mut cc).is_nan());
2144
2145 assert!(INF_NEG.atanh(rand_p(), rm, &mut cc).is_nan());
2146 assert!(INF_POS.atanh(rand_p(), rm, &mut cc).is_nan());
2147 assert!(NAN.atanh(rand_p(), rm, &mut cc).is_nan());
2148
2149 assert!(INF_NEG.reciprocal(rand_p(), rm).is_zero());
2150 assert!(INF_POS.reciprocal(rand_p(), rm).is_zero());
2151 assert!(NAN.reciprocal(rand_p(), rm).is_nan());
2152
2153 assert!(TWO.signum().cmp(&ONE) == Some(0));
2154 assert!(TWO.neg().signum().cmp(&ONE.neg()) == Some(0));
2155 assert!(INF_POS.signum().cmp(&ONE) == Some(0));
2156 assert!(INF_NEG.signum().cmp(&ONE.neg()) == Some(0));
2157 assert!(NAN.signum().is_nan());
2158
2159 let d1 = ONE.clone();
2160 assert!(d1.exponent() == Some(1));
2161 let words: &[Word] = {
2162 #[cfg(not(target_arch = "x86"))]
2163 {
2164 &[0, 0x8000000000000000]
2165 }
2166 #[cfg(target_arch = "x86")]
2167 {
2168 &[0, 0, 0, 0x80000000]
2169 }
2170 };
2171
2172 assert!(d1.mantissa_digits() == Some(words));
2173 assert!(d1.mantissa_max_bit_len() == Some(DEFAULT_P));
2174 assert!(d1.precision() == Some(DEFAULT_P));
2175 assert!(d1.sign() == Some(Sign::Pos));
2176
2177 assert!(INF_POS.exponent().is_none());
2178 assert!(INF_POS.mantissa_digits().is_none());
2179 assert!(INF_POS.mantissa_max_bit_len().is_none());
2180 assert!(INF_POS.precision().is_none());
2181 assert!(INF_POS.sign() == Some(Sign::Pos));
2182
2183 assert!(INF_NEG.exponent().is_none());
2184 assert!(INF_NEG.mantissa_digits().is_none());
2185 assert!(INF_NEG.mantissa_max_bit_len().is_none());
2186 assert!(INF_NEG.precision().is_none());
2187 assert!(INF_NEG.sign() == Some(Sign::Neg));
2188
2189 assert!(NAN.exponent().is_none());
2190 assert!(NAN.mantissa_digits().is_none());
2191 assert!(NAN.mantissa_max_bit_len().is_none());
2192 assert!(NAN.precision().is_none());
2193 assert!(NAN.sign().is_none());
2194
2195 INF_POS.clone().set_exponent(1);
2196 INF_POS.clone().set_precision(1, rm).unwrap();
2197 INF_POS.clone().set_sign(Sign::Pos);
2198
2199 INF_NEG.clone().set_exponent(1);
2200 INF_NEG.clone().set_precision(1, rm).unwrap();
2201 INF_NEG.clone().set_sign(Sign::Pos);
2202
2203 NAN.clone().set_exponent(1);
2204 NAN.clone().set_precision(1, rm).unwrap();
2205 NAN.clone().set_sign(Sign::Pos);
2206
2207 assert!(INF_POS.min(&ONE).cmp(&ONE) == Some(0));
2208 assert!(INF_NEG.min(&ONE).is_inf_neg());
2209 assert!(NAN.min(&ONE).is_nan());
2210 assert!(ONE.min(&INF_POS).cmp(&ONE) == Some(0));
2211 assert!(ONE.min(&INF_NEG).is_inf_neg());
2212 assert!(ONE.min(&NAN).is_nan());
2213 assert!(NAN.min(&INF_POS).is_nan());
2214 assert!(NAN.min(&INF_NEG).is_nan());
2215 assert!(NAN.min(&NAN).is_nan());
2216 assert!(INF_NEG.min(&INF_POS).is_inf_neg());
2217 assert!(INF_POS.min(&INF_NEG).is_inf_neg());
2218 assert!(INF_POS.min(&INF_POS).is_inf_pos());
2219 assert!(INF_NEG.min(&INF_NEG).is_inf_neg());
2220
2221 assert!(INF_POS.max(&ONE).is_inf_pos());
2222 assert!(INF_NEG.max(&ONE).cmp(&ONE) == Some(0));
2223 assert!(NAN.max(&ONE).is_nan());
2224 assert!(ONE.max(&INF_POS).is_inf_pos());
2225 assert!(ONE.max(&INF_NEG).cmp(&ONE) == Some(0));
2226 assert!(ONE.max(&NAN).is_nan());
2227 assert!(NAN.max(&INF_POS).is_nan());
2228 assert!(NAN.max(&INF_NEG).is_nan());
2229 assert!(NAN.max(&NAN).is_nan());
2230 assert!(INF_NEG.max(&INF_POS).is_inf_pos());
2231 assert!(INF_POS.max(&INF_NEG).is_inf_pos());
2232 assert!(INF_POS.max(&INF_POS).is_inf_pos());
2233 assert!(INF_NEG.max(&INF_NEG).is_inf_neg());
2234
2235 assert!(ONE.clamp(&ONE.neg(), &TWO).cmp(&ONE) == Some(0));
2236 assert!(ONE.clamp(&TWO, &ONE).is_nan());
2237 assert!(ONE.clamp(&INF_POS, &ONE).is_nan());
2238 assert!(ONE.clamp(&TWO, &INF_NEG).is_nan());
2239 assert!(ONE.neg().clamp(&ONE, &TWO).cmp(&ONE) == Some(0));
2240 assert!(TWO.clamp(&ONE.neg(), &ONE).cmp(&ONE) == Some(0));
2241 assert!(INF_POS.clamp(&ONE, &TWO).cmp(&TWO) == Some(0));
2242 assert!(INF_POS.clamp(&ONE, &INF_POS).is_inf_pos());
2243 assert!(INF_POS.clamp(&INF_NEG, &ONE).cmp(&ONE) == Some(0));
2244 assert!(INF_POS.clamp(&NAN, &INF_POS).is_nan());
2245 assert!(INF_POS.clamp(&ONE, &NAN).is_nan());
2246 assert!(INF_POS.clamp(&NAN, &NAN).is_nan());
2247 assert!(INF_NEG.clamp(&ONE, &TWO).cmp(&ONE) == Some(0));
2248 assert!(INF_NEG.clamp(&ONE, &INF_POS).cmp(&ONE) == Some(0));
2249 assert!(INF_NEG.clamp(&INF_NEG, &ONE).is_inf_neg());
2250 assert!(INF_NEG.clamp(&NAN, &INF_POS).is_nan());
2251 assert!(INF_NEG.clamp(&ONE, &NAN).is_nan());
2252 assert!(INF_NEG.clamp(&NAN, &NAN).is_nan());
2253 assert!(NAN.clamp(&ONE, &TWO).is_nan());
2254 assert!(NAN.clamp(&NAN, &TWO).is_nan());
2255 assert!(NAN.clamp(&ONE, &NAN).is_nan());
2256 assert!(NAN.clamp(&NAN, &NAN).is_nan());
2257 assert!(NAN.clamp(&INF_NEG, &INF_POS).is_nan());
2258
2259 assert!(BigFloat::min_positive(DEFAULT_P).classify() == FpCategory::Subnormal);
2260 assert!(INF_POS.classify() == FpCategory::Infinite);
2261 assert!(INF_NEG.classify() == FpCategory::Infinite);
2262 assert!(NAN.classify() == FpCategory::Nan);
2263 assert!(ONE.classify() == FpCategory::Normal);
2264
2265 assert!(!INF_POS.is_subnormal());
2266 assert!(!INF_NEG.is_subnormal());
2267 assert!(!NAN.is_subnormal());
2268 assert!(BigFloat::min_positive(DEFAULT_P).is_subnormal());
2269 assert!(!BigFloat::min_positive_normal(DEFAULT_P).is_subnormal());
2270 assert!(!BigFloat::max_value(DEFAULT_P).is_subnormal());
2271 assert!(!BigFloat::min_value(DEFAULT_P).is_subnormal());
2272
2273 let n1 = BigFloat::convert_from_radix(
2274 Sign::Pos,
2275 &[],
2276 0,
2277 Radix::Dec,
2278 usize::MAX - 1,
2279 RoundingMode::None,
2280 &mut cc,
2281 );
2282 assert!(n1.is_nan());
2283 assert!(n1.err() == Some(Error::InvalidArgument));
2284
2285 assert!(
2286 n1.convert_to_radix(Radix::Dec, RoundingMode::None, &mut cc)
2287 == Err(Error::InvalidArgument)
2288 );
2289 assert!(
2290 INF_POS.convert_to_radix(Radix::Dec, RoundingMode::None, &mut cc)
2291 == Err(Error::InvalidArgument)
2292 );
2293 assert!(
2294 INF_NEG.convert_to_radix(Radix::Dec, RoundingMode::None, &mut cc)
2295 == Err(Error::InvalidArgument)
2296 );
2297 }
2298
2299 #[cfg(feature = "std")]
2300 #[test]
2301 fn test_ops_std() {
2302 let mut cc = Consts::new().unwrap();
2303
2304 let d1 = BigFloat::parse(
2305 "0.0123456789012345678901234567890123456789",
2306 Radix::Dec,
2307 DEFAULT_P,
2308 RoundingMode::None,
2309 &mut cc,
2310 );
2311
2312 let d1str = format!("{}", d1);
2313 assert_eq!(&d1str, "1.23456789012345678901234567890123456789e-2");
2314 let mut d2 = BigFloat::from_str(&d1str).unwrap();
2315 d2.set_precision(DEFAULT_P, RoundingMode::ToEven).unwrap();
2316 assert_eq!(d2, d1);
2317
2318 let d1 = BigFloat::parse(
2319 "-123.456789012345678901234567890123456789",
2320 Radix::Dec,
2321 DEFAULT_P,
2322 RoundingMode::None,
2323 &mut cc,
2324 );
2325 let d1str = format!("{}", d1);
2326 assert_eq!(&d1str, "-1.23456789012345678901234567890123456789e+2");
2327 let mut d2 = BigFloat::from_str(&d1str).unwrap();
2328 d2.set_precision(DEFAULT_P, RoundingMode::ToEven).unwrap();
2329 assert_eq!(d2, d1);
2330
2331 let d1str = format!("{}", INF_POS);
2332 assert_eq!(d1str, "Inf");
2333
2334 let d1str = format!("{}", INF_NEG);
2335 assert_eq!(d1str, "-Inf");
2336
2337 let d1str = format!("{}", NAN);
2338 assert_eq!(d1str, "NaN");
2339
2340 assert!(BigFloat::from_str("abc").is_ok());
2341 assert!(BigFloat::from_str("abc").unwrap().is_nan());
2342 }
2343
2344 #[test]
2345 pub fn test_ops() {
2346 let mut cc = Consts::new().unwrap();
2347
2348 let d1 = -&(TWO.clone());
2349 assert!(d1.is_negative());
2350
2351 let p = DEFAULT_P;
2352 let rm = RoundingMode::ToEven;
2353 assert!(
2354 BigFloat::from_i8(-123, p) == BigFloat::parse("-1.23e+2", Radix::Dec, p, rm, &mut cc)
2355 );
2356 assert!(
2357 BigFloat::from_u8(123, p) == BigFloat::parse("1.23e+2", Radix::Dec, p, rm, &mut cc)
2358 );
2359 assert!(
2360 BigFloat::from_i16(-12312, p)
2361 == BigFloat::parse("-1.2312e+4", Radix::Dec, p, rm, &mut cc)
2362 );
2363 assert!(
2364 BigFloat::from_u16(12312, p)
2365 == BigFloat::parse("1.2312e+4", Radix::Dec, p, rm, &mut cc)
2366 );
2367 assert!(
2368 BigFloat::from_i32(-123456789, p)
2369 == BigFloat::parse("-1.23456789e+8", Radix::Dec, p, rm, &mut cc)
2370 );
2371 assert!(
2372 BigFloat::from_u32(123456789, p)
2373 == BigFloat::parse("1.23456789e+8", Radix::Dec, p, rm, &mut cc)
2374 );
2375 assert!(
2376 BigFloat::from_i64(-1234567890123456789, p)
2377 == BigFloat::parse("-1.234567890123456789e+18", Radix::Dec, p, rm, &mut cc)
2378 );
2379 assert!(
2380 BigFloat::from_u64(1234567890123456789, p)
2381 == BigFloat::parse("1.234567890123456789e+18", Radix::Dec, p, rm, &mut cc)
2382 );
2383 assert!(
2384 BigFloat::from_i128(-123456789012345678901234567890123456789, p)
2385 == BigFloat::parse(
2386 "-1.23456789012345678901234567890123456789e+38",
2387 Radix::Dec,
2388 p,
2389 rm,
2390 &mut cc
2391 )
2392 );
2393 assert!(
2394 BigFloat::from_u128(123456789012345678901234567890123456789, p)
2395 == BigFloat::parse(
2396 "1.23456789012345678901234567890123456789e+38",
2397 Radix::Dec,
2398 p,
2399 rm,
2400 &mut cc
2401 )
2402 );
2403
2404 let neg = BigFloat::from_i8(-3, WORD_BIT_SIZE);
2405 let pos = BigFloat::from_i8(5, WORD_BIT_SIZE);
2406
2407 assert!(pos > neg);
2408 assert!(neg < pos);
2409 assert!(!(pos < neg));
2410 assert!(!(neg > pos));
2411 assert!(INF_NEG < neg);
2412 assert!(INF_NEG < pos);
2413 assert!(INF_NEG < INF_POS);
2414 assert!(!(INF_NEG > neg));
2415 assert!(!(INF_NEG > pos));
2416 assert!(!(INF_NEG > INF_POS));
2417 assert!(INF_POS > neg);
2418 assert!(INF_POS > pos);
2419 assert!(INF_POS > INF_NEG);
2420 assert!(!(INF_POS < neg));
2421 assert!(!(INF_POS < pos));
2422 assert!(!(INF_POS < INF_NEG));
2423 assert!(!(INF_POS > INF_POS));
2424 assert!(!(INF_POS < INF_POS));
2425 assert!(!(INF_NEG > INF_NEG));
2426 assert!(!(INF_NEG < INF_NEG));
2427 assert!(!(INF_POS > NAN));
2428 assert!(!(INF_POS < NAN));
2429 assert!(!(INF_NEG > NAN));
2430 assert!(!(INF_NEG < NAN));
2431 assert!(!(NAN > INF_POS));
2432 assert!(!(NAN < INF_POS));
2433 assert!(!(NAN > INF_NEG));
2434 assert!(!(NAN < INF_NEG));
2435 assert!(!(NAN > NAN));
2436 assert!(!(NAN < NAN));
2437 assert!(!(neg > NAN));
2438 assert!(!(neg < NAN));
2439 assert!(!(pos > NAN));
2440 assert!(!(pos < NAN));
2441 assert!(!(NAN > neg));
2442 assert!(!(NAN < neg));
2443 assert!(!(NAN > pos));
2444 assert!(!(NAN < pos));
2445
2446 assert!(!(NAN == NAN));
2447 assert!(!(NAN == INF_POS));
2448 assert!(!(NAN == INF_NEG));
2449 assert!(!(INF_POS == NAN));
2450 assert!(!(INF_NEG == NAN));
2451 assert!(!(INF_NEG == INF_POS));
2452 assert!(!(INF_POS == INF_NEG));
2453 assert!(!(INF_POS == neg));
2454 assert!(!(INF_POS == pos));
2455 assert!(!(INF_NEG == neg));
2456 assert!(!(INF_NEG == pos));
2457 assert!(!(neg == INF_POS));
2458 assert!(!(pos == INF_POS));
2459 assert!(!(neg == INF_NEG));
2460 assert!(!(pos == INF_NEG));
2461 assert!(!(pos == neg));
2462 assert!(!(neg == pos));
2463 assert!(neg == neg);
2464 assert!(pos == pos);
2465 assert!(INF_NEG == INF_NEG);
2466 assert!(INF_POS == INF_POS);
2467 }
2468}
2469
2470#[cfg(feature = "random")]
2471#[cfg(test)]
2472mod rand_tests {
2473
2474 use super::*;
2475 use crate::defs::EXPONENT_MAX;
2476
2477 #[test]
2478 fn test_rand() {
2479 for _ in 0..1000 {
2480 let p = rand::random::<usize>() % 1000 + DEFAULT_P;
2481 let exp_from;
2482 #[cfg(not(target_arch = "x86"))]
2483 {
2484 exp_from = rand::random::<Exponent>().abs();
2485 }
2486 #[cfg(target_arch = "x86")]
2487 {
2488 use crate::defs::EXPONENT_MIN;
2489 exp_from =
2490 rand::random::<Exponent>().abs() % (EXPONENT_MAX - EXPONENT_MIN) + EXPONENT_MIN;
2491 }
2492 let exp_shift = if EXPONENT_MAX > exp_from {
2493 rand::random::<Exponent>().abs()
2494 % (EXPONENT_MAX as isize - exp_from as isize) as Exponent
2495 } else {
2496 0
2497 };
2498 let exp_to = (exp_from as isize + exp_shift as isize) as Exponent;
2499
2500 let n = BigFloat::random_normal(p, exp_from, exp_to);
2501
2502 assert!(!n.is_subnormal());
2503 assert!(n.exponent().unwrap() >= exp_from && n.exponent().unwrap() <= exp_to);
2504 assert!(n.precision().unwrap() >= p);
2505 }
2506 }
2507}