1use std::cmp::Ordering;
2use std::fmt;
3use std::iter::{Product, Sum};
4use std::ops::*;
5
6use safecast::*;
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use super::instance::{Boolean, Complex, Float, Int, UInt};
11use super::{Number, _Complex};
12
13pub trait NumberClass: Default + Into<NumberType> + Ord + Send + fmt::Display {
15 type Instance: NumberInstance;
16
17 fn cast(&self, n: Number) -> Self::Instance;
19
20 fn is_complex(&self) -> bool {
22 return false;
23 }
24
25 fn is_real(&self) -> bool {
27 !self.is_complex()
28 }
29
30 fn size(self) -> usize;
32
33 fn one(&self) -> <Self as NumberClass>::Instance;
35
36 fn zero(&self) -> <Self as NumberClass>::Instance;
38}
39
40pub trait NumberInstance:
42 Copy
43 + Default
44 + Sized
45 + From<Boolean>
46 + Into<Number>
47 + Add<Output = Self>
48 + AddAssign
49 + Sub<Output = Self>
50 + SubAssign
51 + Mul<Output = Self>
52 + MulAssign
53 + Div<Output = Self>
54 + DivAssign
55 + Product
56 + Sum
57 + fmt::Debug
58 + fmt::Display
59{
60 type Abs: NumberInstance;
61 type Exp: NumberInstance;
62 type Log: NumberInstance;
63 type Round: NumberInstance;
64 type Class: NumberClass<Instance = Self>;
65
66 fn class(&self) -> Self::Class;
68
69 fn into_type(
71 self,
72 dtype: <Self as NumberInstance>::Class,
73 ) -> <<Self as NumberInstance>::Class as NumberClass>::Instance;
74
75 fn abs(self) -> Self::Abs;
77
78 fn exp(self) -> Self::Exp;
80
81 fn ln(self) -> Self::Log;
83
84 fn log<N: NumberInstance>(self, base: N) -> Self::Log
86 where
87 Float: From<N>;
88
89 fn pow(self, exp: Number) -> Self;
93
94 fn and(self, other: Self) -> Self
96 where
97 Boolean: CastFrom<Self>,
98 {
99 Boolean::cast_from(self)
100 .and(Boolean::cast_from(other))
101 .into()
102 }
103
104 fn not(self) -> Self
106 where
107 Boolean: CastFrom<Self>,
108 {
109 Boolean::cast_from(self).not().into()
110 }
111
112 fn or(self, other: Self) -> Self
114 where
115 Boolean: CastFrom<Self>,
116 {
117 let this = Boolean::cast_from(self);
118 let that = Boolean::cast_from(other);
119 this.or(that).into()
120 }
121
122 fn round(self) -> Self::Round;
124
125 fn xor(self, other: Self) -> Self
127 where
128 Boolean: CastFrom<Self>,
129 {
130 let this = Boolean::cast_from(self);
131 let that = Boolean::cast_from(other);
132 this.xor(that).into()
133 }
134}
135
136pub trait Trigonometry {
138 type Out: NumberInstance;
139
140 fn asin(self) -> Self::Out;
142
143 fn sin(self) -> Self::Out;
145
146 fn asinh(self) -> Self::Out;
148
149 fn sinh(self) -> Self::Out;
151
152 fn acos(self) -> Self::Out;
154
155 fn cos(self) -> Self::Out;
157
158 fn acosh(self) -> Self::Out;
160
161 fn cosh(self) -> Self::Out;
163
164 fn atan(self) -> Self::Out;
166
167 fn tan(self) -> Self::Out;
169
170 fn atanh(self) -> Self::Out;
172
173 fn tanh(self) -> Self::Out;
175}
176
177pub trait RealInstance: PartialEq + PartialOrd + Sized {
179 const ONE: Self;
180 const ZERO: Self;
181
182 fn is_positive(&self) -> bool {
184 self >= &Self::ZERO
185 }
186
187 fn is_negative(&self) -> bool {
189 self < &Self::ZERO
190 }
191
192 fn is_zero(&self) -> bool {
194 self == &Self::ZERO
195 }
196}
197
198pub trait FloatInstance {
200 fn is_infinite(&self) -> bool;
202
203 fn is_nan(&self) -> bool;
205}
206
207#[derive(Clone, Copy, Hash, Eq, PartialEq)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210pub enum ComplexType {
211 C32,
212 C64,
213 Complex,
214}
215
216impl Default for ComplexType {
217 fn default() -> Self {
218 Self::Complex
219 }
220}
221
222impl NumberClass for ComplexType {
223 type Instance = Complex;
224
225 fn cast(&self, n: Number) -> Complex {
226 match self {
227 Self::C64 => Complex::C64(n.cast_into()),
228 _ => Complex::C32(n.cast_into()),
229 }
230 }
231
232 fn is_complex(&self) -> bool {
233 true
234 }
235
236 fn size(self) -> usize {
237 match self {
238 Self::C32 => 8,
239 Self::C64 => 16,
240 Self::Complex => 16,
241 }
242 }
243
244 fn one(&self) -> Complex {
245 match self {
246 Self::C32 => _Complex::<f32>::new(1f32, 0f32).into(),
247 Self::C64 => _Complex::<f64>::new(1f64, 0f64).into(),
248 Self::Complex => _Complex::<f32>::new(1f32, 0f32).into(),
249 }
250 }
251
252 fn zero(&self) -> Complex {
253 match self {
254 Self::C32 => _Complex::<f32>::new(0f32, 0f32).into(),
255 Self::C64 => _Complex::<f64>::new(0f64, 0f64).into(),
256 Self::Complex => _Complex::<f32>::new(0f32, 0f32).into(),
257 }
258 }
259}
260
261impl Ord for ComplexType {
262 fn cmp(&self, other: &Self) -> Ordering {
263 match (self, other) {
264 (Self::C32, Self::C32) => Ordering::Equal,
265 (Self::C64, Self::C64) => Ordering::Equal,
266 (Self::Complex, Self::Complex) => Ordering::Equal,
267
268 (Self::Complex, _) => Ordering::Greater,
269 (_, Self::Complex) => Ordering::Less,
270
271 (Self::C64, Self::C32) => Ordering::Greater,
272 (Self::C32, Self::C64) => Ordering::Less,
273 }
274 }
275}
276
277impl PartialOrd for ComplexType {
278 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
279 Some(self.cmp(other))
280 }
281}
282
283impl From<ComplexType> for NumberType {
284 fn from(ct: ComplexType) -> NumberType {
285 Self::Complex(ct)
286 }
287}
288
289impl fmt::Debug for ComplexType {
290 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
291 fmt::Display::fmt(self, f)
292 }
293}
294
295impl fmt::Display for ComplexType {
296 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
297 match self {
298 Self::C32 => write!(f, "32-bit complex number"),
299 Self::C64 => write!(f, "64-bit complex number"),
300 Self::Complex => write!(f, "complex number"),
301 }
302 }
303}
304
305#[derive(Clone, Copy, Default, Hash, Eq, PartialEq)]
307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
308pub struct BooleanType;
309
310impl NumberClass for BooleanType {
311 type Instance = Boolean;
312
313 fn cast(&self, n: Number) -> Boolean {
314 n.cast_into()
315 }
316
317 fn size(self) -> usize {
318 1
319 }
320
321 fn one(&self) -> Boolean {
322 true.into()
323 }
324
325 fn zero(&self) -> Boolean {
326 false.into()
327 }
328}
329
330impl Ord for BooleanType {
331 fn cmp(&self, _other: &Self) -> Ordering {
332 Ordering::Equal
333 }
334}
335
336impl PartialOrd for BooleanType {
337 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
338 Some(self.cmp(other))
339 }
340}
341
342impl From<BooleanType> for NumberType {
343 fn from(_bt: BooleanType) -> NumberType {
344 NumberType::Bool
345 }
346}
347
348impl fmt::Debug for BooleanType {
349 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
350 fmt::Display::fmt(self, f)
351 }
352}
353
354impl fmt::Display for BooleanType {
355 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
356 write!(f, "Boolean")
357 }
358}
359
360#[derive(Clone, Copy, Hash, Eq, PartialEq)]
362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
363pub enum FloatType {
364 F32,
365 F64,
366 Float,
367}
368
369impl Default for FloatType {
370 fn default() -> Self {
371 Self::Float
372 }
373}
374
375impl NumberClass for FloatType {
376 type Instance = Float;
377
378 fn cast(&self, n: Number) -> Float {
379 match self {
380 Self::F64 => Float::F64(n.cast_into()),
381 _ => Float::F32(n.cast_into()),
382 }
383 }
384
385 fn size(self) -> usize {
386 match self {
387 Self::F32 => 4,
388 Self::F64 => 8,
389 Self::Float => 8,
390 }
391 }
392
393 fn one(&self) -> Float {
394 match self {
395 Self::F32 => 1f32.into(),
396 Self::F64 => 1f64.into(),
397 Self::Float => 1f32.into(),
398 }
399 }
400
401 fn zero(&self) -> Float {
402 match self {
403 Self::F32 => 0f32.into(),
404 Self::F64 => 0f64.into(),
405 Self::Float => 0f32.into(),
406 }
407 }
408}
409
410impl Ord for FloatType {
411 fn cmp(&self, other: &Self) -> Ordering {
412 match (self, other) {
413 (Self::F32, Self::F32) => Ordering::Equal,
414 (Self::F64, Self::F64) => Ordering::Equal,
415 (Self::Float, Self::Float) => Ordering::Equal,
416
417 (Self::Float, _) => Ordering::Greater,
418 (_, Self::Float) => Ordering::Less,
419
420 (Self::F64, Self::F32) => Ordering::Greater,
421 (Self::F32, Self::F64) => Ordering::Less,
422 }
423 }
424}
425
426impl PartialOrd for FloatType {
427 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
428 Some(self.cmp(other))
429 }
430}
431
432impl From<FloatType> for NumberType {
433 fn from(ft: FloatType) -> NumberType {
434 NumberType::Float(ft)
435 }
436}
437
438impl fmt::Debug for FloatType {
439 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
440 fmt::Display::fmt(self, f)
441 }
442}
443
444impl fmt::Display for FloatType {
445 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
446 use FloatType::*;
447 match self {
448 F32 => write!(f, "32-bit float"),
449 F64 => write!(f, "64-bit float"),
450 Float => write!(f, "float"),
451 }
452 }
453}
454
455#[derive(Clone, Copy, Hash, Eq, PartialEq)]
457#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
458pub enum IntType {
459 I8,
460 I16,
461 I32,
462 I64,
463 Int,
464}
465
466impl Default for IntType {
467 fn default() -> Self {
468 Self::Int
469 }
470}
471
472impl NumberClass for IntType {
473 type Instance = Int;
474
475 fn cast(&self, n: Number) -> Int {
476 match self {
477 Self::I8 => Int::I8(n.cast_into()),
478 Self::I16 => Int::I16(n.cast_into()),
479 Self::Int | Self::I32 => Int::I32(n.cast_into()),
480 Self::I64 => Int::I64(n.cast_into()),
481 }
482 }
483
484 fn size(self) -> usize {
485 match self {
486 Self::I8 => 1,
487 Self::I16 => 2,
488 Self::I32 => 4,
489 Self::I64 => 8,
490 Self::Int => 8,
491 }
492 }
493
494 fn one(&self) -> Int {
495 match self {
496 Self::I8 => 1i8.into(),
497 Self::I16 => 1i16.into(),
498 Self::I32 => 1i32.into(),
499 Self::I64 => 1i64.into(),
500 Self::Int => 1i16.into(),
501 }
502 }
503
504 fn zero(&self) -> Int {
505 match self {
506 Self::I8 => 0i8.into(),
507 Self::I16 => 0i16.into(),
508 Self::I32 => 0i32.into(),
509 Self::I64 => 0i64.into(),
510 Self::Int => 0i16.into(),
511 }
512 }
513}
514
515impl Ord for IntType {
516 fn cmp(&self, other: &Self) -> Ordering {
517 match (self, other) {
518 (this, that) if this == that => Ordering::Equal,
519
520 (Self::Int, _) => Ordering::Greater,
521 (_, Self::Int) => Ordering::Less,
522
523 (Self::I64, _) => Ordering::Greater,
524 (_, Self::I64) => Ordering::Less,
525
526 (Self::I32, _) => Ordering::Greater,
527 (_, Self::I32) => Ordering::Less,
528
529 (Self::I16, _) => Ordering::Greater,
530 (_, Self::I16) => Ordering::Less,
531
532 (Self::I8, _) => Ordering::Less,
533 }
534 }
535}
536
537impl PartialOrd for IntType {
538 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
539 Some(self.cmp(other))
540 }
541}
542
543impl From<IntType> for NumberType {
544 fn from(it: IntType) -> NumberType {
545 NumberType::Int(it)
546 }
547}
548
549impl fmt::Debug for IntType {
550 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
551 fmt::Display::fmt(self, f)
552 }
553}
554
555impl fmt::Display for IntType {
556 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
557 match self {
558 Self::I8 => write!(f, "8-bit integer"),
559 Self::I16 => write!(f, "16-bit integer"),
560 Self::I32 => write!(f, "32-bit integer"),
561 Self::I64 => write!(f, "64-bit integer"),
562 Self::Int => write!(f, "integer"),
563 }
564 }
565}
566
567#[derive(Clone, Copy, Hash, Eq, PartialEq)]
569#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
570pub enum UIntType {
571 U8,
572 U16,
573 U32,
574 U64,
575 UInt,
576}
577
578impl Default for UIntType {
579 fn default() -> Self {
580 Self::UInt
581 }
582}
583
584impl NumberClass for UIntType {
585 type Instance = UInt;
586
587 fn cast(&self, n: Number) -> UInt {
588 match self {
589 Self::U8 => UInt::U8(n.cast_into()),
590 Self::U16 => UInt::U16(n.cast_into()),
591 Self::UInt | Self::U32 => UInt::U32(n.cast_into()),
592 Self::U64 => UInt::U64(n.cast_into()),
593 }
594 }
595
596 fn size(self) -> usize {
597 match self {
598 UIntType::U8 => 1,
599 UIntType::U16 => 2,
600 UIntType::U32 => 4,
601 UIntType::U64 => 8,
602 UIntType::UInt => 8,
603 }
604 }
605
606 fn one(&self) -> UInt {
607 match self {
608 Self::U8 => 1u8.into(),
609 Self::U16 => 1u16.into(),
610 Self::U32 => 1u32.into(),
611 Self::U64 => 1u64.into(),
612 Self::UInt => 1u8.into(),
613 }
614 }
615
616 fn zero(&self) -> UInt {
617 match self {
618 Self::U8 => 0u8.into(),
619 Self::U16 => 0u16.into(),
620 Self::U32 => 0u32.into(),
621 Self::U64 => 0u64.into(),
622 Self::UInt => 0u8.into(),
623 }
624 }
625}
626
627impl Ord for UIntType {
628 fn cmp(&self, other: &Self) -> Ordering {
629 match (self, other) {
630 (Self::U8, Self::U8) => Ordering::Equal,
631 (Self::U16, Self::U16) => Ordering::Equal,
632 (Self::U32, Self::U32) => Ordering::Equal,
633 (Self::U64, Self::U64) => Ordering::Equal,
634 (Self::UInt, Self::UInt) => Ordering::Equal,
635
636 (Self::UInt, _) => Ordering::Greater,
637 (_, Self::UInt) => Ordering::Less,
638
639 (Self::U64, _) => Ordering::Greater,
640 (_, Self::U64) => Ordering::Less,
641
642 (Self::U8, _) => Ordering::Less,
643 (_, Self::U8) => Ordering::Greater,
644
645 (Self::U32, Self::U16) => Ordering::Greater,
646 (Self::U16, Self::U32) => Ordering::Less,
647 }
648 }
649}
650
651impl PartialOrd for UIntType {
652 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
653 Some(self.cmp(other))
654 }
655}
656
657impl From<UIntType> for NumberType {
658 fn from(ut: UIntType) -> NumberType {
659 NumberType::UInt(ut)
660 }
661}
662
663impl fmt::Debug for UIntType {
664 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
665 fmt::Display::fmt(self, f)
666 }
667}
668
669impl fmt::Display for UIntType {
670 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
671 use UIntType::*;
672 match self {
673 U8 => write!(f, "8-bit unsigned"),
674 U16 => write!(f, "16-bit unsigned"),
675 U32 => write!(f, "32-bit unsigned"),
676 U64 => write!(f, "64-bit unsigned"),
677 UInt => write!(f, "uint"),
678 }
679 }
680}
681
682#[derive(Clone, Copy, Hash, Eq, PartialEq)]
684#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
685pub enum NumberType {
686 Bool,
687 Complex(ComplexType),
688 Float(FloatType),
689 Int(IntType),
690 UInt(UIntType),
691 Number,
692}
693
694impl NumberType {
695 pub fn uint64() -> Self {
696 NumberType::UInt(UIntType::U64)
697 }
698}
699
700impl Default for NumberType {
701 fn default() -> Self {
702 Self::Number
703 }
704}
705
706impl NumberClass for NumberType {
707 type Instance = Number;
708
709 fn is_complex(&self) -> bool {
710 match self {
711 Self::Bool => BooleanType.is_complex(),
712 Self::Complex(ct) => ct.is_complex(),
713 Self::Float(ft) => ft.is_complex(),
714 Self::Int(it) => it.is_complex(),
715 Self::UInt(ut) => ut.is_complex(),
716 Self::Number => false,
717 }
718 }
719
720 fn cast(&self, n: Number) -> Number {
721 match self {
722 Self::Bool => Number::Bool(n.cast_into()),
723 Self::Complex(ct) => Number::Complex(ct.cast(n)),
724 Self::Float(ft) => Number::Float(ft.cast(n)),
725 Self::Int(it) => Number::Int(it.cast(n)),
726 Self::UInt(ut) => Number::UInt(ut.cast(n)),
727 Self::Number => n,
728 }
729 }
730
731 fn size(self) -> usize {
732 use NumberType::*;
733 match self {
734 Bool => 1,
735 Complex(ct) => NumberClass::size(ct),
736 Float(ft) => NumberClass::size(ft),
737 Int(it) => NumberClass::size(it),
738 UInt(ut) => NumberClass::size(ut),
739
740 Number => NumberClass::size(ComplexType::C64),
742 }
743 }
744
745 fn one(&self) -> Number {
746 use NumberType::*;
747 match self {
748 Bool | Number => true.into(),
749 Complex(ct) => ct.one().into(),
750 Float(ft) => ft.one().into(),
751 Int(it) => it.one().into(),
752 UInt(ut) => ut.one().into(),
753 }
754 }
755
756 fn zero(&self) -> Number {
757 use NumberType::*;
758 match self {
759 Bool | Number => false.into(),
760 Complex(ct) => ct.zero().into(),
761 Float(ft) => ft.zero().into(),
762 Int(it) => it.zero().into(),
763 UInt(ut) => ut.zero().into(),
764 }
765 }
766}
767
768impl Ord for NumberType {
769 fn cmp(&self, other: &Self) -> Ordering {
770 match (self, other) {
771 (Self::Bool, Self::Bool) => Ordering::Equal,
772 (Self::Complex(l), Self::Complex(r)) => l.cmp(r),
773 (Self::Float(l), Self::Float(r)) => l.cmp(r),
774 (Self::Int(l), Self::Int(r)) => l.cmp(r),
775 (Self::UInt(l), Self::UInt(r)) => l.cmp(r),
776
777 (Self::Number, Self::Number) => Ordering::Equal,
778 (Self::Number, _) => Ordering::Greater,
779 (_, Self::Number) => Ordering::Less,
780
781 (Self::Bool, _) => Ordering::Less,
782 (_, Self::Bool) => Ordering::Greater,
783
784 (Self::Complex(_), _) => Ordering::Greater,
785 (_, Self::Complex(_)) => Ordering::Less,
786
787 (Self::UInt(_), Self::Int(_)) => Ordering::Less,
788 (Self::UInt(_), Self::Float(_)) => Ordering::Less,
789 (Self::Int(_), Self::UInt(_)) => Ordering::Greater,
790 (Self::Float(_), Self::UInt(_)) => Ordering::Greater,
791 (Self::Int(_), Self::Float(_)) => Ordering::Less,
792 (Self::Float(_), Self::Int(_)) => Ordering::Greater,
793 }
794 }
795}
796
797impl PartialOrd for NumberType {
798 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
799 Some(self.cmp(other))
800 }
801}
802
803impl fmt::Debug for NumberType {
804 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
805 fmt::Display::fmt(self, f)
806 }
807}
808
809impl fmt::Display for NumberType {
810 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
811 use NumberType::*;
812 match self {
813 Bool => fmt::Debug::fmt(&BooleanType, f),
814 Complex(ct) => fmt::Debug::fmt(ct, f),
815 Float(ft) => fmt::Debug::fmt(ft, f),
816 Int(it) => fmt::Debug::fmt(it, f),
817 UInt(ut) => fmt::Debug::fmt(ut, f),
818 Number => write!(f, "Number"),
819 }
820 }
821}