dec/
decimal64.rs

1// Copyright Materialize, Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.inner (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License in the LICENSE file at the
6// root of this repository, or online at
7//
8//     http://www.apache.org/licenses/LICENSE-2.inner
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::cmp::Ordering;
17use std::convert::TryFrom;
18use std::convert::TryInto;
19use std::ffi::{CStr, CString};
20use std::fmt;
21use std::iter::{Product, Sum};
22use std::marker::PhantomData;
23use std::mem::MaybeUninit;
24use std::ops::{
25    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
26};
27use std::str::FromStr;
28
29use libc::c_char;
30#[cfg(feature = "num-traits")]
31use num_traits::{MulAdd, MulAddAssign, One, Zero};
32
33use crate::context::{Class, Context};
34use crate::decimal::Decimal;
35use crate::decimal128::Decimal128;
36use crate::decimal32::Decimal32;
37use crate::error::ParseDecimalError;
38
39/// A 64-bit decimal floating-point number.
40///
41/// Additional operations are defined as methods on the [`Context`] type.
42///
43/// For convenience, `Decimal64` overloads many of the standard Rust operators.
44/// For example, you can use the standard `+` operator to add two values
45/// together:
46///
47/// ```
48/// use dec::Decimal64;
49/// let a = Decimal64::from(1);
50/// let b = Decimal64::from(2);
51/// assert_eq!(a + b, Decimal64::from(3));
52/// ```
53///
54/// These overloaded operators implicitly construct a single-use default
55/// context, which has some performance overhead. For maximum performance when
56/// performing operations in bulk, use a long-lived context that you construct
57/// yourself.
58#[repr(transparent)]
59#[derive(Clone, Copy)]
60pub struct Decimal64 {
61    pub(crate) inner: decnumber_sys::decDouble,
62}
63
64impl Decimal64 {
65    /// The value that represents Not-a-Number (NaN).
66    pub const NAN: Decimal64 = Decimal64::from_ne_bytes(if cfg!(target_endian = "little") {
67        [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7c]
68    } else {
69        [0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
70    });
71
72    /// The value that represents zero.
73    pub const ZERO: Decimal64 = Decimal64::from_ne_bytes(if cfg!(target_endian = "little") {
74        [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x22]
75    } else {
76        [0x22, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
77    });
78
79    /// The value that represents one.
80    pub const ONE: Decimal64 = Decimal64::from_ne_bytes(if cfg!(target_endian = "little") {
81        [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x22]
82    } else {
83        [0x22, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1]
84    });
85
86    /// The value that represents 2<sup>32</sup>.
87    const TWO_POW_32: Decimal64 = Decimal64::from_ne_bytes(if cfg!(target_endian = "little") {
88        [0x7A, 0xB5, 0xAF, 0x15, 0x1, 0x0, 0x38, 0x22]
89    } else {
90        [0x22, 0x38, 0x0, 0x1, 0x15, 0xAF, 0xB5, 0x7A]
91    });
92
93    /// Creates a number from its representation as a little-endian byte array.
94    pub fn from_le_bytes(mut bytes: [u8; 8]) -> Decimal64 {
95        if cfg!(target_endian = "big") {
96            bytes.reverse();
97        }
98        Decimal64::from_ne_bytes(bytes)
99    }
100
101    /// Creates a number from its representation as a big-endian byte array.
102    pub fn from_be_bytes(mut bytes: [u8; 8]) -> Decimal64 {
103        if cfg!(target_endian = "little") {
104            bytes.reverse();
105        }
106        Decimal64::from_ne_bytes(bytes)
107    }
108
109    /// Creates a number from its representation as a byte array in the
110    /// native endianness of the target platform.
111    pub const fn from_ne_bytes(bytes: [u8; 8]) -> Decimal64 {
112        Decimal64 {
113            inner: decnumber_sys::decDouble { bytes },
114        }
115    }
116
117    /// Returns the memory representation of the number as a byte array in
118    /// little-endian order.
119    pub fn to_le_bytes(&self) -> [u8; 8] {
120        let mut bytes = self.to_ne_bytes();
121        if cfg!(target_endian = "big") {
122            bytes.reverse();
123        }
124        bytes
125    }
126
127    /// Returns the memory representation of the number as a byte array in
128    /// big-endian order.
129    pub fn to_be_bytes(&self) -> [u8; 8] {
130        let mut bytes = self.to_ne_bytes();
131        if cfg!(target_endian = "little") {
132            bytes.reverse();
133        }
134        bytes
135    }
136
137    /// Returns the memory representation of the number as a byte array in
138    /// the native endianness of the target platform.
139    pub fn to_ne_bytes(&self) -> [u8; 8] {
140        self.inner.bytes
141    }
142
143    /// Classifies the number.
144    pub fn class(&self) -> Class {
145        Class::from_c(unsafe { decnumber_sys::decDoubleClass(&self.inner) })
146    }
147
148    /// Computes the number of significant digits in the number.
149    ///
150    /// If the number is zero or infinite, returns 1. If the number is a NaN,
151    /// returns the number of digits in the payload.
152    pub fn digits(&self) -> u32 {
153        unsafe { decnumber_sys::decDoubleDigits(&self.inner) }
154    }
155
156    /// Computes the coefficient of the number.
157    ///
158    /// If the number is a special value (i.e., NaN or infinity), returns zero.
159    pub fn coefficient(&self) -> i64 {
160        let mut dpd = if cfg!(target_endian = "big") {
161            u64::from_be_bytes(self.inner.bytes)
162        } else {
163            u64::from_le_bytes(self.inner.bytes)
164        };
165
166        // Densely packed decimals are 10-bit strings.
167        let dpd_mask = 0b11_1111_1111;
168
169        // Digits 8-16
170        // Lossy conversion from u64 to usize is fine because we only care
171        // about the 10 rightmost bits.
172        let mut r = i64::from(unsafe { decnumber_sys::DPD2BIN[dpd as usize & dpd_mask] });
173        dpd >>= 10;
174        r += i64::from(unsafe { decnumber_sys::DPD2BINK[dpd as usize & dpd_mask] });
175        dpd >>= 10;
176        r += i64::from(unsafe { decnumber_sys::DPD2BINM[dpd as usize & dpd_mask] });
177        dpd >>= 10;
178
179        // Digits 2-7
180        let mut r_1: i64 = 0;
181        r_1 += i64::from(unsafe { decnumber_sys::DPD2BIN[dpd as usize & dpd_mask] });
182        dpd >>= 10;
183        r_1 += i64::from(unsafe { decnumber_sys::DPD2BINK[dpd as usize & dpd_mask] });
184
185        r += r_1 * 10_000_000_00;
186
187        // Digit 1
188        let h = i64::from(unsafe { decnumber_sys::DECCOMBMSD[(dpd >> 18) as usize] });
189
190        if h > 0 {
191            r += h * 1_000_000_000_000_000;
192        }
193
194        if self.is_negative() {
195            r *= -1;
196        }
197
198        r
199    }
200
201    /// Returns the individual digits of the coefficient in 8-bit, unpacked
202    /// [binary-coded decimal][bcd] format.
203    ///
204    /// [bcd]: https://en.wikipedia.org/wiki/Binary-coded_decimal
205    pub fn coefficient_digits(&self) -> [u8; decnumber_sys::DECDOUBLE_Pmax] {
206        let mut buf = [0u8; decnumber_sys::DECDOUBLE_Pmax];
207        unsafe {
208            decnumber_sys::decDoubleGetCoefficient(&self.inner, buf.as_mut_ptr() as *mut u8);
209        }
210        buf
211    }
212
213    /// Computes the exponent of the number.
214    pub fn exponent(&self) -> i32 {
215        unsafe { decnumber_sys::decDoubleGetExponent(&self.inner) }
216    }
217
218    /// Returns an equivalent number whose encoding is guaranteed to be
219    /// canonical.
220    pub fn canonical(mut self) -> Decimal64 {
221        unsafe {
222            decnumber_sys::decDoubleCanonical(&mut self.inner, &self.inner);
223        }
224        self
225    }
226
227    /// Reports whether the encoding of the number is canonical.
228    pub fn is_canonical(&self) -> bool {
229        unsafe { decnumber_sys::decDoubleIsCanonical(&self.inner) != 0 }
230    }
231
232    /// Reports whether the number is finite.
233    ///
234    /// A finite number is one that is neither infinite nor a NaN.
235    pub fn is_finite(&self) -> bool {
236        unsafe { decnumber_sys::decDoubleIsFinite(&self.inner) != 0 }
237    }
238
239    /// Reports whether the number is positive or negative infinity.
240    pub fn is_infinite(&self) -> bool {
241        unsafe { decnumber_sys::decDoubleIsInfinite(&self.inner) != 0 }
242    }
243
244    /// Reports whether the number is an integer.
245    ///
246    /// An integer is a decimal number that is finite and has an exponent of
247    /// zero.
248    pub fn is_integer(&self) -> bool {
249        unsafe { decnumber_sys::decDoubleIsInteger(&self.inner) != 0 }
250    }
251
252    /// Reports whether the number is a valid argument for logical operations.
253    ///
254    /// A number is a valid argument for logical operations if it is a
255    /// nonnegative integer where each digit is either zero or one.
256    pub fn is_logical(&self) -> bool {
257        unsafe { decnumber_sys::decDoubleIsInteger(&self.inner) != 0 }
258    }
259
260    /// Reports whether the number is a NaN.
261    pub fn is_nan(&self) -> bool {
262        unsafe { decnumber_sys::decDoubleIsNaN(&self.inner) != 0 }
263    }
264
265    /// Reports whether the number is less than zero and not a NaN.
266    pub fn is_negative(&self) -> bool {
267        unsafe { decnumber_sys::decDoubleIsNegative(&self.inner) != 0 }
268    }
269
270    /// Reports whether the number is normal.
271    ///
272    /// A normal number is finite, non-zero, and not subnormal.
273    pub fn is_normal(&self) -> bool {
274        unsafe { decnumber_sys::decDoubleIsNormal(&self.inner) != 0 }
275    }
276
277    /// Reports whether the number is greater than zero and not a NaN.
278    pub fn is_positive(&self) -> bool {
279        unsafe { decnumber_sys::decDoubleIsPositive(&self.inner) != 0 }
280    }
281
282    /// Reports whether the number is a signaling NaN.
283    pub fn is_signaling_nan(&self) -> bool {
284        unsafe { decnumber_sys::decDoubleIsSignaling(&self.inner) != 0 }
285    }
286
287    /// Reports whether the number has a sign of 1.
288    ///
289    /// Note that zeros and NaNs may have a sign of 1.
290    pub fn is_signed(&self) -> bool {
291        unsafe { decnumber_sys::decDoubleIsSigned(&self.inner) != 0 }
292    }
293
294    /// Reports whether the number is subnormal.
295    ///
296    /// A subnormal number is finite, non-zero, and has magnitude less than
297    /// 10<sup>emin</sup>.
298    pub fn is_subnormal(&self) -> bool {
299        unsafe { decnumber_sys::decDoubleIsSubnormal(&self.inner) != 0 }
300    }
301
302    /// Reports whether the number is positive or negative zero.
303    pub fn is_zero(&self) -> bool {
304        unsafe { decnumber_sys::decDoubleIsZero(&self.inner) != 0 }
305    }
306
307    /// Reports whether the quantum of the number matches the quantum of
308    /// `rhs`.
309    ///
310    /// Quantums are considered to match if the numbers have the same exponent,
311    /// are both NaNs, or both infinite.
312    pub fn quantum_matches(&self, rhs: &Decimal64) -> bool {
313        unsafe { decnumber_sys::decDoubleSameQuantum(&self.inner, &rhs.inner) != 0 }
314    }
315
316    /// Determines the ordering of this number relative to `rhs`, using the
317    /// total order predicate defined in IEEE 754-2008.
318    ///
319    /// For a brief description of the ordering, consult [`f32::total_cmp`].
320    pub fn total_cmp(&self, rhs: &Decimal64) -> Ordering {
321        let mut d = Decimal64::ZERO;
322        unsafe {
323            decnumber_sys::decDoubleCompareTotal(&mut d.inner, &self.inner, &rhs.inner);
324        }
325        if d.is_positive() {
326            Ordering::Greater
327        } else if d.is_negative() {
328            Ordering::Less
329        } else {
330            debug_assert!(d.is_zero());
331            Ordering::Equal
332        }
333    }
334
335    /// Returns a string of the number in standard notation, i.e. guaranteed to
336    /// not be scientific notation.
337    pub fn to_standard_notation_string(&self) -> String {
338        if !self.is_finite() {
339            return self.to_string();
340        }
341        let mut digits = [b'0'; decnumber_sys::DECDOUBLE_Pmax];
342        let mut digits_idx = 0;
343        let (sourlo, sourhi) = if cfg!(target_endian = "little") {
344            (
345                u32::from_le_bytes(self.inner.bytes[0..4].try_into().unwrap()) as usize,
346                u32::from_le_bytes(self.inner.bytes[4..8].try_into().unwrap()) as usize,
347            )
348        } else {
349            (
350                u32::from_be_bytes(self.inner.bytes[4..8].try_into().unwrap()) as usize,
351                u32::from_be_bytes(self.inner.bytes[0..4].try_into().unwrap()) as usize,
352            )
353        };
354
355        let comb = ((sourhi >> 26) & 0x1f) as usize;
356        let msd = unsafe { decnumber_sys::DECCOMBMSD[comb] };
357
358        if msd > 0 {
359            digits[digits_idx] = b'0' + msd as u8;
360            digits_idx += 1;
361        }
362
363        #[allow(unused_assignments)]
364        let mut dpd: usize = 0;
365
366        dpd = (sourhi >> 8) & 0x3ff; // declet 1
367        dpd2char!(dpd, digits, digits_idx);
368
369        dpd = ((sourhi & 0xff) << 2) | (sourlo >> 30); // declet 2
370        dpd2char!(dpd, digits, digits_idx);
371
372        dpd = (sourlo >> 20) & 0x3ff; // declet 3
373        dpd2char!(dpd, digits, digits_idx);
374
375        dpd = (sourlo >> 10) & 0x3ff; // declet 4
376        dpd2char!(dpd, digits, digits_idx);
377
378        dpd = (sourlo) & 0x3ff; // declet 5
379        dpd2char!(dpd, digits, digits_idx);
380
381        stringify_digits!(self, digits, digits_idx)
382    }
383}
384
385#[test]
386fn test() {
387    let mut cx = Context::<Decimal64>::default();
388    let d = cx.parse("0").unwrap();
389    println!("{:?}", d.to_standard_notation_string());
390}
391
392impl Default for Decimal64 {
393    fn default() -> Decimal64 {
394        Decimal64::ZERO
395    }
396}
397
398impl fmt::Debug for Decimal64 {
399    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
400        fmt::Display::fmt(self, f)
401    }
402}
403
404impl fmt::Display for Decimal64 {
405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406        let mut buf = ['\0'; decnumber_sys::DECDOUBLE_String];
407        let c_str = unsafe {
408            if f.alternate() {
409                decnumber_sys::decDoubleToEngString(&self.inner, buf.as_mut_ptr() as *mut c_char);
410            } else {
411                decnumber_sys::decDoubleToString(&self.inner, buf.as_mut_ptr() as *mut c_char);
412            }
413            CStr::from_ptr(buf.as_ptr() as *const c_char)
414        };
415        f.write_str(
416            c_str
417                .to_str()
418                .expect("decDoubleToString yields valid UTF-8"),
419        )
420    }
421}
422
423impl FromStr for Decimal64 {
424    type Err = ParseDecimalError;
425
426    fn from_str(s: &str) -> Result<Decimal64, ParseDecimalError> {
427        Context::<Decimal64>::default().parse(s)
428    }
429}
430
431impl From<i32> for Decimal64 {
432    fn from(n: i32) -> Decimal64 {
433        let mut d = Decimal64::ZERO;
434        unsafe {
435            decnumber_sys::decDoubleFromInt32(&mut d.inner, n);
436        };
437        d
438    }
439}
440
441impl From<u32> for Decimal64 {
442    fn from(n: u32) -> Decimal64 {
443        let mut d = Decimal64::ZERO;
444        unsafe {
445            decnumber_sys::decDoubleFromUInt32(&mut d.inner, n);
446        };
447        d
448    }
449}
450
451impl From<Decimal32> for Decimal64 {
452    fn from(d32: Decimal32) -> Decimal64 {
453        let mut d64 = Decimal64::ZERO;
454        unsafe {
455            decnumber_sys::decSingleToWider(&d32.inner, &mut d64.inner);
456        }
457        d64
458    }
459}
460
461impl PartialOrd for Decimal64 {
462    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
463        Context::<Decimal64>::default().partial_cmp(*self, *other)
464    }
465}
466
467impl PartialEq for Decimal64 {
468    fn eq(&self, other: &Self) -> bool {
469        self.partial_cmp(other) == Some(Ordering::Equal)
470    }
471}
472
473impl Neg for Decimal64 {
474    type Output = Decimal64;
475
476    fn neg(self) -> Decimal64 {
477        Context::<Decimal64>::default().minus(self)
478    }
479}
480
481impl Add<Decimal64> for Decimal64 {
482    type Output = Decimal64;
483
484    fn add(self, rhs: Decimal64) -> Decimal64 {
485        Context::<Decimal64>::default().add(self, rhs)
486    }
487}
488
489impl AddAssign<Decimal64> for Decimal64 {
490    fn add_assign(&mut self, rhs: Decimal64) {
491        *self = Context::<Decimal64>::default().add(*self, rhs);
492    }
493}
494
495impl Div<Decimal64> for Decimal64 {
496    type Output = Decimal64;
497
498    fn div(self, rhs: Decimal64) -> Decimal64 {
499        Context::<Decimal64>::default().div(self, rhs)
500    }
501}
502
503impl DivAssign<Decimal64> for Decimal64 {
504    fn div_assign(&mut self, rhs: Decimal64) {
505        *self = Context::<Decimal64>::default().div(*self, rhs);
506    }
507}
508
509impl Mul<Decimal64> for Decimal64 {
510    type Output = Decimal64;
511
512    fn mul(self, rhs: Decimal64) -> Decimal64 {
513        Context::<Decimal64>::default().mul(self, rhs)
514    }
515}
516
517impl MulAssign<Decimal64> for Decimal64 {
518    fn mul_assign(&mut self, rhs: Decimal64) {
519        *self = Context::<Decimal64>::default().mul(*self, rhs);
520    }
521}
522
523impl Rem<Decimal64> for Decimal64 {
524    type Output = Decimal64;
525
526    fn rem(self, rhs: Decimal64) -> Decimal64 {
527        Context::<Decimal64>::default().rem(self, rhs)
528    }
529}
530
531impl RemAssign<Decimal64> for Decimal64 {
532    fn rem_assign(&mut self, rhs: Decimal64) {
533        *self = Context::<Decimal64>::default().rem(*self, rhs);
534    }
535}
536
537impl Sub<Decimal64> for Decimal64 {
538    type Output = Decimal64;
539
540    fn sub(self, rhs: Decimal64) -> Decimal64 {
541        Context::<Decimal64>::default().sub(self, rhs)
542    }
543}
544
545impl SubAssign<Decimal64> for Decimal64 {
546    fn sub_assign(&mut self, rhs: Decimal64) {
547        *self = Context::<Decimal64>::default().sub(*self, rhs);
548    }
549}
550
551impl Sum for Decimal64 {
552    fn sum<I>(iter: I) -> Self
553    where
554        I: Iterator<Item = Decimal64>,
555    {
556        let mut cx = Context::<Decimal64>::default();
557        let mut sum = Decimal64::ZERO;
558        for d in iter {
559            sum = cx.add(sum, d);
560        }
561        sum
562    }
563}
564
565impl<'a> Sum<&'a Decimal64> for Decimal64 {
566    fn sum<I>(iter: I) -> Self
567    where
568        I: Iterator<Item = &'a Decimal64>,
569    {
570        iter.copied().sum()
571    }
572}
573
574impl Product for Decimal64 {
575    fn product<I>(iter: I) -> Self
576    where
577        I: Iterator<Item = Decimal64>,
578    {
579        let mut cx = Context::<Decimal64>::default();
580        let mut product = Decimal64::ONE;
581        for d in iter {
582            product = cx.mul(product, d);
583        }
584        product
585    }
586}
587
588impl<'a> Product<&'a Decimal64> for Decimal64 {
589    fn product<I>(iter: I) -> Self
590    where
591        I: Iterator<Item = &'a Decimal64>,
592    {
593        iter.copied().product()
594    }
595}
596
597impl Default for Context<Decimal64> {
598    fn default() -> Context<Decimal64> {
599        let mut ctx = MaybeUninit::<decnumber_sys::decContext>::uninit();
600        let ctx = unsafe {
601            decnumber_sys::decContextDefault(ctx.as_mut_ptr(), decnumber_sys::DEC_INIT_DECDOUBLE);
602            ctx.assume_init()
603        };
604        Context {
605            inner: ctx,
606            _phantom: PhantomData,
607        }
608    }
609}
610
611impl Context<Decimal64> {
612    /// Parses a number from its string representation.
613    pub fn parse<S>(&mut self, s: S) -> Result<Decimal64, ParseDecimalError>
614    where
615        S: Into<Vec<u8>>,
616    {
617        let c_string = CString::new(s).map_err(|_| ParseDecimalError)?;
618        let mut d = Decimal64::ZERO;
619        unsafe {
620            decnumber_sys::decDoubleFromString(&mut d.inner, c_string.as_ptr(), &mut self.inner);
621        };
622        if (self.inner.status & decnumber_sys::DEC_Conversion_syntax) != 0 {
623            Err(ParseDecimalError)
624        } else {
625            Ok(d)
626        }
627    }
628
629    /// Constructs a number from a 128-bit decimal float.
630    ///
631    /// The result may be inexact. The status fields on the context will be set
632    /// appropriately if so.
633    pub fn from_decimal128(&mut self, d128: Decimal128) -> Decimal64 {
634        let mut d64 = Decimal64::ZERO;
635        unsafe {
636            decnumber_sys::decDoubleFromWider(&mut d64.inner, &d128.inner, &mut self.inner);
637        };
638        d64
639    }
640
641    /// Constructs a number from an arbitrary-precision decimal.
642    ///
643    /// The result may be inexact. The status fields on the context will be set
644    /// appropriately if so.
645    pub fn from_decimal<const N: usize>(&mut self, d: &Decimal<N>) -> Decimal64 {
646        let mut d64 = Decimal64::ZERO;
647        unsafe {
648            decnumber_sys::decimal64FromNumber(&mut d64.inner, d.as_ptr(), &mut self.inner);
649        };
650        d64
651    }
652
653    /// Constructs a number from an `i64`.
654    ///
655    /// Note that this function can return inexact results for numbers with 15
656    /// or more places of precision, e.g. `99_999_999_999_999_999i64`,
657    /// `-99_999_999_999_999_999i64`, `i64::MAX`, `i64::MIN`, etc.
658    ///
659    /// However, some numbers with 15 or more places of precision retain their
660    /// exactness, e.g. `1_000_000_000_000_000i64`.
661    ///
662    /// ```
663    /// use dec::Decimal64;
664    /// let mut ctx = dec::Context::<Decimal64>::default();
665    /// let d = ctx.from_i64(-99_999_999_999_999_999i64);
666    /// // Inexact result
667    /// assert!(ctx.status().inexact());
668    ///
669    /// let mut ctx = dec::Context::<Decimal64>::default();
670    /// let d = ctx.from_i64(1_000_000_000_000_000i64);
671    /// // Exact result
672    /// assert!(!ctx.status().inexact());
673    /// ```
674    ///
675    /// To avoid inexact results when converting from large `i64`, use
676    /// [`crate::Decimal128`] instead.
677    pub fn from_i64(&mut self, n: i64) -> Decimal64 {
678        from_signed_int!(Decimal64, self, n)
679    }
680
681    /// Constructs a number from an `u64`.
682    ///
683    /// Note that this function can return inexact results for numbers with 16
684    /// or more places of precision, e.g., `1_000_000_000_000_0001u64` and
685    /// `u64::MAX`.
686    ///
687    /// However, some numbers with 15 or more places of precision retain their
688    /// exactness, e.g. `1_000_000_000_000_000u64`.
689    ///
690    /// ```
691    /// use dec::Decimal64;
692    /// let mut ctx = dec::Context::<Decimal64>::default();
693    /// let d = ctx.from_i64(1_000_000_000_000_0001i64);
694    /// // Inexact result
695    /// assert!(ctx.status().inexact());
696    ///
697    /// let mut ctx = dec::Context::<Decimal64>::default();
698    /// let d = ctx.from_i64(1_000_000_000_000_000i64);
699    /// // Exact result
700    /// assert!(!ctx.status().inexact());
701    /// ```
702    ///
703    /// To avoid inexact results when converting from large `u64`, use
704    /// [`crate::Decimal128`] instead.
705    pub fn from_u64(&mut self, n: u64) -> Decimal64 {
706        from_unsigned_int!(Decimal64, self, n)
707    }
708
709    /// Computes the absolute value of `n`.
710    ///
711    /// This has the same effect as [`Context::<Decimal64>::plus`] unless
712    /// `n` is negative, in which case it has the same effect as
713    /// [`Context::<Decimal64>::minus`].
714    ///
715    /// The returned result will be canonical.
716    pub fn abs(&mut self, mut n: Decimal64) -> Decimal64 {
717        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
718        unsafe {
719            decnumber_sys::decDoubleAbs(n_inner, n_inner, &mut self.inner);
720        }
721        n
722    }
723
724    /// Adds `lhs` and `rhs`.
725    pub fn add(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
726        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
727        unsafe {
728            decnumber_sys::decDoubleAdd(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
729        }
730        lhs
731    }
732
733    /// Carries out the digitwise logical and of `lhs` and `rhs`.
734    ///
735    /// The operands must be valid for logical operations.
736    /// See [`Decimal64::is_logical`].
737    pub fn and(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
738        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
739        unsafe {
740            decnumber_sys::decDoubleAnd(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
741        }
742        lhs
743    }
744
745    /// Divides `lhs` by `rhs`.
746    pub fn div(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
747        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
748        unsafe {
749            decnumber_sys::decDoubleDivide(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
750        }
751        lhs
752    }
753
754    /// Divides `lhs` by `rhs` and returns the integer part of the result
755    /// (rounded towards zero) with an exponent of 0.
756    ///
757    /// If the result would overflow, then [`Status::division_impossible`] is
758    /// set.
759    ///
760    /// [`Status::division_impossible`]: crate::context::Status::division_impossible
761    pub fn div_integer(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
762        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
763        unsafe {
764            decnumber_sys::decDoubleDivideInteger(
765                lhs_inner,
766                lhs_inner,
767                &rhs.inner,
768                &mut self.inner,
769            );
770        }
771        lhs
772    }
773
774    /// Calculates the fused multiply-add `(x * y) + z`.
775    ///
776    /// The multiplication is carried out first and is exact, so this operation
777    /// only has the one, final rounding.
778    pub fn fma(&mut self, mut x: Decimal64, y: Decimal64, z: Decimal64) -> Decimal64 {
779        let x_inner = &mut x.inner as *mut decnumber_sys::decDouble;
780        unsafe {
781            decnumber_sys::decDoubleFMA(x_inner, x_inner, &y.inner, &z.inner, &mut self.inner);
782        }
783        x
784    }
785
786    /// Carries out the digitwise logical inversion of `n`.
787    ///
788    /// The operand must be valid for logical operation.
789    /// See [`Decimal64::is_logical`].
790    pub fn invert(&mut self, mut n: Decimal64) -> Decimal64 {
791        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
792        unsafe {
793            decnumber_sys::decDoubleInvert(n_inner, n_inner, &mut self.inner);
794        }
795        n
796    }
797
798    /// Computes the adjusted exponent of the number, according to IEEE 754
799    /// rules.
800    pub fn logb(&mut self, mut n: Decimal64) -> Decimal64 {
801        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
802        unsafe {
803            decnumber_sys::decDoubleLogB(n_inner, n_inner, &mut self.inner);
804        }
805        n
806    }
807
808    /// Returns whichever of `lhs` and `rhs` is larger.
809    ////
810    /// The comparison is performed using the same rules as for
811    /// [`Decimal64::total_cmp`].
812    pub fn max(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
813        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
814        unsafe {
815            decnumber_sys::decDoubleMax(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
816        }
817        lhs
818    }
819
820    /// Returns whichever of `lhs` and `rhs` has the largest absolute value.
821    pub fn max_abs(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
822        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
823        unsafe {
824            decnumber_sys::decDoubleMaxMag(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
825        }
826        lhs
827    }
828
829    /// Returns whichever of `lhs` and `rhs` is smaller.
830    ////
831    /// The comparison is performed using the same rules as for
832    /// [`Decimal64::total_cmp`].
833    pub fn min(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
834        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
835        unsafe {
836            decnumber_sys::decDoubleMin(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
837        }
838        lhs
839    }
840
841    /// Returns whichever of `lhs` and `rhs` has the largest absolute value.
842    pub fn min_abs(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
843        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
844        unsafe {
845            decnumber_sys::decDoubleMinMag(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
846        }
847        lhs
848    }
849
850    /// Subtracts `n` from zero.
851    pub fn minus(&mut self, mut n: Decimal64) -> Decimal64 {
852        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
853        unsafe {
854            decnumber_sys::decDoubleMinus(n_inner, n_inner, &mut self.inner);
855        }
856        n
857    }
858
859    /// Multiplies `lhs` by `rhs`.
860    pub fn mul(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
861        unsafe {
862            decnumber_sys::decDoubleMultiply(
863                &mut lhs.inner,
864                &lhs.inner,
865                &rhs.inner,
866                &mut self.inner,
867            );
868        }
869        lhs
870    }
871
872    /// Returns the next number to `n` in the direction of negative infinity.
873    ///
874    /// This operation follows the IEEE 754 rules for the *nextDown* operation.
875    pub fn next_minus(&mut self, mut n: Decimal64) -> Decimal64 {
876        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
877        unsafe {
878            decnumber_sys::decDoubleNextMinus(n_inner, n_inner, &mut self.inner);
879        }
880        n
881    }
882
883    /// Returns the next number to `n` in the direction of positive infinity.
884    ///
885    /// This operation follows the IEEE 754 rules for the *nextUp* operation.
886    pub fn next_plus(&mut self, mut n: Decimal64) -> Decimal64 {
887        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
888        unsafe {
889            decnumber_sys::decDoubleNextPlus(n_inner, n_inner, &mut self.inner);
890        }
891        n
892    }
893
894    /// Returns the next number to `x` in the direction of `y`.
895    ///
896    /// This operation follows the IEEE 754 rules for the *nextAfter* operation.
897    pub fn next_toward(&mut self, mut x: Decimal64, y: Decimal64) -> Decimal64 {
898        let x_inner = &mut x.inner as *mut decnumber_sys::decDouble;
899        unsafe {
900            decnumber_sys::decDoubleNextToward(x_inner, x_inner, &y.inner, &mut self.inner);
901        }
902        x
903    }
904
905    /// Determines the ordering of `lhs` relative to `rhs`, using a partial
906    /// order.
907    ///
908    /// If either `lhs` or `rhs` is a NaN, returns `None`. To force an ordering
909    /// upon NaNs, use [`Decimal64::total_cmp`] or
910    /// [`OrderedDecimal`](crate::OrderedDecimal).
911    pub fn partial_cmp(&mut self, lhs: Decimal64, rhs: Decimal64) -> Option<Ordering> {
912        let mut d = Decimal64::ZERO;
913        unsafe {
914            decnumber_sys::decDoubleCompare(&mut d.inner, &lhs.inner, &rhs.inner, &mut self.inner);
915        }
916        if d.is_positive() {
917            Some(Ordering::Greater)
918        } else if d.is_negative() {
919            Some(Ordering::Less)
920        } else if d.is_zero() {
921            Some(Ordering::Equal)
922        } else {
923            debug_assert!(d.is_nan());
924            None
925        }
926    }
927
928    /// Adds `n` to zero.
929    pub fn plus(&mut self, mut n: Decimal64) -> Decimal64 {
930        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
931        unsafe {
932            decnumber_sys::decDoublePlus(n_inner, n_inner, &mut self.inner);
933        }
934        n
935    }
936
937    /// Rounds or pads `lhs` so that it has the same exponent as `rhs`.
938    pub fn quantize(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
939        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
940        unsafe {
941            decnumber_sys::decDoubleQuantize(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
942        }
943        lhs
944    }
945
946    /// Reduces the number's coefficient to its shortest possible form without
947    /// changing the value of the result.
948    ///
949    /// This removes all possible trailing zeros; some may remain when the
950    /// number is very close to the most positive or most negative number.
951    pub fn reduce(&mut self, mut n: Decimal64) -> Decimal64 {
952        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
953        unsafe {
954            decnumber_sys::decDoubleReduce(n_inner, n_inner, &mut self.inner);
955        }
956        n
957    }
958
959    /// Integer-divides `lhs` by `rhs` and returns the remainder from the
960    /// division.
961    pub fn rem(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
962        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
963        unsafe {
964            decnumber_sys::decDoubleRemainder(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
965        }
966        lhs
967    }
968
969    /// Like [`rem`](Context::<Decimal64>::rem), but uses the IEEE 754
970    /// rules for remainder operations.
971    pub fn rem_near(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
972        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
973        unsafe {
974            decnumber_sys::decDoubleRemainderNear(
975                lhs_inner,
976                lhs_inner,
977                &rhs.inner,
978                &mut self.inner,
979            );
980        }
981        lhs
982    }
983
984    /// Rotates the digits of `lhs` by `rhs`.
985    ///
986    /// If `rhs` is positive, rotates to the left. If `rhs` is negative, rotates
987    /// to the right.
988    ///
989    /// `rhs` specifies the number of positions to rotate, and must be a finite
990    /// integer. NaNs are propagated as usual.
991    ///
992    /// If `lhs` is infinity, the result is infinity of the same sign.
993    pub fn rotate(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
994        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
995        unsafe {
996            decnumber_sys::decDoubleRotate(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
997        }
998        lhs
999    }
1000
1001    /// Rounds the number to an integral value using the rounding mode in the
1002    /// context.
1003    pub fn round(&mut self, mut n: Decimal64) -> Decimal64 {
1004        let n_inner = &mut n.inner as *mut decnumber_sys::decDouble;
1005        unsafe {
1006            decnumber_sys::decDoubleToIntegralExact(n_inner, n_inner, &mut self.inner);
1007        }
1008        n
1009    }
1010
1011    /// Multiplies `x` by 10<sup>`y`</sup>.
1012    pub fn scaleb(&mut self, mut x: Decimal64, y: Decimal64) -> Decimal64 {
1013        let x_inner = &mut x.inner as *mut decnumber_sys::decDouble;
1014        unsafe {
1015            decnumber_sys::decDoubleScaleB(x_inner, x_inner, &y.inner, &mut self.inner);
1016        }
1017        x
1018    }
1019
1020    /// Sets `d`'s exponent to `e` _without_ modifying the coefficient.
1021    pub fn set_exponent(&mut self, d: &mut Decimal64, e: i32) {
1022        unsafe {
1023            decnumber_sys::decDoubleSetExponent(&mut d.inner, &mut self.inner, e);
1024        }
1025    }
1026
1027    /// Shifts the digits of `lhs` by `rhs`.
1028    ///
1029    /// If `rhs` is positive, shifts to the left. If `rhs` is negative, shifts
1030    /// to the right. Any digits "shifted in" will be zero.
1031    ///
1032    /// `rhs` specifies the number of positions to shift, and must be a finite
1033    /// integer. NaNs are propagated as usual.
1034    ///
1035    /// If `lhs` is infinity, the result is infinity of the same sign.
1036    pub fn shift(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
1037        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
1038        unsafe {
1039            decnumber_sys::decDoubleShift(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
1040        }
1041        lhs
1042    }
1043
1044    /// Adjust `x`'s exponent to equal `s`, while retaining as many of the same
1045    /// significant digits of the coefficient as permitted with the current and
1046    /// new exponents.
1047    ///
1048    /// - When increasing the exponent's value, **irrevocably truncates** the least
1049    ///   significant digits. Use caution in this context.
1050    /// - When reducing the exponent's value, appends `0`s as less significant
1051    ///   digits.
1052    ///
1053    /// ```
1054    /// use dec::{Context, Decimal64};
1055    /// let mut cx = Context::<Decimal64>::default();
1056    /// let mut d = cx.div(Decimal64::from(5), Decimal64::from(4));
1057    ///
1058    /// assert_eq!(d.exponent(), -2);
1059    /// assert_eq!(d.to_string(), "1.25");
1060    ///
1061    /// cx.rescale(&mut d, -3);
1062    /// assert_eq!(d.exponent(), -3);
1063    /// assert_eq!(d.to_string(), "1.250");
1064    ///
1065    /// cx.rescale(&mut d, -1);
1066    /// assert_eq!(d.exponent(), -1);
1067    /// assert_eq!(d.to_string(), "1.2");
1068    ///
1069    /// cx.rescale(&mut d, 0);
1070    /// assert_eq!(d.exponent(), 0);
1071    /// assert_eq!(d.to_string(), "1");
1072    /// ```
1073    pub fn rescale(&mut self, x: &mut Decimal64, s: i32) {
1074        let e = x.exponent();
1075        *x = self.shift(*x, Decimal64::from(e - s));
1076        self.set_exponent(x, s);
1077    }
1078
1079    /// Subtracts `rhs` from `lhs`.
1080    pub fn sub(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
1081        unsafe {
1082            decnumber_sys::decDoubleSubtract(
1083                &mut lhs.inner,
1084                &lhs.inner,
1085                &rhs.inner,
1086                &mut self.inner,
1087            );
1088        }
1089        lhs
1090    }
1091
1092    /// Carries out the digitwise logical or of `lhs` and `rhs`.
1093    ///
1094    /// The operands must be valid for logical operations.
1095    /// See [`Decimal64::is_logical`].
1096    pub fn or(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
1097        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
1098        unsafe {
1099            decnumber_sys::decDoubleOr(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
1100        }
1101        lhs
1102    }
1103
1104    /// Carries out the digitwise logical exclusive or of `lhs` and `rhs`.
1105    ///
1106    /// The operands must be valid for logical operations.
1107    /// See [`Decimal64::is_logical`].
1108    pub fn xor(&mut self, mut lhs: Decimal64, rhs: Decimal64) -> Decimal64 {
1109        let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decDouble;
1110        unsafe {
1111            decnumber_sys::decDoubleXor(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
1112        }
1113        lhs
1114    }
1115}
1116
1117#[cfg(feature = "num-traits")]
1118impl One for Decimal64 {
1119    #[inline]
1120    fn one() -> Self {
1121        Self::ONE
1122    }
1123}
1124
1125#[cfg(feature = "num-traits")]
1126impl Zero for Decimal64 {
1127    #[inline]
1128    fn zero() -> Self {
1129        Self::ZERO
1130    }
1131
1132    #[inline]
1133    fn is_zero(&self) -> bool {
1134        self.is_zero()
1135    }
1136}
1137
1138#[cfg(feature = "num-traits")]
1139impl MulAdd for Decimal64 {
1140    type Output = Self;
1141
1142    fn mul_add(self, a: Self, b: Self) -> Self::Output {
1143        Context::<Self>::default().fma(self, a, b)
1144    }
1145}
1146
1147#[cfg(feature = "num-traits")]
1148impl MulAddAssign for Decimal64 {
1149    #[inline]
1150    fn mul_add_assign(&mut self, a: Self, b: Self) {
1151        *self = self.mul_add(a, b)
1152    }
1153}