kalc_lib/types/
float.rs

1use super::{
2    Decimal, Integer, NewVal, Parse, ParseU, Prec, SinhCosh, Special, SpecialValues,
3    SpecialValuesDeci, Type, WithVal, WithValDeci,
4};
5use crate::macros::impls::{
6    float_impl, impl_neg, impl_new_val, impl_partial_ord, impl_rem, impl_self_ops,
7};
8use rug::ops::CompleteRound;
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11use std::ops::{Div, Mul};
12use std::{
13    cmp::{Ordering, PartialOrd},
14    fmt::{Display, Formatter},
15};
16#[derive(Clone, PartialEq)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub enum Float {
19    Rug(rug::Float),
20    Fastnum(Decimal),
21    F64(f64),
22    F32(f32),
23}
24
25impl Prec for Float {
26    fn prec(&self) -> u32 {
27        match self {
28            Self::Rug(a) => a.prec(),
29            Self::Fastnum(a) => a.prec(),
30            Self::F64(_) => 64,
31            Self::F32(_) => 32,
32        }
33    }
34    fn set_prec(&mut self, new_prec: u32) {
35        match self {
36            Self::Rug(a) => a.set_prec(new_prec),
37            Self::Fastnum(a) => a.set_prec(new_prec),
38            Self::F64(_) => {}
39            Self::F32(_) => {}
40        }
41    }
42}
43impl Float {
44    pub fn cmp0(&self) -> Option<Ordering> {
45        self.partial_cmp(&Float::new(self.ftype(), self.prec()))
46    }
47    pub fn is_zero(&self) -> bool {
48        match self {
49            Self::Rug(a) => a.is_zero(),
50            Self::Fastnum(a) => a.is_zero(),
51            Self::F64(a) => a == &0.0,
52            Self::F32(a) => a == &0.0,
53        }
54    }
55    pub fn ftype(&self) -> Type {
56        match self {
57            Self::Rug(_) => Type::Rug,
58            Self::Fastnum(_) => Type::Fastnum,
59            Self::F64(_) => Type::F64,
60            Self::F32(_) => Type::F32,
61        }
62    }
63    pub fn to_f64(&self) -> f64 {
64        match self {
65            Float::Rug(a) => a.to_f64(),
66            Float::Fastnum(a) => a.to_f64(),
67            Float::F64(a) => *a,
68            Float::F32(a) => *a as f64,
69        }
70    }
71    pub fn to_string_radix(self, base: i32, num_digits: Option<usize>) -> String {
72        match self {
73            Self::Rug(a) => a.to_string_radix(base, num_digits),
74            Self::Fastnum(a) => a.to_string_radix(base, num_digits),
75            Self::F64(a) => a.to_string(),
76            Self::F32(a) => a.to_string(),
77        }
78    }
79}
80impl ParseU<&str> for Float {
81    fn parse(t: Type, prec: u32, s: &str) -> Option<Self> {
82        match t {
83            Type::Rug => rug::Float::parse(s)
84                .ok()
85                .map(|a| Float::Rug(a.complete(prec))),
86            Type::Fastnum => Decimal::parse(prec, s).map(Float::Fastnum),
87            Type::F64 => s.parse().ok().map(Float::F64),
88            Type::F32 => s.parse().ok().map(Float::F32),
89        }
90    }
91    fn parse_radix(t: Type, prec: u32, s: &str, base: i32) -> Option<Self> {
92        match t {
93            Type::Rug => rug::Float::parse_radix(s, base)
94                .ok()
95                .map(|a| Float::Rug(a.complete(prec))),
96            Type::Fastnum => Decimal::parse_radix(prec, s, base).map(Float::Fastnum),
97            Type::F64 => s.parse().ok().map(Float::F64),
98            Type::F32 => s.parse().ok().map(Float::F32),
99        }
100    }
101}
102impl Mul<Integer> for Float {
103    type Output = Self;
104    fn mul(self, rhs: Integer) -> Self::Output {
105        match (self, rhs) {
106            (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a * b),
107            (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a * b),
108            (Float::F64(a), Integer::F64(b)) => Float::F64(a * b as f64),
109            (Float::F32(a), Integer::F32(b)) => Float::F32(a * b as f32),
110            _ => unreachable!(),
111        }
112    }
113}
114impl Div<Integer> for Float {
115    type Output = Self;
116    fn div(self, rhs: Integer) -> Self::Output {
117        match (self, rhs) {
118            (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a / b),
119            (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a / b),
120            (Float::F64(a), Integer::F64(b)) => Float::F64(a / b as f64),
121            (Float::F32(a), Integer::F32(b)) => Float::F32(a / b as f32),
122            _ => unreachable!(),
123        }
124    }
125}
126impl Mul<Float> for Integer {
127    type Output = Float;
128    fn mul(self, rhs: Float) -> Self::Output {
129        match (rhs, self) {
130            (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a * b),
131            (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a * b),
132            (Float::F64(a), Integer::F64(b)) => Float::F64(a * b as f64),
133            (Float::F32(a), Integer::F32(b)) => Float::F32(a * b as f32),
134            _ => unreachable!(),
135        }
136    }
137}
138impl Div<Float> for Integer {
139    type Output = Float;
140    fn div(self, rhs: Float) -> Self::Output {
141        match (rhs, self) {
142            (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a / b),
143            (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a / b),
144            (Float::F64(a), Integer::F64(b)) => Float::F64(a / b as f64),
145            (Float::F32(a), Integer::F32(b)) => Float::F32(a / b as f32),
146            _ => unreachable!(),
147        }
148    }
149}
150impl SpecialValues for Float {
151    fn pi(t: Type, prec: u32) -> Self {
152        match t {
153            Type::Rug => Self::Rug(rug::Float::with_val(prec, rug::float::Constant::Pi)),
154            Type::Fastnum => Self::Fastnum(Decimal::pi(prec)),
155            Type::F64 => Self::F64(f64::pi(prec)),
156            Type::F32 => Self::F32(f32::pi(prec)),
157        }
158    }
159    fn nan(t: Type, prec: u32) -> Self {
160        match t {
161            Type::Rug => Self::Rug(rug::Float::with_val(prec, rug::float::Special::Nan)),
162            Type::Fastnum => Self::Fastnum(Decimal::nan(prec)),
163            Type::F64 => Self::F64(f64::nan(prec)),
164            Type::F32 => Self::F32(f32::nan(prec)),
165        }
166    }
167    fn inf(t: Type, prec: u32) -> Self {
168        match t {
169            Type::Rug => Self::Rug(rug::Float::with_val(prec, rug::float::Special::Infinity)),
170            Type::Fastnum => Self::Fastnum(Decimal::inf(prec)),
171            Type::F64 => Self::F64(f64::inf(prec)),
172            Type::F32 => Self::F32(f32::inf(prec)),
173        }
174    }
175}
176
177impl WithVal<Special> for Float {
178    fn with_val(obj: Type, prec: u32, val: Special) -> Self {
179        match val {
180            Special::Pi => Float::pi(obj, prec),
181            Special::Nan => Float::nan(obj, prec),
182            Special::Infinity => Float::inf(obj, prec),
183        }
184    }
185}
186
187impl Display for Float {
188    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
189        match self {
190            Self::Rug(a) => a.fmt(f),
191            Self::Fastnum(a) => a.fmt(f),
192            Self::F32(a) => a.fmt(f),
193            Self::F64(a) => a.fmt(f),
194        }
195    }
196}
197
198impl Float {
199    pub fn sin_cos(self) -> (Self, Self) {
200        match self {
201            Self::Rug(a) => {
202                let p = a.prec();
203                let (s, c) = a.sin_cos(rug::Float::new(p));
204                (Self::Rug(s), Self::Rug(c))
205            }
206            Self::Fastnum(a) => {
207                let (s, c) = a.sin_cos();
208                (Self::Fastnum(s), Self::Fastnum(c))
209            }
210            Self::F64(a) => {
211                let (s, c) = a.sin_cos();
212                (Self::F64(s), Self::F64(c))
213            }
214            Self::F32(a) => {
215                let (s, c) = a.sin_cos();
216                (Self::F32(s), Self::F32(c))
217            }
218        }
219    }
220    pub fn sinh_cosh(self) -> (Self, Self) {
221        match self {
222            Self::Rug(a) => {
223                let p = a.prec();
224                let (s, c) = a.sinh_cosh(rug::Float::new(p));
225                (Self::Rug(s), Self::Rug(c))
226            }
227            Self::Fastnum(a) => {
228                let (s, c) = a.sinh_cosh();
229                (Self::Fastnum(s), Self::Fastnum(c))
230            }
231            Self::F64(a) => {
232                let (s, c) = a.sinh_cosh();
233                (Self::F64(s), Self::F64(c))
234            }
235            Self::F32(a) => {
236                let (s, c) = a.sinh_cosh();
237                (Self::F32(s), Self::F32(c))
238            }
239        }
240    }
241    pub fn atan2(self, other: Self) -> Self {
242        match (self, other) {
243            (Self::Rug(a), Self::Rug(b)) => Self::Rug(a.atan2(&b)),
244            (Self::Fastnum(a), Self::Fastnum(b)) => Self::Fastnum(a.atan2(b)),
245            (Self::F64(a), Self::F64(b)) => Self::F64(a.atan2(b)),
246            (Self::F32(a), Self::F32(b)) => Self::F32(a.atan2(b)),
247            _ => unreachable!(),
248        }
249    }
250    pub fn hypot(self, other: Self) -> Self {
251        match (self, other) {
252            (Self::Rug(a), Self::Rug(b)) => Self::Rug(a.hypot(&b)),
253            (Self::Fastnum(a), Self::Fastnum(b)) => Self::Fastnum(a.hypot(b)),
254            (Self::F64(a), Self::F64(b)) => Self::F64(a.hypot(b)),
255            (Self::F32(a), Self::F32(b)) => Self::F32(a.hypot(b)),
256            _ => unreachable!(),
257        }
258    }
259    pub fn to_integer(self) -> Integer {
260        match self {
261            Float::Rug(a) => Integer::Rug(a.to_integer().unwrap()),
262            Float::Fastnum(a) => Integer::Fastnum(a.to_integer()),
263            Float::F64(a) => Integer::F64(a as i128),
264            Float::F32(a) => Integer::F32(a as i128),
265        }
266    }
267    pub fn gamma(self) -> Self {
268        match self {
269            Float::Rug(a) => Self::Rug(a.gamma()),
270            Float::Fastnum(a) => Self::Fastnum(a),
271            Float::F64(a) => Self::F64(a),
272            Float::F32(a) => Self::F32(a),
273        }
274    }
275}
276
277impl PartialEq<f64> for Float {
278    fn eq(&self, other: &f64) -> bool {
279        match self {
280            Float::Rug(a) => a == other,
281            Float::Fastnum(a) => a == other,
282            Float::F64(a) => a == other,
283            Float::F32(a) => *a == *other as f32,
284        }
285    }
286}
287impl PartialEq<i32> for Float {
288    fn eq(&self, other: &i32) -> bool {
289        match self {
290            Float::Rug(a) => a == other,
291            Float::Fastnum(a) => a == other,
292            Float::F64(a) => *a == *other as f64,
293            Float::F32(a) => *a == *other as f32,
294        }
295    }
296}
297impl PartialOrd<i32> for Float {
298    fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
299        match self {
300            Float::Rug(a) => a.partial_cmp(other),
301            Float::Fastnum(a) => a.to_integer().partial_cmp(&fastnum::I512::from(*other)),
302            Float::F64(a) => a.partial_cmp(&(*other as f64)),
303            Float::F32(a) => a.partial_cmp(&(*other as f32)),
304        }
305    }
306}
307
308impl_new_val!(
309    Float,
310    (Rug, rug::Float::with_val),
311    (Fastnum, Decimal::with_val),
312    (F64, |_, x| x),
313    (F32, |_, x| x as f32)
314);
315impl_rem!(
316    Float,
317    (Rug, |x| x),
318    (Fastnum, |x| x),
319    (F64, |x| x as f64),
320    (F32, |x| x as f32)
321);
322float_impl!(Float, Rug, Fastnum, F64, F32);
323impl_partial_ord!(
324    Float,
325    (Rug, |x: &rug::Float| x.to_f64()),
326    (Fastnum, |x: &Decimal| x.to_f64()),
327    (F64, |x: &f64| *x),
328    (F32, |x: &f32| *x as f64)
329);
330impl_neg!(Float, Rug, Fastnum, F64, F32);
331impl_self_ops!(
332    Float,
333    (Rug, |x| x),
334    (Fastnum, |x| x),
335    (F64, |x| x),
336    (F32, |x| x)
337);