Skip to main content

number_general/
lib.rs

1//! Provides a generic [`Number`] enum with [`Boolean`], [`Complex`], [`Float`], [`Int`],
2//! and [`UInt`] variants, as well as a [`NumberCollator`], [`ComplexCollator`], and
3//! [`FloatCollator`] since these types do not implement [`Ord`].
4//!
5//! `Number` supports casting with [`safecast`].
6//!
7//! For (de)serialization with `serde`, enable the `"serde"` feature.
8//!
9//! For (de)coding with `destream`, enable the `"stream"` feature.
10//!
11//! Example usage:
12//! ```
13//! # use number_general::{Int, Number};
14//! # use safecast::CastFrom;
15//! let sequence: Vec<Number> = vec![true.into(), 2.into(), 3.5.into(), [1.0, -0.5].into()];
16//! let actual = sequence.into_iter().product();
17//! let expected = Number::from(num::Complex::<f64>::new(7., -3.5));
18//!
19//! assert_eq!(expected, actual);
20//! assert_eq!(Int::cast_from(actual), Int::from(7));
21//! ```
22
23use 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
65/// Define a [`NumberType`] for a non-[`Number`] type such as a Rust primitive.
66///
67/// To access the `NumberType` of a `Number`, use `Instance::class`, e.g. `Number::from(1).class()`.
68pub 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
96/// The error type returned when a `Number` operation fails recoverably.
97pub 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/// A generic number.
122#[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    /// Return `true` if this is floating-point [`Number`], `false` if this is an integer.
133    pub fn is_float(&self) -> bool {
134        matches!(self, Self::Complex(_) | Self::Float(_))
135    }
136
137    /// Return `true` if this is an [`Int`] or [`UInt`].
138    pub fn is_int(&self) -> bool {
139        matches!(self, Self::Int(_) | Self::UInt(_))
140    }
141
142    /// Return `false` if this is a [`Complex`] `Number`.
143    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/// Defines a collation order for [`Number`].
771#[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/// A struct for deserializing a `Number` which implements
801/// [`destream::de::Visitor`] and [`serde::de::Visitor`].
802#[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)] // tests use simple decimal literals for readability
886    #[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)] // tests use explicit literals to validate parsing
953    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}