dfp_number/
decimal128.rs

1//! 128-bit decimal floating point arithmetic.
2
3use dfp_number_sys::bid128_000::*;
4use dfp_number_sys::*;
5use std::cmp::Ordering;
6use std::convert::Infallible;
7use std::fmt;
8use std::fmt::{Debug, Display};
9use std::str::FromStr;
10
11#[macro_export]
12macro_rules! decnum {
13  ($e:expr) => {{
14    Decimal128::from(stringify!($e))
15  }};
16}
17
18/// 128-bit decimal floating-point value.
19#[derive(Copy, Clone)]
20pub struct Decimal128(BID128);
21
22impl Default for Decimal128 {
23  /// The default value of [Decimal128] is `0` (zero).
24  fn default() -> Self {
25    Self::zero()
26  }
27}
28
29impl Debug for Decimal128 {
30  /// Converts [Decimal128] into string in debug mode.
31  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32    let mut flags = EXE_CLEAR;
33    write!(f, "{}", bid128_to_string(self.0, &mut flags))
34  }
35}
36
37impl Display for Decimal128 {
38  /// Converts [Decimal128] into human-readable string.
39  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40    let mut flags = EXE_CLEAR;
41    let s = bid128_to_string(self.0, &mut flags);
42    let negative = s.starts_with('-');
43    let mut split = s[1..].split('E');
44    if let Some((sb, sa)) = split.next().zip(split.next()) {
45      if let Ok(exponent) = sa.parse::<isize>() {
46        let decimal_points = exponent.unsigned_abs();
47        let (mut before, mut after) = if exponent < 0 {
48          let digit_count = sb.len();
49          if digit_count <= decimal_points {
50            let before = "0".to_string();
51            let mut after = "0".repeat(decimal_points - digit_count);
52            after.push_str(sb.trim_end_matches('0'));
53            (before, after)
54          } else {
55            let before = sb[..digit_count - decimal_points].to_string();
56            let after = sb[digit_count - decimal_points..].trim_end_matches('0').to_string();
57            (before, after)
58          }
59        } else {
60          let mut before = sb.to_string();
61          before.push_str(&"0".repeat(decimal_points));
62          let after = "".to_string();
63          (before, after)
64        };
65        if let Some(precision) = f.precision() {
66          if after.len() < precision {
67            after.push_str(&"0".repeat(precision - after.len()));
68          } else {
69            after = after[0..precision].to_string();
70          }
71        }
72        if !after.is_empty() {
73          before.push('.');
74          before.push_str(&after);
75        }
76        return f.pad_integral(!negative, "", &before);
77      }
78    }
79    f.pad(&s)
80  }
81}
82
83impl Decimal128 {
84  pub fn new(n: i64, s: i32) -> Self {
85    Self(bid128_scalbn(bid128_from_int64(n), -s))
86  }
87
88  pub fn zero() -> Self {
89    Self(bid128_from_uint32(0))
90  }
91
92  pub fn is_zero(&self) -> bool {
93    bid128_is_zero(self.0)
94  }
95
96  pub fn one() -> Self {
97    Self(bid128_from_uint32(1))
98  }
99
100  pub fn two() -> Self {
101    Self(bid128_from_uint32(2))
102  }
103
104  pub fn ten() -> Self {
105    Self(bid128_from_uint32(10))
106  }
107
108  pub fn one_hundred() -> Self {
109    Self(bid128_from_uint32(100))
110  }
111
112  pub fn one_thousand() -> Self {
113    Self(bid128_from_uint32(1000))
114  }
115
116  pub fn ln(&self) -> Decimal128 {
117    let mut flags = EXE_CLEAR;
118    Self(bid128_log(self.0, RND_NEAREST_EVEN, &mut flags))
119  }
120
121  pub fn exp(&self) -> Decimal128 {
122    let mut flags = EXE_CLEAR;
123    Self(bid128_exp(self.0, RND_NEAREST_EVEN, &mut flags))
124  }
125
126  pub fn round_dp(&self, dp: i32) -> Self {
127    let q = bid128_scalbn(Self::one().0, -dp);
128    let mut flags = EXE_CLEAR;
129    Self(bid128_quantize(self.0, q, RND_NEAREST_EVEN, &mut flags))
130  }
131}
132
133impl std::ops::Neg for Decimal128 {
134  type Output = Self;
135  fn neg(self) -> Self::Output {
136    Self(bid128_negate(self.0))
137  }
138}
139
140impl std::ops::Add<Self> for Decimal128 {
141  type Output = Self;
142
143  fn add(self, rhs: Self) -> Self::Output {
144    let mut flags = EXE_CLEAR;
145    Self(bid128_add(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags))
146  }
147}
148
149impl std::ops::AddAssign<Self> for Decimal128 {
150  fn add_assign(&mut self, rhs: Self) {
151    let mut flags = EXE_CLEAR;
152    self.0 = bid128_add(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags)
153  }
154}
155
156impl std::ops::Sub<Self> for Decimal128 {
157  type Output = Self;
158
159  fn sub(self, rhs: Self) -> Self::Output {
160    let mut flags = EXE_CLEAR;
161    Self(bid128_sub(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags))
162  }
163}
164
165impl std::ops::SubAssign<Self> for Decimal128 {
166  fn sub_assign(&mut self, rhs: Self) {
167    let mut flags = EXE_CLEAR;
168    self.0 = bid128_sub(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags)
169  }
170}
171
172impl std::ops::Mul<Self> for Decimal128 {
173  type Output = Self;
174
175  fn mul(self, rhs: Self) -> Self::Output {
176    let mut flags = EXE_CLEAR;
177    Self(bid128_mul(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags))
178  }
179}
180
181impl std::ops::MulAssign<Self> for Decimal128 {
182  fn mul_assign(&mut self, rhs: Self) {
183    let mut flags = EXE_CLEAR;
184    self.0 = bid128_mul(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags)
185  }
186}
187
188impl std::ops::Div<Self> for Decimal128 {
189  type Output = Self;
190
191  fn div(self, rhs: Self) -> Self::Output {
192    let mut flags = EXE_CLEAR;
193    Self(bid128_div(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags))
194  }
195}
196
197impl std::ops::DivAssign<Self> for Decimal128 {
198  fn div_assign(&mut self, rhs: Self) {
199    let mut flags = EXE_CLEAR;
200    self.0 = bid128_div(self.0, rhs.0, RND_NEAREST_EVEN, &mut flags)
201  }
202}
203
204impl PartialEq<Self> for Decimal128 {
205  fn eq(&self, rhs: &Self) -> bool {
206    let mut flags = EXE_CLEAR;
207    bid128_quiet_equal(self.0, rhs.0, &mut flags)
208  }
209}
210
211impl Eq for Decimal128 {}
212
213impl PartialOrd<Self> for Decimal128 {
214  fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
215    Some(self.cmp(rhs))
216  }
217
218  fn lt(&self, rhs: &Self) -> bool {
219    let mut flags = EXE_CLEAR;
220    bid128_quiet_less(self.0, rhs.0, &mut flags)
221  }
222
223  fn le(&self, rhs: &Self) -> bool {
224    let mut flags = EXE_CLEAR;
225    bid128_quiet_less_equal(self.0, rhs.0, &mut flags)
226  }
227
228  fn gt(&self, rhs: &Self) -> bool {
229    let mut flags = EXE_CLEAR;
230    bid128_quiet_greater(self.0, rhs.0, &mut flags)
231  }
232
233  fn ge(&self, rhs: &Self) -> bool {
234    let mut flags = EXE_CLEAR;
235    bid128_quiet_greater_equal(self.0, rhs.0, &mut flags)
236  }
237}
238
239impl Ord for Decimal128 {
240  fn cmp(&self, rhs: &Self) -> Ordering {
241    let mut flags = EXE_CLEAR;
242    if bid128_quiet_equal(self.0, rhs.0, &mut flags) {
243      return Ordering::Equal;
244    }
245    flags = EXE_CLEAR;
246    if bid128_quiet_less(self.0, rhs.0, &mut flags) {
247      return Ordering::Less;
248    }
249    Ordering::Greater
250  }
251
252  fn max(self, rhs: Self) -> Self
253  where
254    Self: Sized,
255  {
256    let mut flags = EXE_CLEAR;
257    Self(bid128_min_num(self.0, rhs.0, &mut flags))
258  }
259
260  fn min(self, rhs: Self) -> Self
261  where
262    Self: Sized,
263  {
264    let mut flags = EXE_CLEAR;
265    Self(bid128_min_num(self.0, rhs.0, &mut flags))
266  }
267}
268
269impl From<&str> for Decimal128 {
270  /// Converts [Decimal128] from [str].
271  fn from(s: &str) -> Self {
272    let mut flags = EXE_CLEAR;
273    Self(bid128_from_string(s, RND_NEAREST_EVEN, &mut flags))
274  }
275}
276
277impl FromStr for Decimal128 {
278  type Err = Infallible;
279  /// Converts [Decimal128] from [str].
280  fn from_str(s: &str) -> Result<Self, Self::Err> {
281    Ok(s.into())
282  }
283}
284
285impl From<u8> for Decimal128 {
286  /// Converts [Decimal128] from [u8].
287  fn from(n: u8) -> Self {
288    Self(bid128_from_uint32(n as u32))
289  }
290}
291
292impl From<i8> for Decimal128 {
293  /// Converts [Decimal128] from [i8].
294  fn from(n: i8) -> Self {
295    Self(bid128_from_int32(n as i32))
296  }
297}
298
299impl From<u16> for Decimal128 {
300  /// Converts [Decimal128] from [u16].
301  fn from(n: u16) -> Self {
302    Self(bid128_from_uint32(n as u32))
303  }
304}
305
306impl From<i16> for Decimal128 {
307  /// Converts [Decimal128] from [i16].
308  fn from(n: i16) -> Self {
309    Self(bid128_from_int32(n as i32))
310  }
311}
312
313impl From<u32> for Decimal128 {
314  /// Converts [Decimal128] from [u32].
315  fn from(n: u32) -> Self {
316    Self(bid128_from_uint32(n))
317  }
318}
319
320impl From<i32> for Decimal128 {
321  /// Converts [Decimal128] from [i32].
322  fn from(n: i32) -> Self {
323    Self(bid128_from_int32(n))
324  }
325}
326
327impl From<u64> for Decimal128 {
328  /// Converts [Decimal128] from [u64].
329  fn from(n: u64) -> Self {
330    Self(bid128_from_uint64(n))
331  }
332}
333
334impl From<i64> for Decimal128 {
335  /// Converts [Decimal128] from [i64].
336  fn from(n: i64) -> Self {
337    Self(bid128_from_int64(n))
338  }
339}
340
341impl From<usize> for Decimal128 {
342  /// Converts [Decimal128] from [usize].
343  fn from(n: usize) -> Self {
344    Self(bid128_from_uint64(n as u64))
345  }
346}
347
348impl From<isize> for Decimal128 {
349  /// Converts [Decimal128] from [isize].
350  fn from(n: isize) -> Self {
351    Self(bid128_from_int64(n as i64))
352  }
353}