1use num_bigint::{BigInt, BigUint};
2use num_complex::Complex64;
3use num_irrational::{BigQuadratic, Quadratic64};
4use num_rational::{BigRational, Rational64};
5use num_traits::{FromPrimitive, ToPrimitive};
6use std::convert::TryInto;
7
8#[derive(Clone)]
10pub enum Subject {
11 Infinity(bool),
15 Int(i64),
17 BInt(BigInt),
19 Real(f64),
21 #[cfg(feature = "bigdecimal")]
23 BReal(bigdecimal::BigDecimal),
24 #[cfg(feature = "rug")]
25 BReal(rug::Real),
26 Rational(Rational64),
28 BRational(BigRational),
30 Complex(Complex64),
32 #[cfg(feature = "rug")]
34 BComplex(rug::Complex),
35 Quad(Quadratic64),
37 BQuad(BigQuadratic),
39 QuadInt(), BQuadInt(),
43}
44
45impl From<i8> for Subject {
48 fn from(v: i8) -> Self {
49 Subject::Int(v as i64)
50 }
51}
52impl From<i64> for Subject {
53 fn from(v: i64) -> Self {
54 Subject::Int(v)
55 }
56}
57impl From<u64> for Subject {
58 fn from(v: u64) -> Self {
59 match v.try_into() {
60 Ok(u) => Subject::Int(u),
61 Err(_) => Subject::BInt(BigInt::from_u64(v).unwrap()),
62 }
63 }
64}
65impl From<usize> for Subject {
66 fn from(v: usize) -> Self {
67 match v.try_into() {
68 Ok(u) => Subject::Int(u),
69 Err(_) => Subject::BInt(BigInt::from_usize(v).unwrap()),
70 }
71 }
72}
73impl From<f64> for Subject {
74 fn from(v: f64) -> Self {
75 if v.is_nan() {
76 panic!("nan is not accepted as a suan::Subject")
77 } else if v.is_infinite() {
78 Subject::Infinity(v.is_sign_positive())
79 } else {
80 Subject::Real(v)
81 }
82 }
83}
84#[cfg(feature = "bigdecimal")]
85impl From<bigdecimal::BigDecimal> for Subject {
86 fn from(v: bigdecimal::BigDecimal) -> Self {
87 Subject::BReal(v)
90 }
91}
92impl From<BigInt> for Subject {
93 fn from(v: BigInt) -> Self {
94 match v.to_i64() {
95 Some(s) => Subject::Int(s),
96 None => Subject::BInt(v),
97 }
98 }
99}
100impl From<BigUint> for Subject {
101 fn from(v: BigUint) -> Self {
102 match v.to_i64() {
103 Some(s) => Subject::Int(s),
104 None => Subject::BInt(BigInt::from(v)),
105 }
106 }
107}
108impl From<Rational64> for Subject {
109 fn from(v: Rational64) -> Self {
110 if v.is_integer() {
111 Subject::Int(v.to_integer())
112 } else {
113 Subject::Rational(v)
114 }
115 }
116}
117impl From<BigRational> for Subject {
118 fn from(v: BigRational) -> Self {
119 if v.is_integer() {
120 v.to_integer().into()
121 } else {
122 match (v.numer().to_i64(), v.denom().to_i64()) {
123 (Some(n), Some(d)) => Subject::Rational(Rational64::new(n, d)),
124 _ => Subject::BRational(v),
125 }
126 }
127 }
128}
129impl From<Quadratic64> for Subject {
130 fn from(v: Quadratic64) -> Self {
131 if v.is_integer() {
132 Subject::Int(v.to_integer().value())
133 } else if v.is_rational() {
134 Subject::Rational(v.to_rational().value())
135 } else {
136 Subject::Quad(v)
137 }
138 }
139}
140impl From<BigQuadratic> for Subject {
141 fn from(v: BigQuadratic) -> Self {
142 let (ra, rb, rc, rr) = v.parts();
143 match (ra.to_i64(), rb.to_i64(), rc.to_i64(), rr.to_i64()) {
144 (Some(sa), Some(sb), Some(sc), Some(sr)) => {
145 Subject::Quad(Quadratic64::new(sa, sb, sc, sr))
146 }
147 _ => Subject::BQuad(v),
148 }
149 }
150}
151impl From<Complex64> for Subject {
152 fn from(v: Complex64) -> Self {
153 if v.re.is_nan() || v.im.is_nan() {
154 panic!("nan is not accepted as a suan::Subject")
155 } else if v.re.is_infinite() {
156 Subject::Infinity(v.re.is_sign_positive())
158 } else if v.im.is_infinite() {
159 Subject::Infinity(v.im.is_sign_positive())
161 } else {
162 Subject::Complex(v)
163 }
164 }
165}