kalc_lib/types/
decimal.rs

1use super::{NewDeciVal, Parse, Prec, SinhCosh, SpecialValuesDeci};
2use crate::macros::impls::{
3    dec_impl, impl_neg, impl_new_val_deci, impl_partial_ord, impl_rem, impl_self_ops,
4};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use std::cmp::Ordering;
8use std::fmt::{Display, Formatter};
9use std::ops::{Div, Mul};
10#[derive(Copy, Clone, PartialEq)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub enum Decimal {
13    D512(fastnum::D512),
14    D256(fastnum::D256),
15}
16
17impl Prec for Decimal {
18    fn prec(&self) -> u32 {
19        match self {
20            Self::D512(_) => 512,
21            Self::D256(_) => 256,
22        }
23    }
24    fn set_prec(&mut self, _new_prec: u32) {
25        match self {
26            Self::D512(_) => todo!(),
27            Self::D256(_) => todo!(),
28        }
29    }
30}
31
32impl Decimal {
33    pub fn is_zero(&self) -> bool {
34        match self {
35            Self::D512(a) => a.is_zero(),
36            Self::D256(a) => a.is_zero(),
37        }
38    }
39    pub fn to_integer(self) -> fastnum::I512 {
40        match self {
41            Self::D512(_) => todo!(),
42            Self::D256(_) => todo!(),
43        }
44    }
45    pub fn to_f64(&self) -> f64 {
46        match self {
47            Self::D512(_) => todo!(),
48            Self::D256(_) => todo!(),
49        }
50    }
51    pub fn to_string_radix(self, _base: i32, _num_digits: Option<usize>) -> String {
52        match self {
53            Self::D512(a) => a.to_string(),
54            Self::D256(a) => a.to_string(),
55        }
56    }
57}
58
59impl Mul<fastnum::I512> for Decimal {
60    type Output = Self;
61    fn mul(self, rhs: fastnum::I512) -> Self::Output {
62        match self {
63            Decimal::D512(a) => Decimal::D512(
64                a * fastnum::D512::from_str(&rhs.to_string(), fastnum::decimal::Context::default())
65                    .unwrap_or_default(),
66            ),
67            Decimal::D256(a) => Decimal::D256(
68                a * fastnum::D256::from_str(&rhs.to_string(), fastnum::decimal::Context::default())
69                    .unwrap_or_default(),
70            ),
71        }
72    }
73}
74
75impl Div<fastnum::I512> for Decimal {
76    type Output = Self;
77    fn div(self, rhs: fastnum::I512) -> Self::Output {
78        match self {
79            Decimal::D512(a) => Decimal::D512(
80                a / fastnum::D512::from_str(&rhs.to_string(), fastnum::decimal::Context::default())
81                    .unwrap_or_default(),
82            ),
83            Decimal::D256(a) => Decimal::D256(
84                a / fastnum::D256::from_str(&rhs.to_string(), fastnum::decimal::Context::default())
85                    .unwrap_or_default(),
86            ),
87        }
88    }
89}
90
91impl Parse<&str> for Decimal {
92    fn parse(prec: u32, s: &str) -> Option<Self> {
93        match prec.next_power_of_two() {
94            512 => fastnum::D512::from_str(s, fastnum::decimal::Context::default())
95                .ok()
96                .map(Self::D512),
97            256 => fastnum::D256::from_str(s, fastnum::decimal::Context::default())
98                .ok()
99                .map(Self::D256),
100            _ => unreachable!(),
101        }
102    }
103    fn parse_radix(prec: u32, s: &str, _base: i32) -> Option<Self> {
104        match prec.next_power_of_two() {
105            512 => fastnum::D512::from_str(s, fastnum::decimal::Context::default())
106                .ok()
107                .map(Self::D512),
108            256 => fastnum::D256::from_str(s, fastnum::decimal::Context::default())
109                .ok()
110                .map(Self::D256),
111            _ => unreachable!(),
112        }
113    }
114}
115
116impl SpecialValuesDeci for Decimal {
117    fn pi(prec: u32) -> Self {
118        match prec.next_power_of_two() {
119            512 => Self::D512(fastnum::D512::PI),
120            256 => Self::D256(fastnum::D256::PI),
121            _ => unreachable!(),
122        }
123    }
124    fn nan(prec: u32) -> Self {
125        match prec.next_power_of_two() {
126            512 => Self::D512(fastnum::D512::NAN),
127            256 => Self::D256(fastnum::D256::NAN),
128            _ => unreachable!(),
129        }
130    }
131    fn inf(prec: u32) -> Self {
132        match prec.next_power_of_two() {
133            512 => Self::D512(fastnum::D512::INFINITY),
134            256 => Self::D256(fastnum::D256::INFINITY),
135            _ => unreachable!(),
136        }
137    }
138}
139
140impl Display for Decimal {
141    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
142        match self {
143            Self::D512(a) => a.fmt(f),
144            Self::D256(a) => a.fmt(f),
145        }
146    }
147}
148impl PartialEq<f64> for Decimal {
149    fn eq(&self, other: &f64) -> bool {
150        match self {
151            Decimal::D512(a) => &a.to_f64() == other,
152            Decimal::D256(b) => &b.to_f64() == other,
153        }
154    }
155}
156impl PartialEq<i32> for Decimal {
157    fn eq(&self, other: &i32) -> bool {
158        match self {
159            Decimal::D512(a) => a.to_f64() == *other as f64,
160            Decimal::D256(b) => b.to_f64() == *other as f64,
161        }
162    }
163}
164impl_rem!(Decimal, (D512, |x| x), (D256, |x| x));
165impl_new_val_deci!(Decimal);
166impl_partial_ord!(
167    Decimal,
168    (D512, |x: &fastnum::D512| x.to_f64()),
169    (D256, |x: &fastnum::D256| x.to_f64())
170);
171dec_impl!(Decimal, D512, D256);
172impl_neg!(Decimal, D512, D256);
173impl_self_ops!(
174    Decimal,
175    (D512, |x: &fastnum::D512| *x),
176    (D256, |x: &fastnum::D256| *x)
177);