decmathlib_rs/
d128.rs

1/* -------------------------------------------------------------------------------------------------- */
2/* Port of the Intel Decimal Floating-Point Math Library decimal128 type to Rust.                     */
3/* decmathlib-rs - Copyright (C) 2023-2024 Carlos Guzmán Álvarez                                      */
4/* -------------------------------------------------------------------------------------------------- */
5/* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
6/* -------------------------------------------------------------------------------------------------- */
7/* Intel® Decimal Floating-Point Math Library - Copyright (c) 2018, Intel Corp.                       */
8/* -------------------------------------------------------------------------------------------------- */
9
10#![allow(non_camel_case_types)]
11
12//! A 128-bit decimal floating point type (IEEE Standard 754-2008 compliant).
13
14use std::cmp::Ordering;
15use std::fmt::{Debug, Display, Formatter, LowerExp, UpperExp};
16use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign};
17use std::str::FromStr;
18use forward_ref::{forward_ref_binop, forward_ref_op_assign, forward_ref_unop};
19
20use crate::bid128_add::{bid128_add, bid128_sub};
21use crate::bid128_compare::*;
22use crate::bid128_div::bid128_div;
23use crate::bid128_fdim::bid128_fdim;
24use crate::bid128_fma::bid128_fma;
25use crate::bid128_fmod::bid128_fmod;
26use crate::bid128_frexp::bid128_frexp;
27use crate::bid128_ilogb::bid128_ilogb;
28use crate::bid128_ldexp::bid128_ldexp;
29use crate::bid128_llquantexp::bid128_llquantexp;
30use crate::bid128_llrint::bid128_llrint;
31use crate::bid128_llround::bid128_llround;
32use crate::bid128_logb::bid128_logb;
33use crate::bid128_lrint::bid128_lrint;
34use crate::bid128_lround::bid128_lround;
35use crate::bid128_minmax::{bid128_maxnum, bid128_maxnum_mag, bid128_minnum, bid128_minnum_mag};
36use crate::bid128_modf::bid128_modf;
37use crate::bid128_mul::bid128_mul;
38use crate::bid128_nearbyint::bid128_nearbyint;
39use crate::bid128_next::{bid128_nextafter, bid128_nextdown, bid128_nextup};
40use crate::bid128_nexttoward::bid128_nexttoward;
41use crate::bid128_noncomp::*;
42use crate::bid128_quantexp::bid128_quantexp;
43use crate::bid128_quantize::bid128_quantize;
44use crate::bid128_quantum::bid128_quantum;
45use crate::bid128_rem::bid128_rem;
46use crate::bid128_round_integral::*;
47use crate::bid128_scalbln::bid128_scalbln;
48use crate::bid128_scalbn::bid128_scalbn;
49use crate::bid128_sqrt::bid128_sqrt;
50use crate::bid128_string::{bid128_from_string, bid128_to_string};
51use crate::bid128_to_int32::*;
52use crate::bid128_to_int64::*;
53use crate::bid128_to_uint32::*;
54use crate::bid128_to_uint64::*;
55use crate::bid_binarydecimal::{binary32_to_bid128, binary64_to_bid128};
56use crate::bid_dpd::{bid_dpd_to_bid128, bid_to_dpd128};
57use crate::bid_from_int::{bid128_from_int32, bid128_from_int64, bid128_from_uint32, bid128_from_uint64};
58use crate::bid_internal::*;
59
60/// A classification of decimal floating point numbers.
61#[derive(Clone, Copy, Debug, PartialEq, Eq)]
62pub enum ClassTypes {
63    /// Signaling NaN (not a number).
64    SignalingNaN,
65
66    /// Quiet NaN (not a number).
67    QuietNaN,
68
69    /// Negative infinity.
70    NegativeInfinity,
71
72    /// Negative normal.
73    NegativeNormal,
74
75    /// Negative subnormal.
76    NegativeSubnormal,
77
78    /// Negative zero.
79    NegativeZero,
80
81    /// Positive zero.
82    PositiveZero,
83
84    /// Positive subnormal.
85    PositiveSubnormal,
86
87    /// Positive normal.
88    PositiveNormal,
89
90    /// Positive infinity.
91    PositiveInfinity
92}
93
94/// Rounding mode.
95#[derive(Copy, Clone, Debug, PartialEq)]
96pub enum RoundingMode {
97    /// Rounding towards nearest representable value.
98    NearestEven = 0x00000,
99
100    /// Rounding towards negative infinity.
101    Downward = 0x00001,
102
103    /// Rounding towards positive infinity.
104    Upward = 0x00002,
105
106    /// Rounding towards zero.
107    TowardZero = 0x00003,
108
109    /// Rounding towards the nearest value, breaks ties by rounding away from zero.
110    NearestAway = 0x00004
111}
112
113impl From<u32> for RoundingMode {
114    fn from(value: u32) -> Self {
115        match value {
116            0x00000 => RoundingMode::NearestEven,
117            0x00001 => RoundingMode::Downward,
118            0x00002 => RoundingMode::Upward,
119            0x00003 => RoundingMode::TowardZero,
120            0x00004 => RoundingMode::NearestAway,
121            _ => panic!("Unknown rounding mode")
122        }
123    }
124}
125
126pub const DEFAULT_ROUNDING_MODE: RoundingMode = RoundingMode::NearestEven;
127
128/// Status flags.
129pub struct StatusFlags;
130
131// BID_FPSC
132pub type _IDEC_flags = u32;
133
134impl StatusFlags {
135    pub const BID_INEXACT_EXCEPTION: _IDEC_flags            = DEC_FE_INEXACT;
136    pub const BID_UNDERFLOW_EXCEPTION: _IDEC_flags          = DEC_FE_UNDERFLOW;
137    pub const BID_OVERFLOW_EXCEPTION: _IDEC_flags           = DEC_FE_OVERFLOW;
138    pub const BID_ZERO_DIVIDE_EXCEPTION: _IDEC_flags        = DEC_FE_DIVBYZERO;
139    pub const BID_DENORMAL_EXCEPTION: _IDEC_flags           = DEC_FE_UNNORMAL;
140    pub const BID_INVALID_EXCEPTION: _IDEC_flags            = DEC_FE_INVALID;
141    pub const BID_UNDERFLOW_INEXACT_EXCEPTION: _IDEC_flags  = DEC_FE_UNDERFLOW | DEC_FE_INEXACT;
142    pub const BID_OVERFLOW_INEXACT_EXCEPTION: _IDEC_flags   = DEC_FE_OVERFLOW | DEC_FE_INEXACT;
143    pub const BID_EXACT_STATUS:_IDEC_flags                  = 0x00000000;
144}
145
146/// The 128-bit decimal type.
147#[derive(Copy, Clone)]
148#[repr(align(16))]
149pub struct d128 {
150    pub (crate) w: [BID_UINT64; 2]
151}
152
153/// The radix or base of the internal representation of `d128`.
154pub const RADIX: i32 = 10;
155
156/// The number minus one (-1).
157pub const MINUS_ONE: d128 = d128 { w: [0x0000000000000001u64, 0xb040000000000000u64] };
158
159/// The number zero (0).
160pub const ZERO: d128 = d128 { w: [0x0000000000000000u64, 0x3040000000000000u64] };
161
162/// The number one (1).
163pub const ONE: d128 = d128 { w: [0x0000000000000001u64, 0x3040000000000000u64] };
164
165/// Not a Number (NaN).
166pub const NAN: d128 = d128 { w: [0x0000000000000000u64, 0x7c00000000000000u64] };
167
168/// Negative Not a Number (Nan).
169pub const NEG_NAN: d128 = d128 { w: [0x0000000000000000u64, 0xFC00000000000000u64] };
170
171/// Signaling Not a Number (Nan).
172pub const SNAN: d128 = d128 { w: [0x0000000000000000u64, 0x7E00000000000000u64] };
173
174/// Negative signaling Not a Number (Nan).
175pub const NEG_SNAN: d128 = d128 { w: [0x0000000000000000u64, 0xFE00000000000000u64] };
176
177/// Infinity.
178pub const INFINITY: d128 = d128 { w: [0x0000000000000000u64, 0x7800000000000000u64] };
179
180/// Negative Infinity.
181pub const NEGATIVE_INFINITY: d128 = d128 { w: [0x0000000000000000u64, 0xF800000000000000u64] };
182
183/// The number of digits in the coefficient.
184pub const MANTISSA_DIGITS: u32 = BID128_MAXDIGITS;
185
186/// The difference between 1 and the least value greater than 1 that is representable in the given floating point type (1E-33).
187pub const EPSILON: d128 = d128 { w: [0x1u64, 0x2FFE000000000000u64] };
188
189/// Smallest finite value (1E-6143).
190pub const MIN: d128 = d128 { w: [0x1u64, 0x42000000000000u64] };
191
192/// Largest finite value (9.999999999999999999999999999999999E6144).
193pub const MAX: d128 = d128 { w: [0x378D8E63FFFFFFFFu64, 0x5FFFED09BEAD87C0u64] };
194
195/// The minimum exponent.
196pub const MIN_EXP: i32 = -6142;
197
198/// The maximum exponent.
199pub const MAX_EXP: i32 = 6145;
200
201/// Macro to simplify the creation of instances of 128-bit decimal floating point numbers.
202#[macro_export]
203macro_rules! dec128 {
204    ($t:tt) => {{
205        use std::str::FromStr;
206        $crate::d128::d128::from_str(stringify!($t)).expect("Invalid decimal number literal")
207    }}
208}
209
210impl Default for d128 {
211    /// Returns the default value of 0.
212    #[must_use]
213    fn default() -> Self {
214        Self::new(0x3040000000000000u64, 0x0)
215    }
216}
217
218impl d128 {
219    #[must_use]
220    pub (crate) fn new(h: u64, l: u64) -> Self {
221        #[cfg(target_endian = "big")]
222        return Self { w: [h, l] };
223
224        Self { w: [l, h] }
225    }
226
227    /// Convert a 128-bit decimal floating-point value encoded in BID format
228    /// to the same value encoded in DPD
229    pub fn encode_decimal(&self) -> Self {
230        bid_to_dpd128(self)
231    }
232
233    /// Convert a 128-bit decimal floating-point value encoded in DPD format
234    /// to the same value encoded in BID format
235    pub fn decode_decimal(&self) -> Self {
236        bid_dpd_to_bid128(self)
237    }
238
239    /// Copies a 128-bit decimal floating-point operand x to a destination in the same format, changing the sign to positive
240    #[must_use]
241    pub fn abs(&self) -> Self {
242        bid128_abs(self)
243    }
244
245    /// Tells which of the following ten classes x falls into (details in the IEEE Standard 754-2008):
246    /// signalingNaN, quietNaN, negativeInfinity, negativeNormal, negativeSubnormal, negativeZero, positiveZero,
247    /// positiveSubnormal, positiveNormal, positiveInfinity
248    #[must_use]
249    pub fn class(&self) -> ClassTypes {
250        bid128_class(self)
251    }
252
253    /// Copies a decimal floating-point operand x to a destination in the same format, with no change
254    #[must_use]
255    pub fn copy(&self) -> Self { bid128_copy(self) }
256
257    /// Copies a 128-bit decimal floating-point operand x to a destination in the same format as x, but with the sign of y
258    #[must_use]
259    pub fn copy_sign(&self, other: &Self) -> Self { bid128_copy_sign(self, other) }
260
261    /// Return true if and only if x is a finite number, infinity, or NaN that is canonical
262    #[must_use]
263    pub fn is_canonical(&self) -> bool {
264        bid128_is_canonical(self)
265    }
266
267    /// Return true if and only if x is zero, subnormal or normal (not infinite or NaN)
268    #[must_use]
269    pub fn is_finite(&self) -> bool {
270        bid128_is_finite(self)
271    }
272
273    /// Return true if and only if x is infinite
274    #[must_use]
275    pub fn is_infinite(&self) -> bool {
276        bid128_is_inf(self)
277    }
278
279    /// Return true if and only if x is a NaN
280    #[must_use]
281    pub fn is_nan(&self) -> bool {
282        bid128_is_nan(self)
283    }
284
285    /// Return true if and only if x is normal (not zero, subnormal, infinite, or NaN)
286    #[must_use]
287    pub fn is_normal(&self) -> bool {
288        bid128_is_normal(self)
289    }
290
291    /// Return true if and only if x is a signaling NaN
292    #[must_use]
293    pub fn is_signaling(&self) -> bool {
294        bid128_is_signaling(self)
295    }
296
297    /// Return true if and only if x has negative sign
298    #[must_use]
299    pub fn is_sign_minus(&self) -> bool {
300        bid128_is_signed(self)
301    }
302
303    /// Return true if and only if x is subnormal
304    #[must_use]
305    pub fn is_subnormal(&self) -> bool {
306        bid128_is_subnormal(self)
307    }
308
309    /// Return true if and only if x is +0 or -0
310    #[must_use]
311    pub fn is_zero(&self) -> bool {
312        bid128_is_zero(self)
313    }
314
315    /// Copies a 128-bit decimal floating-point operand x to a destination
316    /// in the same format, reversing the sign
317    #[must_use]
318    pub fn negate(x: &Self) -> Self {
319        bid128_negate(x)
320    }
321
322    /// `same_quantum` is true if the exponents of x and y are the same,
323    /// and false otherwise; `same_quantum(NaN, NaN)` and `same_quantum(inf, inf)` are
324    /// true; if exactly one operand is infinite or exactly one operand is NaN,
325    /// sameQuantum is false
326    #[must_use]
327    pub fn same_quantum(x: &Self, y: &Self) -> bool {
328        bid128_same_quantum(x, y)
329    }
330
331    /// Return true if the absolute values of x and y are ordered (see the IEEE Standard 754-2008)
332    #[must_use]
333    pub fn total_order(x: &Self, y: &Self) -> bool {
334        bid128_total_order(x, y)
335    }
336
337    /// Return true if the absolute values of x and y are ordered (see the IEEE Standard 754-2008)
338    #[must_use]
339    pub fn total_order_mag(x: &Self, y: &Self) -> bool {
340        bid128_total_order_mag(x, y)
341    }
342
343    #[must_use]
344    pub fn nan(tagp: &str, pfpsf: &mut _IDEC_flags) -> BID_UINT128 {
345        bid128_nan(tagp, pfpsf)
346    }
347
348    /// Convert a decimal floating-point value represented in string format
349    /// (decimal character sequence) to 128-bit decimal floating-point format (binary encoding)
350    #[must_use]
351    pub fn convert_from_decimal_character(value: &str, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
352        bid128_from_string(value, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
353    }
354
355    /// Convert 32-bit binary floating-point value to 128-bit decimal
356    /// floating-point format (binary encoding)
357    #[must_use]
358    pub fn convert_from_f32(value: f32, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
359        binary32_to_bid128(value, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
360    }
361
362    /// Convert 64-bit binary floating-point value to 128-bit decimal
363    /// floating-point format (binary encoding)
364    #[must_use]
365    pub fn convert_from_f64(value: f64, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
366        binary64_to_bid128(value, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
367    }
368
369    /// fdim returns x - y if x > y, and +0 is x <= y
370    #[must_use]
371    pub fn fdim(&self, rhs: &BID_UINT128, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
372        bid128_fdim(self, rhs, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
373    }
374
375    /// Computes x * y + z as if to infinite precision and rounded only once to fit the result type.
376    #[must_use]
377    pub fn fused_multiply_add(x: &Self, y: &Self, z: &Self, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
378        bid128_fma(x, y, z, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
379    }
380
381    /// Computes the decimal floating point remainder of the division operation x / y.
382    #[must_use]
383    pub fn fmod(&self, rhs: &BID_UINT128, pfpsf: &mut _IDEC_flags) -> Self {
384        bid128_fmod(self, rhs, pfpsf)
385    }
386
387    /// Decomposes given decimal floating point value num into a normalized fraction and an integral power of two.
388    #[must_use]
389    pub fn frexp(&self) -> (Self, i32) {
390        bid128_frexp(self)
391    }
392
393    /// multiply a 128-bit decimal floating-point value by an integral power of 2.
394    #[must_use]
395    pub fn ldexp(&self, n: i32, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
396        bid128_ldexp(self, n, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
397    }
398
399    /// The `llquantexp()` functions return the quantum exponent of x.
400    #[must_use]
401    pub fn llquantexp(&self, pfpsf: &mut _IDEC_flags) -> i64 {
402        bid128_llquantexp(self, pfpsf)
403    }
404
405    /// Returns the exponent e of x, a signed integral value, determined
406    /// as though x were represented with infinite range and minimum exponent
407    #[must_use]
408    pub fn logb(&self, pfpsf: &mut _IDEC_flags) -> Self {
409        bid128_logb(self, pfpsf)
410    }
411
412    /// The lrint function rounds its argument to the nearest integer value of
413    /// type long int, rounding according to the current rounding direction.
414    #[must_use]
415    pub fn lrint(&self, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> i64 {
416        bid128_lrint(self, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
417    }
418
419    /// The llrint function rounds its argument to the nearest integer value of
420    /// type long long int, rounding according to the current rounding direction.
421    #[must_use]
422    pub fn llrint(&self, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> i64 {
423        bid128_llrint(self, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
424    }
425
426    /// The lround function rounds its argument to the nearest integer value of
427    /// type long int, using rounding to nearest-away
428    #[must_use]
429    pub fn lround(&self, pfpsf: &mut _IDEC_flags) -> i64 {
430        bid128_lround(self, pfpsf)
431    }
432
433    /// The llround function rounds its argument to the nearest integer value of
434    /// type long int, using rounding to nearest-away
435    #[must_use]
436    pub fn llround(&self, pfpsf: &mut _IDEC_flags) -> i64 {
437        bid128_llround(self, pfpsf)
438    }
439
440    /// Returns the exponent e of x, a signed integral value, determined
441    /// as though x were represented with infinite range and minimum exponent
442    #[must_use]
443    pub fn log_b(&self, pfpsf: &mut _IDEC_flags) -> i32 {
444        bid128_ilogb(self, pfpsf)
445    }
446
447    /// Returns the canonicalized floating-point number y if x < y,
448    /// x if y < x, the canonicalized floating-point number if one operand is a
449    /// floating-point number and the other a quiet NaN.
450    #[must_use]
451    pub fn max_num(x: &Self, y: &Self, pfpsf: &mut _IDEC_flags) -> Self {
452        bid128_maxnum(x, y, pfpsf)
453    }
454
455    /// Returns the canonicalized floating-point number x if |x| > |y|,
456    /// y if |y| > |x|, otherwise this function is identical to `max`
457    #[must_use]
458    pub fn max_num_mag(x: &Self, y: &Self, pfpsf: &mut _IDEC_flags) -> Self {
459        bid128_maxnum_mag(x, y, pfpsf)
460    }
461
462    /// Returns the canonicalized floating-point number x if x < y,
463    /// y if y < x, the canonicalized floating-point number if one operand is
464    /// a floating-point number and the other a quiet NaN. Otherwise it is either x or y, canonicalized.
465    #[must_use]
466    pub fn min_num(x: &Self, y: &Self, pfpsf: &mut _IDEC_flags) -> Self {
467        bid128_minnum(x, y, pfpsf)
468    }
469
470    /// Returns the canonicalized floating-point number x if |x| < |y|,
471    /// y if |y| < |x|, otherwise this function is identical to `min`
472    #[must_use]
473    pub fn min_num_mag(x: &Self, y: &Self, pfpsf: &mut _IDEC_flags) -> Self {
474        bid128_minnum_mag(x, y, pfpsf)
475    }
476
477    /// Decomposes given decimal floating point value num into integral and fractional parts.
478    #[must_use]
479    pub fn modf(&self, pfpsf: &mut _IDEC_flags) -> (Self, Self) {
480        bid128_modf(self, pfpsf)
481    }
482
483    /// Rounds the decimal floating-point value num to an integer value in decicmal floating-point format, using the given rounding mode.
484    #[must_use]
485    pub fn nearbyint(&self, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
486        bid128_nearbyint(self, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
487    }
488
489    /// Returns the next 128-bit decimal floating-point number that neighbors
490    /// the first operand in the direction toward the second operand
491    #[must_use]
492    pub fn next_after(x: &Self, y:&Self, pfpsf: &mut _IDEC_flags) -> Self {
493        bid128_nextafter(x, y, pfpsf)
494    }
495
496    /// Returns the greatest 128-bit decimal floating-point number that
497    /// compares less than the operand
498    #[must_use]
499    pub fn next_down(&self, pfpsf: &mut _IDEC_flags) -> Self {
500        bid128_nextdown(self, pfpsf)
501    }
502
503    /// Returns the next representable value after x in the direction of y.
504    #[must_use]
505    pub fn next_toward(x: &Self, y: &Self, pfpsf: &mut _IDEC_flags) -> Self {
506        bid128_nexttoward(x, y, pfpsf)
507    }
508
509    /// Returns the least 128-bit decimal floating-point number that
510    /// compares greater than the operand
511    #[must_use]
512    pub fn next_up(&self, pfpsf: &mut _IDEC_flags) -> Self {
513        bid128_nextup(self, pfpsf)
514    }
515
516    /// The `quantexp()` functions return the quantum exponent of x.
517    #[must_use]
518    pub fn quantexp(&self, pfpsf: &mut _IDEC_flags) -> i32 {
519        bid128_quantexp(self, pfpsf)
520    }
521
522    /// `quantize` is a floating-point number in the same format that
523    /// has, if possible, the same numerical value as x and the same quantum
524    /// (unit-in-the-last-place) as y. If the exponent is being increased, rounding
525    /// according to the prevailing rounding-direction mode might occur: the result
526    /// is a different floating-point representation and inexact is signaled if the
527    /// result does not have the same numerical value as x. If the exponent is being
528    /// decreased and the significand of the result would have more than 34 digits,
529    /// invalid is signaled and the result is NaN. If one or both operands are NaN
530    /// the rules for NaNs are followed. Otherwise if only one operand is
531    /// infinite then invalid is signaled and the result is NaN. If both operands
532    /// are infinite then the result is canonical infinity with the sign of x
533    #[must_use]
534    pub fn quantize(x: &Self, y: &Self, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
535        bid128_quantize(x, y, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
536    }
537
538    /// The `quantum` functions compute the quantum of a finite argument.
539    /// If x is infinite, the result is +Inf. If x is NaN, the result is NaN.
540    #[must_use]
541    pub fn quantum(&self) -> Self {
542        bid128_quantum(self)
543    }
544
545    #[allow(unused)]
546    #[must_use]
547    pub (crate) fn scale(&self) -> i32 {
548        let mut x_exp: BID_UINT64;
549        let mut exp: i32;   // unbiased exponent
550
551        #[cfg(target_endian = "big")]
552        let mut x = *x;
553
554        #[cfg(target_endian = "big")]
555        BID_SWAP128(&mut x);
556
557        // check for NaN or Infinity
558        if ((self.w[1] & MASK_COEFF) == 0x0u64) && (self.w[0] == 0x0u64) {
559            exp = (((self.w[1] & MASK_EXP) >> 49) - 6176) as i32;
560
561            if exp > (((0x5ffe) >> 1) - (6176)) {
562                exp = ((((self.w[1] << 2) & MASK_EXP) >> 49) as i32) - 6176;
563            }
564
565            exp
566        } else { // x is not special and is not zero
567            // unpack x
568            x_exp = self.w[1] & MASK_EXP;             // biased and shifted left 49 bit positions
569
570            if (self.w[1] & 0x6000000000000000u64) == 0x6000000000000000u64 {
571                x_exp = (self.w[1] << 2) & MASK_EXP;   // biased and shifted left 49 bit positions
572            }
573
574            ((x_exp >> 49) - 6176) as i32
575        }
576    }
577
578    /// Returns x * 10^N
579    #[must_use]
580    pub fn scaleb(&self, n: i32, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
581        bid128_scalbn(self, n, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
582    }
583
584    /// Returns x * 10^N
585    #[must_use]
586    pub fn scalebln(&self, n: i64, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
587        bid128_scalbln(self, n, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
588    }
589
590    /// Decimal floating-point square root
591    #[must_use]
592    pub fn square_root(&self, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> Self {
593        bid128_sqrt(self, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
594    }
595
596    /// Convert 128-bit decimal floating-point value to 32-bit signed
597    /// integer in rounding-to-nearest-even mode; inexact exceptions not signaled
598    #[must_use]
599    pub fn convert_to_i32_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> i32 {
600        bid128_to_int32_rnint(self, pfpsf)
601    }
602
603    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
604    /// in rounding-to-nearest-even mode; inexact exceptions signaled
605    #[must_use]
606    pub fn convert_to_i32_exact_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> i32 {
607        bid128_to_int32_xrnint(self, pfpsf)
608    }
609
610    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
611    /// in rounding-down mode; inexact exceptions not signaled
612    #[must_use]
613    pub fn convert_to_i32_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> i32 {
614        bid128_to_int32_floor(self, pfpsf)
615    }
616
617    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
618    /// in rounding-down mode; inexact exceptions signaled
619    #[must_use]
620    pub fn convert_to_i32_exact_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> i32 {
621        bid128_to_int32_xfloor(self, pfpsf)
622    }
623
624    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
625    /// in rounding-up mode; inexact exceptions not signaled
626    #[must_use]
627    pub fn convert_to_i32_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> i32 {
628        bid128_to_int32_ceil(self, pfpsf)
629    }
630
631    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
632    /// in rounding-up mode; inexact exceptions signaled
633    #[must_use]
634    pub fn convert_to_i32_exact_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> i32 {
635        bid128_to_int32_xceil(self, pfpsf)
636    }
637
638    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
639    /// in rounding-to-zero; inexact exceptions not signaled
640    #[must_use]
641    pub fn convert_to_i32_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> i32 {
642        bid128_to_int32_int(self, pfpsf)
643    }
644
645    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
646    /// in rounding-to-zero; inexact exceptions signale
647    #[must_use]
648    pub fn convert_to_i32_exact_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> i32 {
649        bid128_to_int32_xint(self, pfpsf)
650    }
651
652    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
653    /// in rounding-to-nearest-away; inexact exceptions not signaled
654    #[must_use]
655    pub fn convert_to_i32_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> i32 {
656        bid128_to_int32_rninta(self, pfpsf)
657    }
658
659    /// Convert 128-bit decimal floating-point value to 32-bit signed integer
660    /// in rounding-to-nearest-away; inexact exceptions signaled
661    #[must_use]
662    pub fn convert_to_i32_exact_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> i32 {
663        bid128_to_int32_xrninta(self, pfpsf)
664    }
665
666    /// Convert 128-bit decimal floating-point value to 64-bit signed integer
667    /// in rounding-up mode; inexact exceptions not signaled
668    #[must_use]
669    pub fn convert_to_i64_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> i64 {
670        bid128_to_int64_ceil(self, pfpsf)
671    }
672
673    /// Convert 128-bit decimal floating-point value to 64-bit signed integer
674    /// in rounding-down mode; inexact exceptions not signaled
675    #[must_use]
676    pub fn convert_to_i64_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> i64 {
677        bid128_to_int64_floor(self, pfpsf)
678    }
679
680    /// Convert 128-bit decimal floating-point value to 64-bit signed integer
681    /// in rounding-to-zero; inexact exceptions not signaled
682    #[must_use]
683    pub fn convert_to_i64_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> i64 {
684        bid128_to_int64_int(self, pfpsf)
685    }
686
687    /// Convert 128-bit decimal floating-point value to 64-bit signed
688    /// integer in rounding-to-nearest-even mode; inexact exceptions not signaled
689    #[must_use]
690    pub fn convert_to_i64_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> i64 {
691        bid128_to_int64_rnint(self, pfpsf)
692    }
693
694    /// Convert 128-bit decimal floating-point value to 64-bit signed
695    /// integer in rounding-to-nearest-away; inexact exceptions not signaled
696    #[must_use]
697    pub fn convert_to_i64_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> i64 {
698        bid128_to_int64_rninta(self, pfpsf)
699    }
700
701    /// Convert 128-bit decimal floating-point value to 64-bit signed integer
702    /// in rounding-up mode; inexact exceptions signaled
703    #[must_use]
704    pub fn convert_to_i64_exact_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> i64 {
705        bid128_to_int64_xceil(self, pfpsf)
706    }
707
708    /// Convert 128-bit decimal floating-point value to 64-bit signed integer
709    /// in rounding-down mode; inexact exceptions signaled
710    #[must_use]
711    pub fn convert_to_i64_exact_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> i64 {
712        bid128_to_int64_xfloor(self, pfpsf)
713    }
714
715    /// Convert 128-bit decimal floating-point value to 64-bit signed integer
716    /// in rounding-to-zero; inexact exceptions signaled
717    #[must_use]
718    pub fn convert_to_i64_exact_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> i64 {
719        bid128_to_int64_xint(self, pfpsf)
720    }
721
722    /// Convert 128-bit decimal floating-point value to 64-bit signed
723    /// integer in rounding-to-nearest-even mode; inexact exceptions signaled
724    #[must_use]
725    pub fn convert_to_i64_exact_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> i64 {
726        bid128_to_int64_xrnint(self, pfpsf)
727    }
728
729    /// Convert 128-bit decimal floating-point value to 64-bit signed
730    /// integer in rounding-to-nearest-away; inexact exceptions signaled
731    #[must_use]
732    pub fn convert_to_i64_exact_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> i64 {
733        bid128_to_int64_xrninta(self, pfpsf)
734    }
735
736    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
737    /// integer in rounding-up mode; inexact exceptions not signaled
738    #[must_use]
739    pub fn convert_to_u32_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> u32 {
740        bid128_to_uint32_ceil(self, pfpsf)
741    }
742
743    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
744    /// integer in rounding-down mode; inexact exceptions not signaled
745    #[must_use]
746    pub fn convert_to_u32_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> u32 {
747        bid128_to_uint32_floor(self, pfpsf)
748    }
749
750    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
751    /// integer in rounding-to-zero; inexact exceptions not signaled
752    #[must_use]
753    pub fn convert_to_u32_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> u32 {
754        bid128_to_uint32_int(self, pfpsf)
755    }
756
757    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
758    /// integer in rounding-to-nearest-even mode; inexact exceptions not signaled
759    #[must_use]
760    pub fn convert_to_u32_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> u32 {
761        bid128_to_uint32_rnint(self, pfpsf)
762    }
763
764    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
765    /// integer in rounding-to-nearest-away; inexact exceptions not signaled
766    #[must_use]
767    pub fn convert_to_u32_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> u32 {
768        bid128_to_uint32_rninta(self, pfpsf)
769    }
770
771    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
772    /// integer in rounding-up mode; inexact exceptions signaled
773    #[must_use]
774    pub fn convert_to_u32_exact_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> u32 {
775        bid128_to_uint32_xceil(self, pfpsf)
776    }
777
778    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
779    /// integer in rounding-down mode; inexact exceptions signaled
780    #[must_use]
781    pub fn convert_to_u32_exact_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> u32 {
782        bid128_to_uint32_xfloor(self, pfpsf)
783    }
784
785    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
786    /// integer in rounding-to-zero; inexact exceptions signaled
787    #[must_use]
788    pub fn convert_to_u32_exact_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> u32 {
789        bid128_to_uint32_xint(self, pfpsf)
790    }
791
792    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
793    /// integer in rounding-to-nearest-even mode; inexact exceptions signaled
794    #[must_use]
795    pub fn convert_to_u32_exact_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> u32 {
796        bid128_to_uint32_xrnint(self, pfpsf)
797    }
798
799    /// Convert 128-bit decimal floating-point value to 32-bit unsigned
800    /// integer in rounding-to-nearest-away; inexact exceptions signaled
801    #[must_use]
802    pub fn convert_to_u32_exact_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> u32 {
803        bid128_to_uint32_xrninta(self, pfpsf)
804    }
805
806    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
807    /// integer in rounding-up mode; inexact exceptions not signaled
808    #[must_use]
809    pub fn convert_to_u64_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> u64 {
810        bid128_to_uint64_ceil(self, pfpsf)
811    }
812
813    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
814    /// integer in rounding-down mode; inexact exceptions not signaled
815    #[must_use]
816    pub fn convert_to_u64_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> u64 {
817        bid128_to_uint64_floor(self, pfpsf)
818    }
819
820    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
821    /// integer in rounding-to-zero; inexact exceptions not signaled
822    #[must_use]
823    pub fn convert_to_u64_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> u64 {
824        bid128_to_uint64_int(self, pfpsf)
825    }
826
827    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
828    /// integer in rounding-to-nearest-even mode; inexact exceptions not signaled
829    #[must_use]
830    pub fn convert_to_u64_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> u64 {
831        bid128_to_uint64_rnint(self, pfpsf)
832    }
833
834    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
835    /// integer in rounding-to-nearest-away; inexact exceptions not signaled
836    #[must_use]
837    pub fn convert_to_u64_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> u64 {
838        bid128_to_uint64_rninta(self, pfpsf)
839    }
840
841    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
842    /// integer in rounding-up mode; inexact exceptions signaled
843    #[must_use]
844    pub fn convert_to_u64_exact_toward_positive(&self, pfpsf: &mut _IDEC_flags) -> u64 {
845        bid128_to_uint64_xceil(self, pfpsf)
846    }
847
848    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
849    /// integer in rounding-down mode; inexact exceptions signaled
850    #[must_use]
851    pub fn convert_to_u64_exact_toward_negative(&self, pfpsf: &mut _IDEC_flags) -> u64 {
852        bid128_to_uint64_xfloor(self, pfpsf)
853    }
854
855    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
856    /// integer in rounding-to-zero; inexact exceptions signaled
857    #[must_use]
858    pub fn convert_to_u64_exact_toward_zero(&self, pfpsf: &mut _IDEC_flags) -> u64 {
859        bid128_to_uint64_xint(self, pfpsf)
860    }
861
862    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
863    /// integer in rounding-to-nearest-even mode; inexact exceptions signaled
864    #[must_use]
865    pub fn convert_to_u64_exact_ties_to_even(&self, pfpsf: &mut _IDEC_flags) -> u64 {
866        bid128_to_uint64_xrnint(self, pfpsf)
867    }
868
869    /// Convert 128-bit decimal floating-point value to 64-bit unsigned
870    /// integer in rounding-to-nearest-away; inexact exceptions signaled
871    #[must_use]
872    pub fn convert_to_u64_exact_ties_to_away(&self, pfpsf: &mut _IDEC_flags) -> u64 {
873        bid128_to_uint64_xrninta(self, pfpsf)
874    }
875
876    /// Decimal floating-point addition, d128 + d128 -> d128
877    #[must_use]
878    pub fn addition(lhs: &Self, rhs: &Self, rnd_mode: Option<RoundingMode>, status: &mut _IDEC_flags) -> Self {
879        bid128_add(lhs, rhs, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), status)
880    }
881
882    /// Decimal floating-point division, d128 / d128 -> d128
883    #[must_use]
884    pub fn division(lhs: &Self, rhs: &Self, rnd_mode: Option<RoundingMode>, status: &mut _IDEC_flags) -> Self {
885        bid128_div(lhs, rhs, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), status)
886    }
887
888    /// Decimal floating-point multiplication, d128 / d128 -> d128
889    #[must_use]
890    pub fn multiplication(lhs: &Self, rhs: &Self, rnd_mode: Option<RoundingMode>, status: &mut _IDEC_flags) -> Self {
891        bid128_mul(lhs, rhs, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), status)
892    }
893
894    /// Decimal floating-point remainder
895    #[must_use]
896    pub fn remainder(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> Self {
897        bid128_rem(lhs, rhs, status)
898    }
899
900    /// Decimal floating-point subtraction, d128 - d128 -> d128
901    #[must_use]
902    pub fn subtraction(lhs: &Self, rhs: &Self, rnd_mode: Option<RoundingMode>, status: &mut _IDEC_flags) -> Self {
903        bid128_sub(lhs, rhs, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), status)
904    }
905
906    /// Compare 128-bit decimal floating-point numbers for specified relation;
907    /// do not signal invalid exception for quiet NaNs
908    #[must_use]
909    pub fn compare_quiet_equal(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
910        bid128_quiet_equal(lhs, rhs, status)
911    }
912
913    /// Compare 128-bit decimal floating-point numbers for specified relation;
914    /// do not signal invalid exception for quiet NaNs
915    #[must_use]
916    pub fn compare_quiet_greater(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
917        bid128_quiet_greater(lhs, rhs, status)
918    }
919
920    /// Compare 128-bit decimal floating-point numbers for specified relation;
921    /// do not signal invalid exception for quiet NaNs
922    #[must_use]
923    pub fn compare_quiet_unordered(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
924        bid128_quiet_unordered(lhs, rhs, status)
925    }
926
927    /// Compare 128-bit decimal floating-point numbers for specified relation;
928    /// do not signal invalid exception for quiet NaNs
929    #[must_use]
930    pub fn compare_quiet_ordered(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
931        bid128_quiet_ordered(lhs, rhs, status)
932    }
933
934    /// Compare 128-bit decimal floating-point numbers for specified relation;
935    /// do not signal invalid exception for quiet NaNs
936    #[must_use]
937    pub fn compare_quiet_greater_equal(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
938        bid128_quiet_greater_equal(lhs, rhs, status)
939    }
940
941    /// Compare 128-bit decimal floating-point numbers for specified relation;
942    /// do not signal invalid exception for quiet NaNs
943    #[must_use]
944    pub fn compare_quiet_greater_unordered(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
945        bid128_quiet_greater_unordered(lhs, rhs, status)
946    }
947
948    /// Compare 128-bit decimal floating-point numbers for specified relation;
949    /// do not signal invalid exception for quiet NaNs
950    #[must_use]
951    pub fn compare_quiet_less(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
952        bid128_quiet_less(lhs, rhs, status)
953    }
954
955    /// Compare 128-bit decimal floating-point numbers for specified relation;
956    /// do not signal invalid exception for quiet NaNs
957    #[must_use]
958    pub fn compare_quiet_less_equal(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
959        bid128_quiet_less_equal(lhs, rhs, status)
960    }
961
962    /// Compare 128-bit decimal floating-point numbers for specified relation;
963    /// do not signal invalid exception for quiet NaNs
964    #[must_use]
965    pub fn compare_quiet_less_unordered(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
966        bid128_quiet_less_unordered(lhs, rhs, status)
967    }
968
969    /// Compare 128-bit decimal floating-point numbers for specified relation;
970    /// do not signal invalid exception for quiet NaNs
971    #[must_use]
972    pub fn compare_quiet_not_equal(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
973        bid128_quiet_not_equal(lhs, rhs, status)
974    }
975
976    /// Compare 128-bit decimal floating-point numbers for specified relation;
977    /// do not signal invalid exception for quiet NaNs
978    #[must_use]
979    pub fn compare_quiet_not_greater(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
980        bid128_quiet_not_greater(lhs, rhs, status)
981    }
982
983    /// Compare 128-bit decimal floating-point numbers for specified relation;
984    /// do not signal invalid exception for quiet NaNs
985    #[must_use]
986    pub fn compare_quiet_not_less(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
987        bid128_quiet_not_less(lhs, rhs, status)
988    }
989
990    /// Compare 128-bit decimal floating-point numbers for specified relation;
991    /// do not signal invalid exception for quiet NaNs
992    #[must_use]
993    pub fn compare_signaling_greater(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
994        bid128_signaling_greater(lhs, rhs, status)
995    }
996
997    /// Compare 128-bit decimal floating-point numbers for specified relation;
998    /// do not signal invalid exception for quiet NaNs
999    #[must_use]
1000    pub fn compare_signaling_greater_equal(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
1001        bid128_signaling_greater_equal(lhs, rhs, status)
1002    }
1003
1004    /// Compare 128-bit decimal floating-point numbers for specified relation;
1005    /// do not signal invalid exception for quiet NaNs
1006    #[must_use]
1007    pub fn compare_signaling_greater_unordered(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
1008        bid128_signaling_greater_unordered(lhs, rhs, status)
1009    }
1010
1011    /// Compare 128-bit decimal floating-point numbers for specified relation;
1012    /// do not signal invalid exception for quiet NaNs
1013    #[must_use]
1014    pub fn compare_signaling_less(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
1015        bid128_signaling_less(lhs, rhs, status)
1016    }
1017
1018    /// Compare 128-bit decimal floating-point numbers for specified relation;
1019    /// do not signal invalid exception for quiet NaNs
1020    #[must_use]
1021    pub fn compare_signaling_less_equal(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
1022        bid128_signaling_less_equal(lhs, rhs, status)
1023    }
1024
1025    /// Compare 128-bit decimal floating-point numbers for specified relation;
1026    /// do not signal invalid exception for quiet NaNs
1027    #[must_use]
1028    pub fn compare_signaling_less_unordered(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
1029        bid128_signaling_less_unordered(lhs, rhs, status)
1030    }
1031
1032    /// Compare 128-bit decimal floating-point numbers for specified relation;
1033    /// do not signal invalid exception for quiet NaNs
1034    #[must_use]
1035    pub fn compare_signaling_not_greater(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
1036        bid128_signaling_not_greater(lhs, rhs, status)
1037    }
1038
1039    /// Compare 128-bit decimal floating-point numbers for specified relation;
1040    /// do not signal invalid exception for quiet NaNs
1041    #[must_use]
1042    pub fn compare_signaling_not_less(lhs: &Self, rhs: &Self, status: &mut _IDEC_flags) -> bool {
1043        bid128_signaling_not_less(lhs, rhs, status)
1044    }
1045
1046    /// Round 128-bit decimal floating-point value to integral-valued decimal
1047    /// floating-point value in the same format, using the current rounding mode;
1048    /// signal inexact exceptions
1049    #[must_use]
1050    pub fn round_to_integral_exact(x: &BID_UINT128, rnd_mode: Option<RoundingMode>, pfpsf: &mut _IDEC_flags) -> d128 {
1051        bid128_round_integral_exact(x, rnd_mode.unwrap_or(DEFAULT_ROUNDING_MODE), pfpsf)
1052    }
1053
1054    /// Round 128-bit decimal floating-point value to integral-valued decimal
1055    /// floating-point value in the same format, using the rounding-to-nearest-away mode;
1056    /// do not signal inexact exceptions
1057    #[must_use]
1058    pub fn round_to_integral_ties_to_away(x: &BID_UINT128, pfpsf: &mut _IDEC_flags) -> d128 {
1059        bid128_round_integral_nearest_away(x, pfpsf)
1060    }
1061
1062    /// Round 128-bit decimal floating-point value to integral-valued decimal
1063    /// floating-point value in the same format, using the rounding-to-nearest-even mode;
1064    /// do not signal inexact exceptions
1065    #[must_use]
1066    pub fn round_to_integral_ties_to_even(x: &BID_UINT128, pfpsf: &mut _IDEC_flags) -> d128 {
1067        bid128_round_integral_nearest_even(x, pfpsf)
1068    }
1069
1070    /// Round 128-bit decimal floating-point value to integral-valued decimal
1071    /// floating-point value in the same format, using the rounding-down mode; do not
1072    /// signal inexact exceptions
1073    #[must_use]
1074    pub fn round_to_integral_ties_toward_negative(x: &BID_UINT128, pfpsf: &mut _IDEC_flags) -> d128 {
1075        bid128_round_integral_negative(x, pfpsf)
1076    }
1077
1078    /// Round 128-bit decimal floating-point value to integral-valued decimal
1079    /// floating-point value in the same format, using the rounding-up mode; do not
1080    /// signal inexact exceptions
1081    #[must_use]
1082    pub fn round_to_integral_ties_toward_positive(x: &BID_UINT128, pfpsf: &mut _IDEC_flags) -> d128 {
1083        bid128_round_integral_positive(x, pfpsf)
1084    }
1085
1086    /// Round 128-bit decimal floating-point value to integral-valued decimal
1087    /// floating-point value in the same format, using the rounding-to-zero mode;
1088    /// do not signal inexact exceptions
1089    #[must_use]
1090    pub fn round_to_integral_ties_toward_zero(x: &BID_UINT128, pfpsf: &mut _IDEC_flags) -> d128 {
1091        bid128_round_integral_zero(x, pfpsf)
1092    }
1093}
1094
1095impl Eq for d128 { }
1096
1097impl PartialEq for d128 {
1098    fn eq(&self, other: &Self) -> bool {
1099        let mut status: _IDEC_flags = StatusFlags::BID_EXACT_STATUS;
1100        let s_nan: bool = self.is_nan();
1101        let o_nan: bool = other.is_nan();
1102
1103        if s_nan && o_nan {
1104            bid128_quiet_unordered(self, other, &mut status)
1105        } else if s_nan || o_nan {
1106            bid128_quiet_ordered(self, other, &mut status)
1107        } else {
1108            bid128_quiet_equal(self, other, &mut status)
1109        }
1110    }
1111}
1112
1113impl PartialOrd for d128 {
1114    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1115        let mut status: _IDEC_flags = StatusFlags::BID_EXACT_STATUS;
1116        let equal: bool = self.eq(other);
1117        if equal {
1118            return Some(Ordering::Equal)
1119        }
1120        let less = bid128_quiet_less(self, other, &mut status);
1121        if less {
1122            return Some(Ordering::Less);
1123        }
1124        let greater = bid128_quiet_greater(self, other, &mut status);
1125        if greater {
1126            return Some(Ordering::Greater);
1127        }
1128        None
1129    }
1130
1131    fn lt(&self, other: &Self) -> bool {
1132        let mut status: _IDEC_flags = StatusFlags::BID_EXACT_STATUS;
1133        bid128_quiet_less(self, other, &mut status)
1134    }
1135
1136    fn le(&self, other: &Self) -> bool {
1137        let mut status: _IDEC_flags = StatusFlags::BID_EXACT_STATUS;
1138        bid128_quiet_less_equal(self, other, &mut status)
1139    }
1140
1141    fn gt(&self, other: &Self) -> bool {
1142        let mut status: _IDEC_flags = StatusFlags::BID_EXACT_STATUS;
1143        bid128_quiet_greater(self, other, &mut status)
1144    }
1145
1146    fn ge(&self, other: &Self) -> bool {
1147        let mut status: _IDEC_flags = StatusFlags::BID_EXACT_STATUS;
1148        bid128_quiet_greater_equal(self, other, &mut status)
1149    }
1150}
1151
1152impl Debug for d128 {
1153    fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
1154        bid128_to_string(self, fmt, true)
1155    }
1156}
1157
1158impl Display for d128 {
1159    fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
1160        bid128_to_string(self, fmt, true)
1161    }
1162}
1163
1164impl LowerExp for d128 {
1165    fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
1166        bid128_to_string(self, fmt, false)
1167    }
1168}
1169
1170impl UpperExp for d128 {
1171    fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
1172        bid128_to_string(self, fmt, true)
1173    }
1174}
1175
1176impl FromStr for d128 {
1177    type Err = u32;
1178
1179    /// Converts a decimal string value to decimal128.
1180    /// # Examples
1181    ///
1182    /// ```
1183    /// use std::str::FromStr;
1184    /// let dec1 = decmathlib_rs::d128::d128::from_str("+100000.00000000E6107");
1185    /// ```
1186    fn from_str(s: &str) -> Result<Self, Self::Err> {
1187         let mut status: _IDEC_flags = 0;
1188         let dec: BID_UINT128 = bid128_from_string(s, DEFAULT_ROUNDING_MODE, &mut status);
1189
1190         match status {
1191            StatusFlags::BID_EXACT_STATUS | StatusFlags::BID_INEXACT_EXCEPTION => Ok(dec),
1192            _ => Err(status)
1193         }
1194    }
1195}
1196
1197impl From<f32> for d128 {
1198    /// Converts f32 to decimal128.
1199    /// # Examples
1200    ///
1201    /// ```
1202    /// let value = 1.1f32;
1203    /// let dec1 = decmathlib_rs::d128::d128::from(value);
1204    /// ```
1205    fn from(value: f32) -> Self {
1206        let mut status: _IDEC_flags = 0;
1207        binary32_to_bid128(value, DEFAULT_ROUNDING_MODE, &mut status)
1208    }
1209}
1210
1211impl From<f64> for d128 {
1212    /// Converts f64 to decimal128.
1213    /// # Examples
1214    ///
1215    /// ```
1216    /// let value = 1.1f64;
1217    /// let dec1 = decmathlib_rs::d128::d128::from(value);
1218    /// ```
1219    fn from(value: f64) -> Self {
1220        let mut status: _IDEC_flags = 0;
1221        binary64_to_bid128(value, DEFAULT_ROUNDING_MODE, &mut status)
1222    }
1223}
1224
1225impl From<i32> for d128 {
1226    /// Converts i32 to decimal128.
1227    /// # Examples
1228    ///
1229    /// ```
1230    /// let value = 0;
1231    /// let dec1 = decmathlib_rs::d128::d128::from(value);
1232    /// ```
1233    fn from(value: i32) -> Self {
1234        bid128_from_int32(value)
1235    }
1236}
1237
1238impl From<u32> for d128 {
1239    /// Converts u32 to decimal128.
1240    /// # Examples
1241    ///
1242    /// ```
1243    /// let value = 0;
1244    /// let dec1 = decmathlib_rs::d128::d128::from(value);
1245    /// ```
1246    fn from(value: u32) -> Self {
1247        bid128_from_uint32(value)
1248    }
1249}
1250
1251impl From<i64> for d128 {
1252    /// Converts i64 to decimal128.
1253    /// # Examples
1254    ///
1255    /// ```
1256    /// let value = 0;
1257    /// let dec1 = decmathlib_rs::d128::d128::from(value);
1258    /// ```
1259    fn from(value: i64) -> Self {
1260        bid128_from_int64(value)
1261    }
1262}
1263
1264impl From<u64> for d128 {
1265    /// Converts i64 to decimal128.
1266    /// # Examples
1267    ///
1268    /// ```
1269    /// let value = 0;
1270    /// let dec1 = decmathlib_rs::d128::d128::from(value);
1271    /// ```
1272    fn from(value: u64) -> Self {
1273        bid128_from_uint64(value)
1274    }
1275}
1276
1277impl From<u128> for d128 {
1278    /// Converts an i128 encoded decimal.
1279    /// # Examples
1280    ///
1281    /// ```
1282    /// let dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1283    /// ```
1284    fn from(value: u128) -> Self {
1285        Self::new((value >> 64) as u64, value as u64)
1286    }
1287}
1288
1289impl From<&str> for d128 {
1290    fn from(value: &str) -> Self {
1291        let mut status: _IDEC_flags = StatusFlags::BID_EXACT_STATUS;
1292        bid128_from_string(value, DEFAULT_ROUNDING_MODE, &mut status)
1293    }
1294}
1295
1296impl Neg for d128 {
1297    type Output = Self;
1298
1299    /// Performs the unary - operation
1300    /// # Examples
1301    ///
1302    /// ```
1303    /// use std::ops::Neg;
1304    /// let dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1305    /// let neg1 = -dec1;
1306    /// let neg2 = -&dec1;
1307    /// ```
1308    fn neg(self) -> Self::Output {
1309        bid128_negate(&self)
1310    }
1311}
1312
1313forward_ref_unop! { impl Neg, neg for d128 }
1314
1315impl Add for d128 {
1316    type Output = Self;
1317
1318    /// Performs the + operation.
1319    /// # Examples
1320    ///
1321    /// ```
1322    /// let dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1323    /// let dec2 = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1324    /// let res  = dec1 + dec2;
1325    /// ```
1326    fn add(self, rhs: Self) -> Self::Output {
1327        let mut status: _IDEC_flags = 0;
1328        bid128_add(&self, &rhs, DEFAULT_ROUNDING_MODE, &mut status)
1329    }
1330}
1331
1332forward_ref_binop!(impl Add, add for d128, d128);
1333
1334impl AddAssign for d128 {
1335    /// Performs the += operation.
1336    /// # Examples
1337    ///
1338    /// ```
1339    /// use decmathlib_rs::d128::RoundingMode;
1340    /// let mut dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1341    /// let dec2     = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1342    /// dec1        += dec2;
1343    /// ```
1344    fn add_assign(&mut self, rhs: Self) {
1345        let mut status: _IDEC_flags = 0;
1346        let dec: BID_UINT128 = bid128_add(self, &rhs, DEFAULT_ROUNDING_MODE, &mut status);
1347
1348        self.w[0] = dec.w[0];
1349        self.w[1] = dec.w[1];
1350    }
1351}
1352
1353forward_ref_op_assign! { impl AddAssign, add_assign for d128, d128 }
1354
1355impl Div for d128 {
1356    type Output = Self;
1357
1358    /// Performs the * operation.
1359    /// # Examples
1360    ///
1361    /// ```
1362    /// let dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1363    /// let dec2 = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1364    /// let res  = dec1 / dec2;
1365    /// ```
1366    fn div(self, rhs: Self) -> Self::Output {
1367        let mut status: _IDEC_flags = 0;
1368        bid128_div(&self, &rhs, DEFAULT_ROUNDING_MODE, &mut status)
1369    }
1370}
1371
1372forward_ref_binop!(impl Div, div for d128, d128);
1373
1374impl DivAssign for d128 {
1375    /// Performs the /= operation.
1376    /// # Examples
1377    ///
1378    /// ```
1379    /// use decmathlib_rs::d128::RoundingMode;
1380    /// let mut dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1381    /// let dec2     = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1382    /// dec1        /= dec2;
1383    /// ```
1384    fn div_assign(&mut self, rhs: Self) {
1385        let mut status: _IDEC_flags = 0;
1386        let dec: BID_UINT128 = bid128_div(self, &rhs, DEFAULT_ROUNDING_MODE, &mut status);
1387
1388        self.w[0] = dec.w[0];
1389        self.w[1] = dec.w[1];
1390    }
1391}
1392
1393forward_ref_op_assign! { impl DivAssign, div_assign for d128, d128 }
1394
1395impl Mul for d128 {
1396    type Output = Self;
1397
1398    /// Performs the * operation.
1399    /// # Examples
1400    ///
1401    /// ```
1402    /// let dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1403    /// let dec2 = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1404    /// let res  = dec1 * dec2;
1405    /// ```
1406    fn mul(self, rhs: Self) -> Self::Output {
1407        let mut status: _IDEC_flags = 0;
1408        bid128_mul(&self, &rhs, DEFAULT_ROUNDING_MODE, &mut status)
1409    }
1410}
1411
1412forward_ref_binop!(impl Mul, mul for d128, d128);
1413
1414impl MulAssign for d128 {
1415    /// Performs the *= operation.
1416    /// # Examples
1417    ///
1418    /// ```
1419    /// use decmathlib_rs::d128::RoundingMode;
1420    /// let mut dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1421    /// let dec2     = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1422    /// dec1        *= dec2;
1423    /// ```
1424    fn mul_assign(&mut self, rhs: Self) {
1425        let mut status: _IDEC_flags = 0;
1426        let dec: BID_UINT128 = bid128_mul(self, &rhs, DEFAULT_ROUNDING_MODE, &mut status);
1427
1428        self.w[0] = dec.w[0];
1429        self.w[1] = dec.w[1];
1430    }
1431}
1432
1433forward_ref_op_assign! { impl MulAssign, mul_assign for d128, d128 }
1434
1435impl Rem for d128 {
1436    type Output = Self;
1437
1438    /// Performs the - operation.
1439    /// # Examples
1440    ///
1441    /// ```
1442    /// let dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1443    /// let dec2 = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1444    /// let res  = dec1 % dec2;
1445    /// ```
1446    fn rem(self, rhs: Self) -> Self::Output {
1447        let mut status: _IDEC_flags = 0;
1448        bid128_rem(&self, &rhs, &mut status)
1449    }
1450}
1451
1452forward_ref_binop!(impl Rem, rem for d128, d128);
1453
1454impl RemAssign for d128 {
1455    /// Performs the %= operation.
1456    /// # Examples
1457    ///
1458    /// ```
1459    /// use decmathlib_rs::d128::RoundingMode;
1460    /// let mut dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1461    /// let dec2     = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1462    /// dec1        %= dec2;
1463    /// ```
1464    fn rem_assign(&mut self, rhs: Self) {
1465        let mut status: _IDEC_flags = 0;
1466        let dec: BID_UINT128 = bid128_rem(self, &rhs, &mut status);
1467
1468        self.w[0] = dec.w[0];
1469        self.w[1] = dec.w[1];
1470    }
1471}
1472
1473forward_ref_op_assign! { impl RemAssign, rem_assign for d128, d128 }
1474
1475impl Sub for d128 {
1476    type Output = Self;
1477
1478    /// Performs the - operation.
1479    /// # Examples
1480    ///
1481    /// ```
1482    /// let dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1483    /// let dec2 = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1484    /// let res  = dec1 - dec2;
1485    /// ```
1486    fn sub(self, rhs: Self) -> Self::Output {
1487        let mut status: _IDEC_flags = 0;
1488        bid128_sub(&self, &rhs, DEFAULT_ROUNDING_MODE, &mut status)
1489    }
1490}
1491
1492forward_ref_binop!(impl Sub, sub for d128, d128);
1493
1494impl SubAssign for d128 {
1495    /// Performs the *= operation.
1496    /// # Examples
1497    ///
1498    /// ```
1499    /// use decmathlib_rs::d128::RoundingMode;
1500    /// let mut dec1 = decmathlib_rs::d128::d128::from(0x150a2e0d6728de4e95595bd43d654036u128);
1501    /// let dec2     = decmathlib_rs::d128::d128::from(0xc47aef17e9919a5569aaaf503275e8f4u128);
1502    /// dec1        -= dec2;
1503    /// ```
1504    fn sub_assign(&mut self, rhs: Self) {
1505        let mut status: _IDEC_flags = 0;
1506        let dec: BID_UINT128 = bid128_sub(self, &rhs, DEFAULT_ROUNDING_MODE, &mut status);
1507
1508        self.w[0] = dec.w[0];
1509        self.w[1] = dec.w[1];
1510    }
1511}
1512
1513forward_ref_op_assign! { impl SubAssign, sub_assign for d128, d128 }
1514
1515impl std::iter::Sum for d128 {
1516    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1517        iter.fold(ZERO, |a, b| a + b)
1518    }
1519}
1520
1521impl std::iter::Product for d128 {
1522    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
1523        iter.fold(ONE, |a, b| a * b)
1524    }
1525}
1526
1527impl<'a> std::iter::Sum<&'a d128> for d128 {
1528    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1529        iter.fold(ZERO, |a, b| a + b)
1530    }
1531}
1532
1533impl<'a> std::iter::Product<&'a d128> for d128 {
1534    fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1535        iter.fold(ONE, |a, b| a * b)
1536    }
1537}
1538
1539impl std::hash::Hash for d128 {
1540    /// Computes the hash of a decimal floating point number.
1541    /// ```
1542    /// use std::hash::{DefaultHasher, Hash, Hasher};
1543    ///
1544    /// let mut hasher = DefaultHasher::new();
1545    /// decmathlib_rs::dec128!(7920).hash(&mut hasher);
1546    /// assert_eq!(6912922690305470905, hasher.finish());
1547    /// ```
1548    #[inline]
1549    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1550        state.write_u64(self.w[0]);
1551        state.write_u64(self.w[1]);
1552    }
1553
1554    /// Computes the hash of a sequence of decimal floating point numbers.
1555    /// ```
1556    /// use std::hash::{DefaultHasher, Hash, Hasher};
1557    ///
1558    /// let mut hasher = DefaultHasher::new();
1559    /// let numbers = [decmathlib_rs::dec128!(6), decmathlib_rs::dec128!(28), decmathlib_rs::dec128!(496), decmathlib_rs::dec128!(8128)];
1560    /// Hash::hash_slice(&numbers, &mut hasher);
1561    /// assert_eq!(16555189424726162492, hasher.finish());
1562    /// ```
1563    #[inline]
1564    fn hash_slice<H: std::hash::Hasher>(data: &[d128], state: &mut H) {
1565        let newlen: usize  = std::mem::size_of_val(data);
1566        let ptr: *const u8 = data.as_ptr() as *const u8;
1567        state.write(unsafe { std::slice::from_raw_parts(ptr, newlen) })
1568    }
1569}