1use std::cmp::Ordering;
24use std::fmt;
25use std::hash::{Hash, Hasher};
26use std::iter::{Product, Sum};
27use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
28use std::str::FromStr;
29
30use collate::{Collate, Collator};
31use get_size::GetSize;
32use safecast::{CastFrom, CastInto};
33
34mod class;
35#[cfg(feature = "stream")]
36mod destream;
37#[cfg(feature = "hash")]
38mod hash;
39mod instance;
40#[cfg(feature = "serde")]
41mod serde;
42
43pub use class::*;
44pub use instance::*;
45
46#[cfg(any(feature = "serde", feature = "stream"))]
47const ERR_COMPLEX: &str = "a complex number";
48
49#[cfg(any(feature = "serde", feature = "stream"))]
50const ERR_NUMBER: &str = "a Number, like 1 or -2 or 3.14 or [0., -1.414]";
51
52const CANONICAL_NAN32_BITS: u32 = 0x7fc0_0000;
53
54#[inline]
55fn normalized_f32_bits(f: f32) -> u32 {
56 if f == 0.0 {
57 0
58 } else if f.is_nan() {
59 CANONICAL_NAN32_BITS
60 } else {
61 f.to_bits()
62 }
63}
64
65pub trait DType {
69 fn dtype() -> NumberType;
70}
71
72macro_rules! dtype {
73 ($t:ty, $nt:expr) => {
74 impl DType for $t {
75 fn dtype() -> NumberType {
76 $nt
77 }
78 }
79 };
80}
81
82dtype!(bool, NumberType::Bool);
83dtype!(u8, NumberType::UInt(UIntType::U8));
84dtype!(u16, NumberType::UInt(UIntType::U16));
85dtype!(u32, NumberType::UInt(UIntType::U32));
86dtype!(u64, NumberType::UInt(UIntType::U64));
87dtype!(i8, NumberType::Int(IntType::I8));
88dtype!(i16, NumberType::Int(IntType::I16));
89dtype!(i32, NumberType::Int(IntType::I32));
90dtype!(i64, NumberType::Int(IntType::I64));
91dtype!(f32, NumberType::Float(FloatType::F32));
92dtype!(f64, NumberType::Float(FloatType::F64));
93dtype!(_Complex<f32>, NumberType::Complex(ComplexType::C32));
94dtype!(_Complex<f64>, NumberType::Complex(ComplexType::C64));
95
96pub struct Error(String);
98
99impl Error {
100 fn new<E: fmt::Display>(cause: E) -> Self {
101 Self(cause.to_string())
102 }
103}
104
105impl std::error::Error for Error {}
106
107impl fmt::Debug for Error {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 f.write_str(&self.0)
110 }
111}
112
113impl fmt::Display for Error {
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 f.write_str(&self.0)
116 }
117}
118
119type _Complex<T> = num::complex::Complex<T>;
120
121#[derive(Clone, Copy, Eq, get_size_derive::GetSize)]
123pub enum Number {
124 Bool(Boolean),
125 Complex(Complex),
126 Float(Float),
127 Int(Int),
128 UInt(UInt),
129}
130
131impl Number {
132 pub fn is_float(&self) -> bool {
134 matches!(self, Self::Complex(_) | Self::Float(_))
135 }
136
137 pub fn is_int(&self) -> bool {
139 matches!(self, Self::Int(_) | Self::UInt(_))
140 }
141
142 pub fn is_real(&self) -> bool {
144 !matches!(self, Self::Complex(_))
145 }
146}
147
148impl NumberInstance for Number {
149 type Abs = Number;
150 type Exp = Self;
151 type Log = Self;
152 type Round = Self;
153 type Class = NumberType;
154
155 fn class(&self) -> NumberType {
156 match self {
157 Self::Bool(_) => NumberType::Bool,
158 Self::Complex(c) => c.class().into(),
159 Self::Float(f) => f.class().into(),
160 Self::Int(i) => i.class().into(),
161 Self::UInt(u) => u.class().into(),
162 }
163 }
164
165 fn into_type(self, dtype: NumberType) -> Number {
166 use NumberType as NT;
167
168 match dtype {
169 NT::Bool => {
170 let b: Boolean = self.cast_into();
171 b.into()
172 }
173 NT::Complex(ct) => {
174 let c: Complex = self.cast_into();
175 c.into_type(ct).into()
176 }
177 NT::Float(ft) => {
178 let f: Float = self.cast_into();
179 f.into_type(ft).into()
180 }
181 NT::Int(it) => {
182 let i: Int = self.cast_into();
183 i.into_type(it).into()
184 }
185 NT::UInt(ut) => {
186 let u: UInt = self.cast_into();
187 u.into_type(ut).into()
188 }
189 NT::Number => self,
190 }
191 }
192
193 fn abs(self) -> Number {
194 use Number::*;
195 match self {
196 Complex(c) => Float(c.abs()),
197 Float(f) => Float(f.abs()),
198 Int(i) => Int(i.abs()),
199 other => other,
200 }
201 }
202
203 fn exp(self) -> Self::Exp {
204 match self {
205 Self::Complex(this) => this.exp().into(),
206 Self::Float(this) => this.exp().into(),
207 this => Float::cast_from(this).exp().into(),
208 }
209 }
210
211 fn ln(self) -> Self::Log {
212 match self {
213 Self::Bool(b) => b.ln().into(),
214 Self::Complex(this) => this.ln().into(),
215 Self::Float(this) => this.ln().into(),
216 Self::Int(this) => this.ln().into(),
217 Self::UInt(this) => this.ln().into(),
218 }
219 }
220
221 fn log<N: NumberInstance>(self, base: N) -> Self::Log
222 where
223 Float: From<N>,
224 {
225 match self {
226 Self::Complex(this) => this.log(base).into(),
227 Self::Float(this) => this.log(base).into(),
228 this => Float::cast_from(this).log(base).into(),
229 }
230 }
231
232 fn pow(self, exp: Self) -> Self {
233 match self {
234 Self::Complex(this) => Self::Complex(this.pow(exp)),
235 Self::Float(this) => Self::Float(this.pow(exp)),
236 Self::Int(this) => match exp {
237 Self::Complex(exp) => Self::Float(Float::from(this).pow(exp.into())),
238 Self::Float(exp) => Self::Float(Float::from(this).pow(exp.into())),
239 Self::Int(exp) if exp < exp.class().zero() => {
240 Self::Float(Float::from(this).pow(exp.into()))
241 }
242 exp => Self::Int(this.pow(exp)),
243 },
244 Self::UInt(this) => match exp {
245 Self::Complex(exp) => Self::Float(Float::from(this).pow(exp.into())),
246 Self::Float(exp) => Self::Float(Float::from(this).pow(exp.into())),
247 Self::Int(exp) if exp < exp.class().zero() => {
248 Self::Float(Float::from(this).pow(exp.into()))
249 }
250 exp => Self::UInt(this.pow(exp)),
251 },
252 Self::Bool(b) => Self::Bool(b.pow(exp)),
253 }
254 }
255
256 fn round(self) -> Self::Round {
257 match self {
258 Self::Complex(c) => c.round().into(),
259 Self::Float(f) => f.round().into(),
260 other => other,
261 }
262 }
263}
264
265impl FloatInstance for Number {
266 fn is_infinite(&self) -> bool {
267 match self {
268 Self::Complex(c) => c.is_infinite(),
269 Self::Float(f) => f.is_infinite(),
270 _ => false,
271 }
272 }
273
274 fn is_nan(&self) -> bool {
275 match self {
276 Self::Complex(c) => c.is_nan(),
277 Self::Float(f) => f.is_nan(),
278 _ => false,
279 }
280 }
281}
282
283impl PartialEq for Number {
284 fn eq(&self, other: &Self) -> bool {
285 let dtype = Ord::max(self.class(), other.class());
286 let l = (*self).into_type(dtype);
287 let r = (*other).into_type(dtype);
288
289 match (l, r) {
290 (Self::Bool(l), Self::Bool(r)) => l.eq(&r),
291 (Self::Complex(l), Self::Complex(r)) => l.eq(&r),
292 (Self::Float(l), Self::Float(r)) => l.eq(&r),
293 (Self::Int(l), Self::Int(r)) => l.eq(&r),
294 (Self::UInt(l), Self::UInt(r)) => l.eq(&r),
295 _ => {
296 unreachable!("a Number instance must have a specific type, not NumberType::Number")
297 }
298 }
299 }
300}
301
302impl Hash for Number {
303 fn hash<H: Hasher>(&self, state: &mut H) {
304 let c: _Complex<f32> = Complex::cast_from(*self).cast_into();
305 normalized_f32_bits(c.re).hash(state);
306 normalized_f32_bits(c.im).hash(state);
307 }
308}
309
310impl PartialOrd for Number {
311 fn partial_cmp(&self, other: &Number) -> Option<Ordering> {
312 match (self, other) {
313 (Self::Int(l), Self::Int(r)) => l.partial_cmp(r),
314 (Self::UInt(l), Self::UInt(r)) => l.partial_cmp(r),
315 (Self::Float(l), Self::Float(r)) => l.partial_cmp(r),
316 (Self::Bool(l), Self::Bool(r)) => l.partial_cmp(r),
317 (Self::Complex(_), _) => None,
318 (_, Self::Complex(_)) => None,
319
320 (l, r) => {
321 let dtype = Ord::max(l.class(), r.class());
322 let l = l.into_type(dtype);
323 let r = r.into_type(dtype);
324 l.partial_cmp(&r)
325 }
326 }
327 }
328}
329
330macro_rules! number_binop {
331 ($lhs:expr, $rhs:expr, $op:tt) => {{
332 let lhs = $lhs;
333 let rhs = $rhs;
334 let dtype = Ord::max(lhs.class(), rhs.class());
335
336 use NumberType as NT;
337
338 match dtype {
339 NT::Bool => {
340 let lhs: Boolean = lhs.cast_into();
341 (lhs $op rhs.cast_into()).into()
342 }
343 NT::Complex(_) => {
344 let lhs: Complex = lhs.cast_into();
345 (lhs $op rhs.cast_into()).into()
346 }
347 NT::Float(_) => {
348 let lhs: Float = lhs.cast_into();
349 (lhs $op rhs.cast_into()).into()
350 }
351 NT::Int(_) => {
352 let lhs: Int = lhs.cast_into();
353 (lhs $op rhs.cast_into()).into()
354 }
355 NT::UInt(_) => {
356 let lhs: UInt = lhs.cast_into();
357 (lhs $op rhs.cast_into()).into()
358 }
359 NT::Number => unreachable!(
360 "a Number instance must have a specific type, not NumberType::Number"
361 ),
362 }
363 }};
364}
365
366impl Add for Number {
367 type Output = Self;
368
369 fn add(self, other: Number) -> Self {
370 number_binop!(self, other, +)
371 }
372}
373
374impl AddAssign for Number {
375 fn add_assign(&mut self, other: Self) {
376 let sum = *self + other;
377 *self = sum;
378 }
379}
380
381impl Rem for Number {
382 type Output = Self;
383
384 fn rem(self, other: Self) -> Self::Output {
385 number_binop!(self, other, %)
386 }
387}
388
389impl RemAssign for Number {
390 fn rem_assign(&mut self, other: Self) {
391 let rem = *self % other;
392 *self = rem;
393 }
394}
395
396impl Sub for Number {
397 type Output = Self;
398
399 fn sub(self, other: Number) -> Self {
400 number_binop!(self, other, -)
401 }
402}
403
404impl SubAssign for Number {
405 fn sub_assign(&mut self, other: Self) {
406 let difference = *self - other;
407 *self = difference;
408 }
409}
410
411impl Sum for Number {
412 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
413 let mut sum = NumberType::Number.zero();
414 for i in iter {
415 sum += i;
416 }
417 sum
418 }
419}
420
421impl Mul for Number {
422 type Output = Self;
423
424 fn mul(self, other: Number) -> Self {
425 number_binop!(self, other, *)
426 }
427}
428
429impl MulAssign for Number {
430 fn mul_assign(&mut self, other: Self) {
431 let product = *self * other;
432 *self = product;
433 }
434}
435
436impl Div for Number {
437 type Output = Self;
438
439 fn div(self, other: Number) -> Self {
440 number_binop!(self, other, /)
441 }
442}
443
444impl DivAssign for Number {
445 fn div_assign(&mut self, other: Self) {
446 let div = *self / other;
447 *self = div;
448 }
449}
450
451impl Product for Number {
452 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
453 let zero = NumberType::Number.zero();
454 let mut product = NumberType::Number.one();
455
456 for i in iter {
457 if i == zero {
458 return zero;
459 }
460
461 product *= i;
462 }
463 product
464 }
465}
466
467macro_rules! trig {
468 ($fun:ident) => {
469 fn $fun(self) -> Self::Out {
470 match self {
471 Self::Bool(b) => b.$fun().into(),
472 Self::Complex(c) => c.$fun().into(),
473 Self::Float(f) => f.$fun().into(),
474 Self::Int(i) => i.$fun().into(),
475 Self::UInt(u) => u.$fun().into(),
476 }
477 }
478 };
479}
480
481impl Trigonometry for Number {
482 type Out = Self;
483
484 trig! {asin}
485 trig! {sin}
486 trig! {asinh}
487 trig! {sinh}
488
489 trig! {acos}
490 trig! {cos}
491 trig! {acosh}
492 trig! {cosh}
493
494 trig! {atan}
495 trig! {tan}
496 trig! {atanh}
497 trig! {tanh}
498}
499
500impl Default for Number {
501 fn default() -> Self {
502 Self::Bool(Boolean::default())
503 }
504}
505
506impl From<bool> for Number {
507 fn from(b: bool) -> Self {
508 Self::Bool(b.into())
509 }
510}
511
512impl From<Boolean> for Number {
513 fn from(b: Boolean) -> Number {
514 Number::Bool(b)
515 }
516}
517
518macro_rules! from_uint {
519 ($($t:ty),+ $(,)?) => {
520 $(
521 impl From<$t> for Number {
522 fn from(u: $t) -> Self {
523 Self::UInt(u.into())
524 }
525 }
526 )+
527 };
528}
529
530macro_rules! from_int {
531 ($($t:ty),+ $(,)?) => {
532 $(
533 impl From<$t> for Number {
534 fn from(i: $t) -> Self {
535 Self::Int(i.into())
536 }
537 }
538 )+
539 };
540}
541
542macro_rules! from_float {
543 ($($t:ty),+ $(,)?) => {
544 $(
545 impl From<$t> for Number {
546 fn from(f: $t) -> Self {
547 Self::Float(f.into())
548 }
549 }
550 )+
551 };
552}
553
554from_uint!(u8, u16, u32, u64);
555
556impl From<UInt> for Number {
557 fn from(u: UInt) -> Number {
558 Number::UInt(u)
559 }
560}
561
562from_int!(i8, i16, i32, i64);
563
564impl From<Int> for Number {
565 fn from(i: Int) -> Number {
566 Number::Int(i)
567 }
568}
569
570from_float!(f32, f64);
571
572impl From<Float> for Number {
573 fn from(f: Float) -> Number {
574 Number::Float(f)
575 }
576}
577
578impl From<[f32; 2]> for Number {
579 fn from(arr: [f32; 2]) -> Self {
580 Self::Complex(arr.into())
581 }
582}
583
584impl From<[f64; 2]> for Number {
585 fn from(arr: [f64; 2]) -> Self {
586 Self::Complex(arr.into())
587 }
588}
589
590impl From<_Complex<f32>> for Number {
591 fn from(c: _Complex<f32>) -> Self {
592 Self::Complex(c.into())
593 }
594}
595
596impl From<_Complex<f64>> for Number {
597 fn from(c: _Complex<f64>) -> Self {
598 Self::Complex(c.into())
599 }
600}
601
602impl From<Complex> for Number {
603 fn from(c: Complex) -> Number {
604 Number::Complex(c)
605 }
606}
607
608impl FromStr for Number {
609 type Err = Error;
610
611 fn from_str(s: &str) -> Result<Self, Self::Err> {
612 let s = s.trim();
613 let bytes = s.as_bytes();
614
615 if s.is_empty() {
616 Err(Error(
617 "cannot parse a Number from an empty string".to_string(),
618 ))
619 } else if bytes.len() == 1 {
620 Int::from_str(s).map(Self::from)
621 } else if bytes
622 .windows(2)
623 .any(|w| matches!(w, [b'e' | b'E', b'+' | b'-']))
624 {
625 Float::from_str(s).map(Self::from)
626 } else if bytes.iter().skip(1).any(|b| matches!(b, b'+' | b'-')) {
627 Complex::from_str(s).map(Self::from)
628 } else if bytes.contains(&b'.') || bytes.iter().any(|b| matches!(b, b'e' | b'E')) {
629 Float::from_str(s).map(Self::from)
630 } else {
631 Int::from_str(s).map(Self::from)
632 }
633 }
634}
635
636impl CastFrom<Number> for Boolean {
637 fn cast_from(number: Number) -> Boolean {
638 match number {
639 Number::Bool(b) => b,
640 Number::Complex(c) => Boolean::cast_from(c),
641 Number::Float(f) => Boolean::cast_from(f),
642 Number::Int(i) => Boolean::cast_from(i),
643 Number::UInt(u) => Boolean::from(bool::cast_from(u)),
644 }
645 }
646}
647
648impl CastFrom<Number> for bool {
649 fn cast_from(n: Number) -> bool {
650 Boolean::cast_from(n).cast_into()
651 }
652}
653
654impl CastFrom<Number> for _Complex<f32> {
655 fn cast_from(n: Number) -> _Complex<f32> {
656 Complex::cast_from(n).cast_into()
657 }
658}
659
660impl CastFrom<Number> for _Complex<f64> {
661 fn cast_from(n: Number) -> _Complex<f64> {
662 Complex::cast_from(n).cast_into()
663 }
664}
665
666impl CastFrom<Number> for f32 {
667 fn cast_from(n: Number) -> f32 {
668 Float::cast_from(n).cast_into()
669 }
670}
671impl CastFrom<Number> for f64 {
672 fn cast_from(n: Number) -> f64 {
673 Float::cast_from(n).cast_into()
674 }
675}
676
677impl CastFrom<Number> for Float {
678 fn cast_from(number: Number) -> Float {
679 use Number::*;
680 match number {
681 Bool(b) => Self::cast_from(b),
682 Complex(c) => Self::cast_from(c),
683 Float(f) => f,
684 Int(i) => Self::cast_from(i),
685 UInt(u) => Self::cast_from(u),
686 }
687 }
688}
689
690impl CastFrom<Number> for i8 {
691 fn cast_from(n: Number) -> i8 {
692 Int::cast_from(n).cast_into()
693 }
694}
695
696impl CastFrom<Number> for i16 {
697 fn cast_from(n: Number) -> i16 {
698 Int::cast_from(n).cast_into()
699 }
700}
701
702impl CastFrom<Number> for i32 {
703 fn cast_from(n: Number) -> i32 {
704 Int::cast_from(n).cast_into()
705 }
706}
707
708impl CastFrom<Number> for i64 {
709 fn cast_from(n: Number) -> i64 {
710 Int::cast_from(n).cast_into()
711 }
712}
713
714impl CastFrom<Number> for Int {
715 fn cast_from(number: Number) -> Int {
716 use Number::*;
717 match number {
718 Bool(b) => Self::cast_from(b),
719 Complex(c) => Self::cast_from(c),
720 Float(f) => Self::cast_from(f),
721 Int(i) => i,
722 UInt(u) => Self::cast_from(u),
723 }
724 }
725}
726
727impl CastFrom<Number> for u8 {
728 fn cast_from(n: Number) -> u8 {
729 UInt::cast_from(n).cast_into()
730 }
731}
732
733impl CastFrom<Number> for u16 {
734 fn cast_from(n: Number) -> u16 {
735 UInt::cast_from(n).cast_into()
736 }
737}
738
739impl CastFrom<Number> for u32 {
740 fn cast_from(n: Number) -> u32 {
741 UInt::cast_from(n).cast_into()
742 }
743}
744
745impl CastFrom<Number> for u64 {
746 fn cast_from(n: Number) -> u64 {
747 UInt::cast_from(n).cast_into()
748 }
749}
750
751impl CastFrom<Number> for usize {
752 fn cast_from(n: Number) -> usize {
753 UInt::cast_from(n).cast_into()
754 }
755}
756
757impl CastFrom<Number> for UInt {
758 fn cast_from(number: Number) -> UInt {
759 use Number::*;
760 match number {
761 Bool(b) => Self::cast_from(b),
762 Complex(c) => Self::cast_from(c),
763 Float(f) => Self::cast_from(f),
764 Int(i) => Self::cast_from(i),
765 UInt(u) => u,
766 }
767 }
768}
769
770#[derive(Copy, Clone, Default, Eq, PartialEq)]
772pub struct NumberCollator {
773 bool: Collator<Boolean>,
774 complex: ComplexCollator,
775 float: FloatCollator,
776 int: Collator<Int>,
777 uint: Collator<UInt>,
778}
779
780impl Collate for NumberCollator {
781 type Value = Number;
782
783 fn cmp(&self, left: &Self::Value, right: &Self::Value) -> Ordering {
784 match (left, right) {
785 (Number::Bool(l), Number::Bool(r)) => self.bool.cmp(l, r),
786 (Number::Complex(l), Number::Complex(r)) => self.complex.cmp(l, r),
787 (Number::Float(l), Number::Float(r)) => self.float.cmp(l, r),
788 (Number::Int(l), Number::Int(r)) => self.int.cmp(l, r),
789 (Number::UInt(l), Number::UInt(r)) => self.uint.cmp(l, r),
790 (l, r) => {
791 let dtype = Ord::max(l.class(), r.class());
792 let l = l.into_type(dtype);
793 let r = r.into_type(dtype);
794 self.cmp(&l, &r)
795 }
796 }
797 }
798}
799
800#[cfg(any(feature = "serde", feature = "stream"))]
803pub struct NumberVisitor;
804
805#[cfg(any(feature = "serde", feature = "stream"))]
806impl NumberVisitor {
807 #[inline]
808 fn bool<E>(self, b: bool) -> Result<Number, E> {
809 Ok(Number::Bool(b.into()))
810 }
811
812 #[inline]
813 fn i8<E>(self, i: i8) -> Result<Number, E> {
814 Ok(Number::Int(Int::I8(i)))
815 }
816
817 #[inline]
818 fn i16<E>(self, i: i16) -> Result<Number, E> {
819 Ok(Number::Int(Int::I16(i)))
820 }
821
822 #[inline]
823 fn i32<E>(self, i: i32) -> Result<Number, E> {
824 Ok(Number::Int(Int::I32(i)))
825 }
826
827 #[inline]
828 fn i64<E>(self, i: i64) -> Result<Number, E> {
829 Ok(Number::Int(Int::I64(i)))
830 }
831
832 #[inline]
833 fn u8<E>(self, u: u8) -> Result<Number, E> {
834 Ok(Number::UInt(UInt::U8(u)))
835 }
836
837 #[inline]
838 fn u16<E>(self, u: u16) -> Result<Number, E> {
839 Ok(Number::UInt(UInt::U16(u)))
840 }
841
842 #[inline]
843 fn u32<E>(self, u: u32) -> Result<Number, E> {
844 Ok(Number::UInt(UInt::U32(u)))
845 }
846
847 #[inline]
848 fn u64<E>(self, u: u64) -> Result<Number, E> {
849 Ok(Number::UInt(UInt::U64(u)))
850 }
851
852 #[inline]
853 fn f32<E>(self, f: f32) -> Result<Number, E> {
854 Ok(Number::Float(Float::F32(f)))
855 }
856
857 #[inline]
858 fn f64<E>(self, f: f64) -> Result<Number, E> {
859 Ok(Number::Float(Float::F64(f)))
860 }
861}
862
863impl fmt::Debug for Number {
864 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
865 write!(f, "{} ({})", self, self.class())
866 }
867}
868
869impl fmt::Display for Number {
870 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
871 match self {
872 Number::Bool(b) => fmt::Display::fmt(b, f),
873 Number::Complex(c) => fmt::Display::fmt(c, f),
874 Number::Float(n) => fmt::Display::fmt(n, f),
875 Number::Int(i) => fmt::Display::fmt(i, f),
876 Number::UInt(u) => fmt::Display::fmt(u, f),
877 }
878 }
879}
880
881#[cfg(test)]
882mod tests {
883 use super::*;
884
885 #[allow(clippy::approx_constant)] #[test]
887 fn test_complex() {
888 let n = Complex::from([1.23, -3.14]);
889 assert_eq!(n.re(), Float::from(1.23));
890 assert_eq!(n.im(), Float::from(-3.14));
891 }
892
893 #[test]
894 fn test_log() {
895 let n = 1.23f32;
896 assert_eq!(n.ln(), f32::cast_from(Number::from(n).ln()));
897 assert_eq!(
898 (-n).ln().is_nan(),
899 f32::cast_from(Number::from(-n).ln()).is_nan()
900 );
901 }
902
903 #[test]
904 fn test_ops() {
905 let ones = [
906 Number::from(true),
907 Number::from(1u8),
908 Number::from(1u16),
909 Number::from(1u32),
910 Number::from(1u64),
911 Number::from(1i16),
912 Number::from(1i32),
913 Number::from(1i64),
914 Number::from(1f32),
915 Number::from(1f64),
916 Number::from(_Complex::new(1f32, 0f32)),
917 Number::from(_Complex::new(1f64, 0f64)),
918 ];
919
920 let f = Number::from(false);
921 let t = Number::from(true);
922 let two = Number::from(2);
923
924 for one in &ones {
925 let one = *one;
926 let zero = one.class().zero();
927
928 assert_eq!(one, one.class().one());
929
930 assert_eq!(two, one * two);
931 assert_eq!(one, (one * two) - one);
932 assert_eq!(two, (one * two) / one);
933 assert_eq!(zero, one * zero);
934 assert_eq!(two.log(Float::cast_from(two)), one);
935 assert_eq!(two.ln() / two.ln(), one);
936
937 if one.is_real() {
938 assert_eq!(zero, two % one);
939 assert_eq!(one, one.pow(zero));
940 assert_eq!(one * one, one.pow(two));
941 assert_eq!(two.pow(two), (one * two).pow(two));
942 }
943
944 assert_eq!(f, one.not());
945 assert_eq!(f, one.and(zero));
946 assert_eq!(t, one.or(zero));
947 assert_eq!(t, one.xor(zero));
948 }
949 }
950
951 #[test]
952 #[allow(clippy::approx_constant)] fn test_parse() {
954 assert_eq!(Number::from_str("12").unwrap(), Number::from(12));
955 assert_eq!(Number::from_str("1e6").unwrap(), Number::from(1e6));
956 assert_eq!(Number::from_str("1e-6").unwrap(), Number::from(1e-6));
957 assert_eq!(Number::from_str("1e-06").unwrap(), Number::from(1e-6));
958 assert_eq!(Number::from_str("+31.4").unwrap(), Number::from(31.4));
959 assert_eq!(Number::from_str("-3.14").unwrap(), Number::from(-3.14));
960 assert_eq!(
961 Number::from_str("3.14+1.414i").unwrap(),
962 Number::from(num::Complex::new(3.14, 1.414))
963 );
964 assert_eq!(
965 Number::from_str("1+2i").unwrap(),
966 Number::from(num::Complex::new(1., 2.))
967 );
968 assert_eq!(
969 Number::from_str("1.0-2i").unwrap(),
970 Number::from(num::Complex::new(1., -2.))
971 );
972 }
973}