1use std::cmp::Ordering;
2use std::fmt;
3use std::iter::{Product, Sum};
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
5
6use safecast::{CastFrom, CastInto};
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 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, Default, Hash, Eq, PartialEq)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210pub enum ComplexType {
211 C32,
212 C64,
213 #[default]
214 Complex,
215}
216
217impl NumberClass for ComplexType {
218 type Instance = Complex;
219
220 fn cast(&self, n: Number) -> Complex {
221 match self {
222 Self::C64 => Complex::C64(n.cast_into()),
223 _ => Complex::C32(n.cast_into()),
224 }
225 }
226
227 fn is_complex(&self) -> bool {
228 true
229 }
230
231 fn size(self) -> usize {
232 match self {
233 Self::C32 => 8,
234 Self::C64 => 16,
235 Self::Complex => 16,
236 }
237 }
238
239 fn one(&self) -> Complex {
240 match self {
241 Self::C32 => _Complex::<f32>::new(1f32, 0f32).into(),
242 Self::C64 => _Complex::<f64>::new(1f64, 0f64).into(),
243 Self::Complex => _Complex::<f32>::new(1f32, 0f32).into(),
244 }
245 }
246
247 fn zero(&self) -> Complex {
248 match self {
249 Self::C32 => _Complex::<f32>::new(0f32, 0f32).into(),
250 Self::C64 => _Complex::<f64>::new(0f64, 0f64).into(),
251 Self::Complex => _Complex::<f32>::new(0f32, 0f32).into(),
252 }
253 }
254}
255
256impl Ord for ComplexType {
257 fn cmp(&self, other: &Self) -> Ordering {
258 match (self, other) {
259 (Self::C32, Self::C32) => Ordering::Equal,
260 (Self::C64, Self::C64) => Ordering::Equal,
261 (Self::Complex, Self::Complex) => Ordering::Equal,
262
263 (Self::Complex, _) => Ordering::Greater,
264 (_, Self::Complex) => Ordering::Less,
265
266 (Self::C64, Self::C32) => Ordering::Greater,
267 (Self::C32, Self::C64) => Ordering::Less,
268 }
269 }
270}
271
272impl PartialOrd for ComplexType {
273 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
274 Some(self.cmp(other))
275 }
276}
277
278impl From<ComplexType> for NumberType {
279 fn from(ct: ComplexType) -> NumberType {
280 Self::Complex(ct)
281 }
282}
283
284impl fmt::Debug for ComplexType {
285 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
286 fmt::Display::fmt(self, f)
287 }
288}
289
290impl fmt::Display for ComplexType {
291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292 match self {
293 Self::C32 => write!(f, "32-bit complex number"),
294 Self::C64 => write!(f, "64-bit complex number"),
295 Self::Complex => write!(f, "complex number"),
296 }
297 }
298}
299
300#[derive(Clone, Copy, Default, Hash, Eq, PartialEq)]
302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
303pub struct BooleanType;
304
305impl NumberClass for BooleanType {
306 type Instance = Boolean;
307
308 fn cast(&self, n: Number) -> Boolean {
309 n.cast_into()
310 }
311
312 fn size(self) -> usize {
313 1
314 }
315
316 fn one(&self) -> Boolean {
317 true.into()
318 }
319
320 fn zero(&self) -> Boolean {
321 false.into()
322 }
323}
324
325impl Ord for BooleanType {
326 fn cmp(&self, _other: &Self) -> Ordering {
327 Ordering::Equal
328 }
329}
330
331impl PartialOrd for BooleanType {
332 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
333 Some(self.cmp(other))
334 }
335}
336
337impl From<BooleanType> for NumberType {
338 fn from(_bt: BooleanType) -> NumberType {
339 NumberType::Bool
340 }
341}
342
343impl fmt::Debug for BooleanType {
344 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
345 fmt::Display::fmt(self, f)
346 }
347}
348
349impl fmt::Display for BooleanType {
350 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
351 write!(f, "Boolean")
352 }
353}
354
355#[derive(Clone, Copy, Default, Hash, Eq, PartialEq)]
357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
358pub enum FloatType {
359 F32,
360 F64,
361 #[default]
362 Float,
363}
364
365impl NumberClass for FloatType {
366 type Instance = Float;
367
368 fn cast(&self, n: Number) -> Float {
369 match self {
370 Self::F64 => Float::F64(n.cast_into()),
371 _ => Float::F32(n.cast_into()),
372 }
373 }
374
375 fn size(self) -> usize {
376 match self {
377 Self::F32 => 4,
378 Self::F64 => 8,
379 Self::Float => 8,
380 }
381 }
382
383 fn one(&self) -> Float {
384 match self {
385 Self::F32 => 1f32.into(),
386 Self::F64 => 1f64.into(),
387 Self::Float => 1f32.into(),
388 }
389 }
390
391 fn zero(&self) -> Float {
392 match self {
393 Self::F32 => 0f32.into(),
394 Self::F64 => 0f64.into(),
395 Self::Float => 0f32.into(),
396 }
397 }
398}
399
400impl Ord for FloatType {
401 fn cmp(&self, other: &Self) -> Ordering {
402 match (self, other) {
403 (Self::F32, Self::F32) => Ordering::Equal,
404 (Self::F64, Self::F64) => Ordering::Equal,
405 (Self::Float, Self::Float) => Ordering::Equal,
406
407 (Self::Float, _) => Ordering::Greater,
408 (_, Self::Float) => Ordering::Less,
409
410 (Self::F64, Self::F32) => Ordering::Greater,
411 (Self::F32, Self::F64) => Ordering::Less,
412 }
413 }
414}
415
416impl PartialOrd for FloatType {
417 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
418 Some(self.cmp(other))
419 }
420}
421
422impl From<FloatType> for NumberType {
423 fn from(ft: FloatType) -> NumberType {
424 NumberType::Float(ft)
425 }
426}
427
428impl fmt::Debug for FloatType {
429 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430 fmt::Display::fmt(self, f)
431 }
432}
433
434impl fmt::Display for FloatType {
435 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
436 use FloatType::*;
437 match self {
438 F32 => write!(f, "32-bit float"),
439 F64 => write!(f, "64-bit float"),
440 Float => write!(f, "float"),
441 }
442 }
443}
444
445#[derive(Clone, Copy, Default, Hash, Eq, PartialEq)]
447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
448pub enum IntType {
449 I8,
450 I16,
451 I32,
452 I64,
453 #[default]
454 Int,
455}
456
457impl NumberClass for IntType {
458 type Instance = Int;
459
460 fn cast(&self, n: Number) -> Int {
461 match self {
462 Self::I8 => Int::I8(n.cast_into()),
463 Self::I16 => Int::I16(n.cast_into()),
464 Self::Int | Self::I32 => Int::I32(n.cast_into()),
465 Self::I64 => Int::I64(n.cast_into()),
466 }
467 }
468
469 fn size(self) -> usize {
470 match self {
471 Self::I8 => 1,
472 Self::I16 => 2,
473 Self::I32 => 4,
474 Self::I64 => 8,
475 Self::Int => 8,
476 }
477 }
478
479 fn one(&self) -> Int {
480 match self {
481 Self::I8 => 1i8.into(),
482 Self::I16 => 1i16.into(),
483 Self::I32 => 1i32.into(),
484 Self::I64 => 1i64.into(),
485 Self::Int => 1i16.into(),
486 }
487 }
488
489 fn zero(&self) -> Int {
490 match self {
491 Self::I8 => 0i8.into(),
492 Self::I16 => 0i16.into(),
493 Self::I32 => 0i32.into(),
494 Self::I64 => 0i64.into(),
495 Self::Int => 0i16.into(),
496 }
497 }
498}
499
500impl Ord for IntType {
501 fn cmp(&self, other: &Self) -> Ordering {
502 match (self, other) {
503 (this, that) if this == that => Ordering::Equal,
504
505 (Self::Int, _) => Ordering::Greater,
506 (_, Self::Int) => Ordering::Less,
507
508 (Self::I64, _) => Ordering::Greater,
509 (_, Self::I64) => Ordering::Less,
510
511 (Self::I32, _) => Ordering::Greater,
512 (_, Self::I32) => Ordering::Less,
513
514 (Self::I16, _) => Ordering::Greater,
515 (_, Self::I16) => Ordering::Less,
516
517 (Self::I8, _) => Ordering::Less,
518 }
519 }
520}
521
522impl PartialOrd for IntType {
523 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
524 Some(self.cmp(other))
525 }
526}
527
528impl From<IntType> for NumberType {
529 fn from(it: IntType) -> NumberType {
530 NumberType::Int(it)
531 }
532}
533
534impl fmt::Debug for IntType {
535 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
536 fmt::Display::fmt(self, f)
537 }
538}
539
540impl fmt::Display for IntType {
541 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
542 match self {
543 Self::I8 => write!(f, "8-bit integer"),
544 Self::I16 => write!(f, "16-bit integer"),
545 Self::I32 => write!(f, "32-bit integer"),
546 Self::I64 => write!(f, "64-bit integer"),
547 Self::Int => write!(f, "integer"),
548 }
549 }
550}
551
552#[derive(Clone, Copy, Default, Hash, Eq, PartialEq)]
554#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
555pub enum UIntType {
556 U8,
557 U16,
558 U32,
559 U64,
560 #[default]
561 UInt,
562}
563
564impl NumberClass for UIntType {
565 type Instance = UInt;
566
567 fn cast(&self, n: Number) -> UInt {
568 match self {
569 Self::U8 => UInt::U8(n.cast_into()),
570 Self::U16 => UInt::U16(n.cast_into()),
571 Self::UInt | Self::U32 => UInt::U32(n.cast_into()),
572 Self::U64 => UInt::U64(n.cast_into()),
573 }
574 }
575
576 fn size(self) -> usize {
577 match self {
578 UIntType::U8 => 1,
579 UIntType::U16 => 2,
580 UIntType::U32 => 4,
581 UIntType::U64 => 8,
582 UIntType::UInt => 8,
583 }
584 }
585
586 fn one(&self) -> UInt {
587 match self {
588 Self::U8 => 1u8.into(),
589 Self::U16 => 1u16.into(),
590 Self::U32 => 1u32.into(),
591 Self::U64 => 1u64.into(),
592 Self::UInt => 1u8.into(),
593 }
594 }
595
596 fn zero(&self) -> UInt {
597 match self {
598 Self::U8 => 0u8.into(),
599 Self::U16 => 0u16.into(),
600 Self::U32 => 0u32.into(),
601 Self::U64 => 0u64.into(),
602 Self::UInt => 0u8.into(),
603 }
604 }
605}
606
607impl Ord for UIntType {
608 fn cmp(&self, other: &Self) -> Ordering {
609 match (self, other) {
610 (Self::U8, Self::U8) => Ordering::Equal,
611 (Self::U16, Self::U16) => Ordering::Equal,
612 (Self::U32, Self::U32) => Ordering::Equal,
613 (Self::U64, Self::U64) => Ordering::Equal,
614 (Self::UInt, Self::UInt) => Ordering::Equal,
615
616 (Self::UInt, _) => Ordering::Greater,
617 (_, Self::UInt) => Ordering::Less,
618
619 (Self::U64, _) => Ordering::Greater,
620 (_, Self::U64) => Ordering::Less,
621
622 (Self::U8, _) => Ordering::Less,
623 (_, Self::U8) => Ordering::Greater,
624
625 (Self::U32, Self::U16) => Ordering::Greater,
626 (Self::U16, Self::U32) => Ordering::Less,
627 }
628 }
629}
630
631impl PartialOrd for UIntType {
632 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
633 Some(self.cmp(other))
634 }
635}
636
637impl From<UIntType> for NumberType {
638 fn from(ut: UIntType) -> NumberType {
639 NumberType::UInt(ut)
640 }
641}
642
643impl fmt::Debug for UIntType {
644 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
645 fmt::Display::fmt(self, f)
646 }
647}
648
649impl fmt::Display for UIntType {
650 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
651 use UIntType::*;
652 match self {
653 U8 => write!(f, "8-bit unsigned"),
654 U16 => write!(f, "16-bit unsigned"),
655 U32 => write!(f, "32-bit unsigned"),
656 U64 => write!(f, "64-bit unsigned"),
657 UInt => write!(f, "uint"),
658 }
659 }
660}
661
662#[derive(Clone, Copy, Default, Hash, Eq, PartialEq)]
664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
665pub enum NumberType {
666 Bool,
667 Complex(ComplexType),
668 Float(FloatType),
669 Int(IntType),
670 UInt(UIntType),
671 #[default]
672 Number,
673}
674
675impl NumberType {
676 pub fn uint64() -> Self {
677 NumberType::UInt(UIntType::U64)
678 }
679}
680
681impl NumberClass for NumberType {
682 type Instance = Number;
683
684 fn is_complex(&self) -> bool {
685 match self {
686 Self::Bool => BooleanType.is_complex(),
687 Self::Complex(ct) => ct.is_complex(),
688 Self::Float(ft) => ft.is_complex(),
689 Self::Int(it) => it.is_complex(),
690 Self::UInt(ut) => ut.is_complex(),
691 Self::Number => false,
692 }
693 }
694
695 fn cast(&self, n: Number) -> Number {
696 match self {
697 Self::Bool => Number::Bool(n.cast_into()),
698 Self::Complex(ct) => Number::Complex(ct.cast(n)),
699 Self::Float(ft) => Number::Float(ft.cast(n)),
700 Self::Int(it) => Number::Int(it.cast(n)),
701 Self::UInt(ut) => Number::UInt(ut.cast(n)),
702 Self::Number => n,
703 }
704 }
705
706 fn size(self) -> usize {
707 use NumberType::*;
708 match self {
709 Bool => 1,
710 Complex(ct) => NumberClass::size(ct),
711 Float(ft) => NumberClass::size(ft),
712 Int(it) => NumberClass::size(it),
713 UInt(ut) => NumberClass::size(ut),
714
715 Number => NumberClass::size(ComplexType::C64),
717 }
718 }
719
720 fn one(&self) -> Number {
721 use NumberType::*;
722 match self {
723 Bool | Number => true.into(),
724 Complex(ct) => ct.one().into(),
725 Float(ft) => ft.one().into(),
726 Int(it) => it.one().into(),
727 UInt(ut) => ut.one().into(),
728 }
729 }
730
731 fn zero(&self) -> Number {
732 use NumberType::*;
733 match self {
734 Bool | Number => false.into(),
735 Complex(ct) => ct.zero().into(),
736 Float(ft) => ft.zero().into(),
737 Int(it) => it.zero().into(),
738 UInt(ut) => ut.zero().into(),
739 }
740 }
741}
742
743impl Ord for NumberType {
744 fn cmp(&self, other: &Self) -> Ordering {
745 match (self, other) {
746 (Self::Bool, Self::Bool) => Ordering::Equal,
747 (Self::Complex(l), Self::Complex(r)) => l.cmp(r),
748 (Self::Float(l), Self::Float(r)) => l.cmp(r),
749 (Self::Int(l), Self::Int(r)) => l.cmp(r),
750 (Self::UInt(l), Self::UInt(r)) => l.cmp(r),
751
752 (Self::Number, Self::Number) => Ordering::Equal,
753 (Self::Number, _) => Ordering::Greater,
754 (_, Self::Number) => Ordering::Less,
755
756 (Self::Bool, _) => Ordering::Less,
757 (_, Self::Bool) => Ordering::Greater,
758
759 (Self::Complex(_), _) => Ordering::Greater,
760 (_, Self::Complex(_)) => Ordering::Less,
761
762 (Self::UInt(_), Self::Int(_)) => Ordering::Less,
763 (Self::UInt(_), Self::Float(_)) => Ordering::Less,
764 (Self::Int(_), Self::UInt(_)) => Ordering::Greater,
765 (Self::Float(_), Self::UInt(_)) => Ordering::Greater,
766 (Self::Int(_), Self::Float(_)) => Ordering::Less,
767 (Self::Float(_), Self::Int(_)) => Ordering::Greater,
768 }
769 }
770}
771
772impl PartialOrd for NumberType {
773 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
774 Some(self.cmp(other))
775 }
776}
777
778impl fmt::Debug for NumberType {
779 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
780 fmt::Display::fmt(self, f)
781 }
782}
783
784impl fmt::Display for NumberType {
785 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
786 use NumberType::*;
787 match self {
788 Bool => fmt::Debug::fmt(&BooleanType, f),
789 Complex(ct) => fmt::Debug::fmt(ct, f),
790 Float(ft) => fmt::Debug::fmt(ft, f),
791 Int(it) => fmt::Debug::fmt(it, f),
792 UInt(ut) => fmt::Debug::fmt(ut, f),
793 Number => write!(f, "Number"),
794 }
795 }
796}