pgnumeric/
var.rs

1// Copyright 2020 CoD Technologies Corp.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! NumericVar.
16
17use crate::binary::{
18    NumericDigit, NUMERIC_DIGIT_SIZE, NUMERIC_DSCALE_MAX, NUMERIC_HEADER_NDIGITS, NUMERIC_NAN,
19    NUMERIC_NEG, NUMERIC_POS, NUMERIC_WEIGHT_MAX, NUMERIC_WEIGHT_MIN, VAR_HEADER_SIZE,
20};
21use crate::data::{NumericData, NumericDigits};
22use crate::num::{NumericBuf, DIVIDE_BY_ZERO_MSG};
23use crate::typmod::Typmod;
24use lazy_static::lazy_static;
25use std::borrow::Cow;
26use std::convert::{TryFrom, TryInto};
27use std::f64::consts::{LN_10, LOG10_2, LOG10_E};
28use std::fmt;
29
30/// Limit on the precision (and hence scale) specifiable in a NUMERIC typmod.
31/// Note that the implementation limit on the length of a numeric value is
32/// much larger --- beware of what you use this for!
33pub const NUMERIC_MAX_PRECISION: i32 = 1000;
34
35// Internal limits on the scales chosen for calculation results
36const NUMERIC_MAX_DISPLAY_SCALE: i32 = NUMERIC_MAX_PRECISION;
37const NUMERIC_MIN_DISPLAY_SCALE: i32 = 0;
38
39const NUMERIC_MAX_RESULT_SCALE: i32 = NUMERIC_MAX_PRECISION * 2;
40
41/// For inherently inexact calculations such as division and square root,
42/// we try to get at least this many significant digits; the idea is to
43/// deliver a result no worse than f64 would.
44const NUMERIC_MIN_SIG_DIGITS: i32 = 16;
45
46pub const NBASE: i32 = 10000;
47const HALF_NBASE: NumericDigit = 5000;
48pub const DEC_DIGITS: i32 = 4;
49const MUL_GUARD_DIGITS: i32 = 2;
50const DIV_GUARD_DIGITS: i32 = 4;
51
52const ROUND_POWERS: [NumericDigit; 4] = [0, 1000, 100, 10];
53
54lazy_static! {
55    // 0
56    static ref ZERO: NumericVar<'static> = NumericVar::zero();
57    // 1
58    static ref ONE: NumericVar<'static> = NumericVar::borrowed(1, 0, 0, NUMERIC_POS, &[1]);
59    // 2
60    static ref TWO: NumericVar<'static> = NumericVar::borrowed(1, 0, 0, NUMERIC_POS, &[2]);
61    // 10
62    static ref TEN: NumericVar<'static> = NumericVar::borrowed(1, 0, 0, NUMERIC_POS, &[10]);
63
64    // 0.5
65    static ref ZERO_POINT_FIVE: NumericVar<'static> = NumericVar::borrowed(1, -1, 1, NUMERIC_POS, &[5000]);
66    // 0.9
67    static ref ZERO_POINT_NINE: NumericVar<'static> = NumericVar::borrowed(1, -1, 1, NUMERIC_POS, &[9000]);
68    // 1.1
69    static ref ONE_POINT_ONE: NumericVar<'static> = NumericVar::borrowed(2, 0, 1, NUMERIC_POS, &[1, 1000]);
70}
71
72/// `NumericVar` is the format we use for arithmetic.  The `digits`-array part
73/// is the same as the `NumericBinary` storage format, but the header is more
74/// complex.
75///
76/// The value represented by a `Numeric` is determined by the `sign`, `weight`,
77/// `ndigits`, and `digits[]` array.
78///
79/// Note: the first digit of a Numeric's value is assumed to be multiplied
80/// by NBASE ** weight.  Another way to say it is that there are weight+1
81/// digits before the decimal point.  It is possible to have weight < 0.
82///
83/// `data.buf` points at the physical start of the digit buffer for the
84/// Numeric. `data.offset` points at the first digit in actual use (the one
85/// with the specified weight).  We normally leave an unused digit or two
86/// (preset to zeroes) between buf and digits, so that there is room to store
87/// a carry out of the top digit without reallocating space.  We just need to
88/// decrement digits (and increment weight) to make room for the carry digit.
89/// (There is no such extra space in a numeric value stored in the database,
90/// only in a Numeric in memory.)
91///
92/// `dscale`, or display scale, is the nominal precision expressed as number
93/// of digits after the decimal point (it must always be >= 0 at present).
94/// dscale may be more than the number of physically stored fractional digits,
95/// implying that we have suppressed storage of significant trailing zeroes.
96/// It should never be less than the number of stored digits, since that would
97/// imply hiding digits that are present.  NOTE that dscale is always expressed
98/// in *decimal* digits, and so it may correspond to a fractional number of
99/// base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
100///
101/// While we consistently use `weight` to refer to the base-NBASE weight of
102/// a numeric value, it is convenient in some scale-related calculations to
103/// make use of the base-10 weight (ie, the approximate log10 of the value).
104/// To avoid confusion, such a decimal-units weight is called a "dweight".
105///
106#[derive(Debug, Clone)]
107pub(crate) struct NumericVar<'a> {
108    ndigits: i32,
109    weight: i32,
110    dscale: i32,
111    sign: u16,
112    digits: Cow<'a, NumericDigits>,
113}
114
115impl<'a> NumericVar<'a> {
116    /// Creates a `NumericVar` with `ndigits` data space.
117    #[inline]
118    fn with_ndigits(ndigits: i32) -> Self {
119        debug_assert!(ndigits >= 0);
120        NumericVar {
121            ndigits,
122            weight: 0,
123            dscale: 0,
124            sign: 0,
125            digits: Cow::Owned(NumericData::with_ndigits(ndigits)),
126        }
127    }
128
129    /// Creates a `NumericVar` of `NaN`, which has no data space.
130    #[inline]
131    pub fn nan() -> Self {
132        NumericVar::borrowed(0, 0, 0, NUMERIC_NAN, &[])
133    }
134
135    /// Creates a `NumericVar` of zero with given scale.
136    #[inline]
137    fn zero_scaled(scale: i32) -> NumericVar<'a> {
138        debug_assert!(scale >= 0 && scale <= NUMERIC_DSCALE_MAX as i32);
139        Self::borrowed(0, 0, scale, NUMERIC_POS, &[])
140    }
141
142    /// Creates a `NumericVar` with borrowed data space.
143    #[inline]
144    pub fn borrowed(
145        ndigits: i32,
146        weight: i32,
147        dscale: i32,
148        sign: u16,
149        digits: &'a [NumericDigit],
150    ) -> Self {
151        debug_assert_eq!(ndigits as usize, digits.len());
152        let digits = Cow::Borrowed(unsafe { NumericDigits::from_slice_unchecked(digits) });
153        NumericVar {
154            ndigits,
155            weight,
156            dscale,
157            sign,
158            digits,
159        }
160    }
161
162    /// Creates a `NumericVar` with given data space.
163    #[inline]
164    pub fn owned(ndigits: i32, weight: i32, dscale: i32, sign: u16, digits: NumericData) -> Self {
165        debug_assert!(digits.offset() + ndigits as u32 <= digits.len());
166        NumericVar {
167            ndigits,
168            weight,
169            dscale,
170            sign,
171            digits: Cow::Owned(digits),
172        }
173    }
174
175    /// Creates a `NumericVar` of zero.
176    #[inline]
177    pub fn zero() -> Self {
178        NumericVar::borrowed(0, 0, 0, NUMERIC_POS, &[])
179    }
180
181    #[inline]
182    pub fn ndigits(&self) -> i32 {
183        self.ndigits
184    }
185
186    #[inline]
187    pub fn weight(&self) -> i32 {
188        self.weight
189    }
190
191    #[inline]
192    pub fn dscale(&self) -> i32 {
193        self.dscale
194    }
195
196    /// Checks if `self` is `NaN`.
197    #[inline]
198    pub const fn is_nan(&self) -> bool {
199        self.sign == NUMERIC_NAN
200    }
201
202    /// Checks if `self` is positive.
203    #[inline]
204    pub const fn is_positive(&self) -> bool {
205        self.sign == NUMERIC_POS
206    }
207
208    /// Checks if `self` is negative.
209    #[inline]
210    pub const fn is_negative(&self) -> bool {
211        self.sign == NUMERIC_NEG
212    }
213
214    #[inline]
215    pub fn digits(&self) -> &[NumericDigit] {
216        &self.digits.as_slice()[0..self.ndigits as usize]
217    }
218
219    #[inline]
220    pub fn into_numeric_buf(self) -> NumericBuf {
221        let mut data = self.digits.into_owned();
222        let header_offset = data.set_header(
223            self.weight as i16,
224            self.dscale as u16,
225            self.sign as u16,
226            self.ndigits,
227        );
228
229        let (buf, len, _) = data.into_raw_parts();
230
231        unsafe {
232            NumericBuf::from_raw_parts(buf as *const u8, len * NUMERIC_DIGIT_SIZE, header_offset)
233        }
234    }
235
236    /// Round the value of a variable to no more than rscale decimal digits
237    /// after the decimal point.
238    ///
239    /// NOTE: we allow rscale < 0 here, implying rounding before the decimal point.
240    pub fn round_common(&mut self, rscale: i32) {
241        debug_assert!(!self.is_nan());
242
243        // decimal digits wanted
244        let di = (self.weight + 1) * DEC_DIGITS + rscale;
245
246        // If di = 0, the value loses all digits, but could round up to 1 if its
247        // first extra digit is >= 5.  If di < 0 the result must be 0.
248        if di < 0 {
249            self.ndigits = 0;
250            self.weight = 0;
251            self.sign = NUMERIC_POS;
252        } else {
253            // NBASE digits wanted
254            let mut ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
255            // 0, or number of decimal digits to keep in last NBASE digit
256            let di = di % DEC_DIGITS;
257
258            if ndigits < self.ndigits || (ndigits == self.ndigits && di > 0) {
259                let data = self.digits.to_mut();
260
261                if self.ndigits > 0 {
262                    data.reserve_rounding_digit(self.ndigits);
263                }
264
265                // Carry may need one additional digit
266                debug_assert!(data.offset() > NUMERIC_HEADER_NDIGITS || self.ndigits == 0);
267
268                let digits = data.digits_mut(self.ndigits);
269
270                self.ndigits = ndigits;
271
272                let mut carry: i32 = 0;
273
274                if di == 0 {
275                    if digits[ndigits as usize] >= HALF_NBASE {
276                        carry = 1;
277                    }
278                } else {
279                    // Must round within last NBASE digit
280                    let mut pow10 = ROUND_POWERS[di as usize];
281                    ndigits -= 1;
282                    debug_assert!((ndigits as usize) < digits.len());
283                    let digit = unsafe { digits.get_unchecked_mut(ndigits as usize) };
284                    let extra = *digit % pow10;
285                    *digit -= extra;
286
287                    if extra >= pow10 / 2 {
288                        pow10 += *digit;
289                        if pow10 >= NBASE as NumericDigit {
290                            pow10 -= NBASE as NumericDigit;
291                            carry = 1;
292                        }
293                        *digit = pow10;
294                    }
295                }
296
297                let offset = data.offset();
298                // Carry may need one additional digit, so we use buf from start.
299                let digits = data.as_mut_slice();
300                digits[offset as usize - 1] = 0;
301
302                // Propagate carry if needed
303                while carry > 0 {
304                    ndigits -= 1;
305                    let i = (offset as i32 + ndigits) as usize;
306                    debug_assert!(i < digits.len());
307                    let digit = unsafe { digits.get_unchecked_mut(i) };
308                    carry += *digit as i32;
309
310                    if carry >= NBASE as i32 {
311                        *digit = (carry - NBASE as i32) as NumericDigit;
312                        carry = 1;
313                    } else {
314                        *digit = carry as NumericDigit;
315                        carry = 0;
316                    }
317                }
318
319                if ndigits < 0 {
320                    debug_assert_eq!(ndigits, -1);
321                    debug_assert!(data.offset() > 0);
322                    data.offset_sub(1);
323                    self.ndigits += 1;
324                    self.weight += 1;
325                }
326            }
327        }
328
329        self.dscale = rscale;
330    }
331
332    /// Truncate (towards zero) the value of a variable at rscale decimal digits
333    /// after the decimal point.
334    ///
335    /// NOTE: we allow rscale < 0 here, implying truncation before the decimal point.
336    pub fn trunc_common(&mut self, rscale: i32) {
337        debug_assert!(!self.is_nan());
338
339        // decimal digits wanted
340        let di = (self.weight + 1) * DEC_DIGITS + rscale;
341
342        // If di <= 0, the value loses all digits.
343        if di <= 0 {
344            self.ndigits = 0;
345            self.weight = 0;
346            self.sign = NUMERIC_POS;
347        } else {
348            // NBASE digits wanted
349            let mut ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
350
351            if ndigits <= self.ndigits {
352                self.ndigits = ndigits;
353
354                // 0, or number of decimal digits to keep in last NBASE digit
355                let di = di % DEC_DIGITS;
356
357                if di > 0 {
358                    let data = self.digits.to_mut();
359                    let digits = data.digits_mut(self.ndigits);
360                    let pow10 = ROUND_POWERS[di as usize];
361                    ndigits -= 1;
362
363                    let extra = digits[ndigits as usize] % pow10;
364                    digits[ndigits as usize] -= extra;
365                }
366            }
367        }
368
369        self.dscale = rscale;
370    }
371
372    /// Return the smallest integer greater than or equal to the argument
373    /// on variable level
374    #[inline]
375    pub fn ceil_common(&self) -> Self {
376        debug_assert!(!self.is_nan());
377
378        let mut result = self.clone();
379        result.trunc_common(0);
380
381        if self.is_positive() && self.cmp_common(&result) != 0 {
382            result = result.add_common(&ONE);
383        }
384
385        result
386    }
387
388    /// Return the largest integer equal to or less than the argument
389    /// on variable level
390    #[inline]
391    pub fn floor_common(&self) -> Self {
392        debug_assert!(!self.is_nan());
393
394        let mut result = self.clone();
395        result.trunc_common(0);
396
397        if self.is_negative() && self.cmp_common(&result) != 0 {
398            result = result.sub_common(&ONE);
399        }
400
401        result
402    }
403
404    /// Strips the leading and trailing zeroes, and normalize zero.
405    pub fn strip(&mut self) {
406        let data = self.digits.to_mut();
407
408        let digits = data.digits(self.ndigits);
409        let mut ndigits = self.ndigits;
410        let mut i = 0;
411
412        // strip leading zeroes
413        while ndigits > 0 && unsafe { *digits.get_unchecked(i) } == 0 {
414            i += 1;
415            self.weight -= 1;
416            ndigits -= 1;
417        }
418
419        // strip trailing zeroes
420        while ndigits > 0 && unsafe { *digits.get_unchecked(i + ndigits as usize - 1) } == 0 {
421            ndigits -= 1;
422        }
423
424        // if it's zero, normalize the sign and weight
425        if ndigits == 0 {
426            self.sign = NUMERIC_POS;
427            self.weight = 0;
428        }
429
430        data.offset_add(i as u32);
431        self.ndigits = ndigits;
432    }
433
434    /// Add the absolute values of two variables into result.
435    pub fn add_abs(&self, other: &Self) -> Self {
436        debug_assert!(!self.is_nan());
437        debug_assert!(!other.is_nan());
438
439        // copy these values into local vars for speed in inner loop
440        let var1_ndigits = self.ndigits;
441        let var2_ndigits = other.ndigits;
442        let var1_digits = self.digits();
443        let var2_digits = other.digits();
444
445        let res_weight = self.weight.max(other.weight) + 1;
446        let res_dscale = self.dscale.max(other.dscale);
447
448        // Note: here we are figuring rscale in base-NBASE digits
449        let res_rscale = {
450            let rscale1 = self.ndigits - self.weight - 1;
451            let rscale2 = other.ndigits - other.weight - 1;
452            rscale1.max(rscale2)
453        };
454
455        let res_ndigits = {
456            let ndigits = res_rscale + res_weight + 1;
457            if ndigits > 0 {
458                ndigits
459            } else {
460                1
461            }
462        };
463
464        let mut res = Self::with_ndigits(res_ndigits);
465        let data = res.digits.to_mut();
466        let res_digits = data.digits_mut(res_ndigits);
467
468        let mut carry: NumericDigit = 0;
469        let mut i1 = res_rscale + self.weight + 1;
470        let mut i2 = res_rscale + other.weight + 1;
471        for i in (0..res_ndigits as usize).rev() {
472            i1 -= 1;
473            i2 -= 1;
474
475            if i1 >= 0 && i1 < var1_ndigits {
476                carry += unsafe { *var1_digits.get_unchecked(i1 as usize) };
477            }
478            if i2 >= 0 && i2 < var2_ndigits {
479                carry += unsafe { *var2_digits.get_unchecked(i2 as usize) };
480            }
481
482            let digit = unsafe { res_digits.get_unchecked_mut(i) };
483            if carry >= NBASE as NumericDigit {
484                *digit = carry - NBASE as NumericDigit;
485                carry = 1;
486            } else {
487                *digit = carry;
488                carry = 0;
489            }
490        }
491
492        debug_assert_eq!(carry, 0); // else we failed to allow for carry out
493
494        res.weight = res_weight;
495        res.dscale = res_dscale;
496
497        // Remove leading/trailing zeroes
498        res.strip();
499
500        res
501    }
502
503    /// Subtract the absolute value of `other` from the absolute value of `self`
504    /// and store in result.
505    ///
506    /// NOTE: ABS(`self`) MUST BE GREATER OR EQUAL ABS(`other`) !!!
507    pub fn sub_abs(&self, other: &Self) -> Self {
508        debug_assert!(!self.is_nan());
509        debug_assert!(!other.is_nan());
510
511        // copy these values into local vars for speed in inner loop
512        let var1_ndigits = self.ndigits;
513        let var2_ndigits = other.ndigits;
514        let var1_digits = self.digits();
515        let var2_digits = other.digits();
516
517        let res_weight = self.weight;
518        let res_dscale = self.dscale.max(other.dscale);
519
520        // Note: here we are figuring rscale in base-NBASE digits
521        let res_rscale = {
522            let rscale1 = self.ndigits - self.weight - 1;
523            let rscale2 = other.ndigits - other.weight - 1;
524            rscale1.max(rscale2)
525        };
526
527        let res_ndigits = {
528            let ndigits = res_rscale + res_weight + 1;
529            if ndigits <= 0 {
530                1
531            } else {
532                ndigits
533            }
534        };
535
536        let mut res = Self::with_ndigits(res_ndigits);
537        let data = res.digits.to_mut();
538        let res_digits = data.digits_mut(res_ndigits);
539
540        let mut borrow: NumericDigit = 0;
541        let mut i1 = res_rscale + self.weight + 1;
542        let mut i2 = res_rscale + other.weight + 1;
543        for i in (0..res_ndigits as usize).rev() {
544            i1 -= 1;
545            i2 -= 1;
546
547            if i1 >= 0 && i1 < var1_ndigits {
548                borrow += unsafe { *var1_digits.get_unchecked(i1 as usize) };
549            }
550            if i2 >= 0 && i2 < var2_ndigits {
551                borrow -= unsafe { *var2_digits.get_unchecked(i2 as usize) };
552            }
553
554            let digit = unsafe { res_digits.get_unchecked_mut(i) };
555            if borrow < 0 {
556                *digit = borrow + NBASE as NumericDigit;
557                borrow = -1;
558            } else {
559                *digit = borrow;
560                borrow = 0;
561            }
562        }
563
564        debug_assert_eq!(borrow, 0); // else caller gave us self < other
565
566        res.weight = res_weight;
567        res.dscale = res_dscale;
568
569        // Remove leading/trailing zeroes
570        res.strip();
571
572        res
573    }
574
575    /// Compare the absolute values of `self` and `other`
576    ///
577    /// * -1 for ABS(`self`) < ABS(`other`)
578    /// * 0 for ABS(`self`) == ABS(`other`)
579    /// * 1 for ABS(`self`) > ABS(`other`)
580    pub fn cmp_abs(&self, other: &Self) -> i32 {
581        debug_assert!(!self.is_nan());
582        debug_assert!(!other.is_nan());
583
584        let var1_ndigits = self.ndigits;
585        let var1_digits = self.digits();
586        let mut var1_weight = self.weight;
587
588        let var2_ndigits = other.ndigits;
589        let var2_digits = other.digits();
590        let mut var2_weight = other.weight;
591
592        let mut i1 = 0;
593        let mut i2 = 0;
594
595        // Check any digits before the first common digit
596
597        while var1_weight > var2_weight && i1 < var1_ndigits {
598            if unsafe { *var1_digits.get_unchecked(i1 as usize) } != 0 {
599                return 1;
600            }
601
602            i1 += 1;
603            var1_weight -= 1;
604        }
605        while var2_weight > var1_weight && i2 < var2_ndigits {
606            if unsafe { *var2_digits.get_unchecked(i2 as usize) } != 0 {
607                return -1;
608            }
609
610            i2 += 1;
611            var2_weight -= 1;
612        }
613
614        // At this point, either var1_weight == var2_weight or we've run out of digits
615
616        if var1_weight == var2_weight {
617            while i1 < var1_ndigits && i2 < var2_ndigits {
618                let stat = unsafe {
619                    *var1_digits.get_unchecked(i1 as usize)
620                        - *var2_digits.get_unchecked(i2 as usize)
621                };
622                if stat != 0 {
623                    return if stat > 0 { 1 } else { -1 };
624                } else {
625                    i1 += 1;
626                    i2 += 1;
627                }
628            }
629        }
630
631        // At this point, we've run out of digits on one side or the other; so any
632        // remaining nonzero digits imply that side is larger
633        while i1 < var1_ndigits {
634            if unsafe { *var1_digits.get_unchecked(i1 as usize) } != 0 {
635                return 1;
636            }
637
638            i1 += 1;
639        }
640        while i2 < var2_ndigits {
641            if unsafe { *var2_digits.get_unchecked(i2 as usize) } != 0 {
642                return -1;
643            }
644
645            i2 += 1;
646        }
647
648        0
649    }
650
651    /// Full version of add functionality on variable level (handling signs).
652    pub fn add_common(&self, other: &Self) -> Self {
653        debug_assert!(!self.is_nan());
654        debug_assert!(!other.is_nan());
655
656        // Decide on the signs of the two variables what to do
657        if self.is_positive() {
658            if other.is_positive() {
659                // Both are positive
660                // result = +(ABS(self) + ABS(other))
661                let mut result = self.add_abs(other);
662                result.sign = NUMERIC_POS;
663                result
664            } else {
665                let cmp = self.cmp_abs(other);
666                match cmp {
667                    0 => {
668                        // ABS(self) == ABS(other)
669                        // result = ZERO
670                        Self::zero_scaled(self.dscale.max(other.dscale))
671                    }
672                    1 => {
673                        // ABS(self) > ABS(other)
674                        // result = +(ABS(self) - ABS(other))
675                        let mut result = self.sub_abs(other);
676                        result.sign = NUMERIC_POS;
677                        result
678                    }
679                    -1 => {
680                        // ABS(self) < ABS(other)
681                        // result = -(ABS(other) - ABS(self))
682                        let mut result = other.sub_abs(self);
683                        result.sign = NUMERIC_NEG;
684                        result
685                    }
686                    _ => panic!("invalid comparison result"),
687                }
688            }
689        } else if other.is_positive() {
690            // self is negative, other is positive
691            // Must compare absolute values
692            let cmp = self.cmp_abs(other);
693            match cmp {
694                0 => {
695                    // ABS(self) == ABS(other)
696                    // result = ZERO
697                    Self::zero_scaled(self.dscale.max(other.dscale))
698                }
699                1 => {
700                    // ABS(self) > ABS(other)
701                    // result = -(ABS(self) - ABS(other))
702                    let mut result = self.sub_abs(other);
703                    result.sign = NUMERIC_NEG;
704                    result
705                }
706                -1 => {
707                    // ABS(self) < ABS(other)
708                    // result = +(ABS(other) - ABS(self))
709                    let mut result = other.sub_abs(self);
710                    result.sign = NUMERIC_POS;
711                    result
712                }
713                _ => panic!("invalid comparison result"),
714            }
715        } else {
716            // Both are negative
717            // result = -(ABS(self) + ABS(other))
718            let mut result = self.add_abs(other);
719            result.sign = NUMERIC_NEG;
720            result
721        }
722    }
723
724    /// Full version of sub functionality on variable level (handling signs).
725    pub fn sub_common(&self, other: &Self) -> Self {
726        debug_assert!(!self.is_nan());
727        debug_assert!(!other.is_nan());
728
729        // Decide on the signs of the two variables what to do
730        if self.is_positive() {
731            if other.is_negative() {
732                // self is positive, other is negative
733                // result = +(ABS(self) + ABS(other))
734                let mut result = self.add_abs(other);
735                result.sign = NUMERIC_POS;
736                result
737            } else {
738                // Both are positive
739                // Must compare absolute values
740                let cmp = self.cmp_abs(other);
741                match cmp {
742                    0 => {
743                        // ABS(self) == ABS(other)
744                        // result = ZERO
745                        Self::zero_scaled(self.dscale.max(other.dscale))
746                    }
747                    1 => {
748                        // ABS(self) > ABS(other)
749                        // result = +(ABS(self) - ABS(other))
750                        let mut result = self.sub_abs(other);
751                        result.sign = NUMERIC_POS;
752                        result
753                    }
754                    -1 => {
755                        // ABS(self) < ABS(other)
756                        // result = -(ABS(other) - ABS(self))
757                        let mut result = other.sub_abs(self);
758                        result.sign = NUMERIC_NEG;
759                        result
760                    }
761                    _ => panic!("invalid comparison result"),
762                }
763            }
764        } else if other.is_negative() {
765            // Both are negative
766            // Must compare absolute values
767            let cmp = self.cmp_abs(other);
768            match cmp {
769                0 => {
770                    // ABS(self) == ABS(other)
771                    // result = ZERO
772                    Self::zero_scaled(self.dscale.max(other.dscale))
773                }
774                1 => {
775                    // ABS(self) > ABS(other)
776                    // result = -(ABS(self) - ABS(other))
777                    let mut result = self.sub_abs(other);
778                    result.sign = NUMERIC_NEG;
779                    result
780                }
781                -1 => {
782                    // ABS(self) < ABS(other)
783                    // result = +(ABS(other) - ABS(self))
784                    let mut result = other.sub_abs(self);
785                    result.sign = NUMERIC_POS;
786                    result
787                }
788                _ => panic!("invalid comparison result"),
789            }
790        } else {
791            // var1 is negative, var2 is positive
792            // result = -(ABS(self) + ABS(other))
793            let mut result = self.add_abs(other);
794            result.sign = NUMERIC_NEG;
795            result
796        }
797    }
798
799    /// Multiplication on variable level.
800    /// Product of self * other is returned.
801    /// Result is rounded to no more than rscale fractional digits.
802    pub fn mul_common(&self, other: &Self, rscale: i32) -> Self {
803        debug_assert!(!self.is_nan());
804        debug_assert!(!other.is_nan());
805
806        // Arrange for var1 to be the shorter of the two numbers.  This improves
807        // performance because the inner multiplication loop is much simpler than
808        // the outer loop, so it's better to have a smaller number of iterations
809        // of the outer loop.  This also reduces the number of times that the
810        // accumulator array needs to be normalized.
811        let (var1, var2) = if self.ndigits > other.ndigits {
812            (other, self)
813        } else {
814            (self, other)
815        };
816
817        // copy these values into local vars for speed in inner loop
818        let var1_ndigits = var1.ndigits;
819        let var1_digits = var1.digits();
820        let var2_ndigits = var2.ndigits;
821        let var2_digits = var2.digits();
822
823        if var1_ndigits == 0 || var2_ndigits == 0 {
824            // one or both inputs is zero; so is result
825            return Self::zero_scaled(rscale);
826        }
827
828        // Determine result sign and (maximum possible) weight
829        let res_sign = if var1.sign == var2.sign {
830            NUMERIC_POS
831        } else {
832            NUMERIC_NEG
833        };
834        let res_weight = var1.weight + var2.weight + 2;
835
836        // Determine the number of result digits to compute.  If the exact result
837        // would have more than rscale fractional digits, truncate the computation
838        // with MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that
839        // would only contribute to the right of that.  (This will give the exact
840        // rounded-to-rscale answer unless carries out of the ignored positions
841        // would have propagated through more than MUL_GUARD_DIGITS digits.)
842        //
843        // Note: an exact computation could not produce more than var1ndigits +
844        // var2ndigits digits, but we allocate one extra output digit in case
845        // rscale-driven rounding produces a carry out of the highest exact digit.
846        let res_ndigits = {
847            let ndigits = var1.ndigits + var2.ndigits + 1;
848            let max_digits =
849                res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS + MUL_GUARD_DIGITS;
850            ndigits.min(max_digits)
851        };
852
853        if res_ndigits < 3 {
854            // All input digits will be ignored; so result is zero
855            return Self::zero_scaled(rscale);
856        }
857
858        // We do the arithmetic in an array "dig[]" of signed int32's.  Since
859        // INT32_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
860        // to avoid normalizing carries immediately.
861        //
862        // max_dig tracks the maximum possible value of any dig[] entry; when this
863        // threatens to exceed INT32_MAX, we take the time to propagate carries.
864        // Furthermore, we need to ensure that overflow doesn't occur during the
865        // carry propagation passes either.  The carry values could be as much as
866        // INT32_MAX/NBASE, so really we must normalize when digits threaten to
867        // exceed INT32_MAX - INT32_MAX/NBASE.
868        //
869        // To avoid overflow in max_dig itself, it actually represents the max
870        // possible value divided by NBASE-1, ie, at the top of the loop it is
871        // known that no dig[] entry exceeds max_dig * (NBASE-1).
872        let mut dig = vec![0; res_ndigits as usize * std::mem::size_of::<i32>()];
873        let mut max_dig = 0i32;
874
875        // The least significant digits of var1 should be ignored if they don't
876        // contribute directly to the first res_ndigits digits of the result that
877        // we are computing.
878        //
879        // Digit i1 of var1 and digit i2 of var2 are multiplied and added to digit
880        // i1+i2+2 of the accumulator array, so we need only consider digits of
881        // var1 for which i1 <= res_ndigits - 3.
882        let bound = (var1_ndigits - 1).min(res_ndigits - 3);
883        for i1 in (0..=bound).rev() {
884            let var1_digit = unsafe { *var1_digits.get_unchecked(i1 as usize) } as i32;
885            if var1_digit == 0 {
886                continue;
887            }
888
889            // Time to normalize?
890            max_dig += var1_digit;
891            if max_dig > ((i32::max_value() - i32::max_value() / NBASE) / (NBASE - 1)) {
892                // Yes, do it
893                let mut carry = 0;
894                for i in (0..res_ndigits).rev() {
895                    let d = unsafe { dig.get_unchecked_mut(i as usize) };
896                    let mut new_dig = *d + carry;
897                    if new_dig >= NBASE {
898                        carry = new_dig / NBASE;
899                        new_dig -= carry * NBASE;
900                    } else {
901                        carry = 0;
902                    }
903                    *d = new_dig;
904                }
905                debug_assert_eq!(carry, 0);
906                // Reset max_dig to indicate new worst-case
907                max_dig = 1 + var1_digit;
908            }
909
910            // Add the appropriate multiple of var2 into the accumulator.
911            //
912            // As above, digits of var2 can be ignored if they don't contribute,
913            // so we only include digits for which i1+i2+2 <= res_ndigits - 1.
914            let bound = (var2_ndigits - 1).min(res_ndigits - i1 - 3);
915            let mut i = i1 + bound + 2;
916            for i2 in (0..=bound).rev() {
917                let d = unsafe { dig.get_unchecked_mut(i as usize) };
918                *d += var1_digit * unsafe { *var2_digits.get_unchecked(i2 as usize) } as i32;
919                i -= 1;
920            }
921        }
922
923        // Now we do a final carry propagation pass to normalize the result, which
924        // we combine with storing the result digits into the output. Note that
925        // this is still done at full precision w/guard digits.
926        let mut result = Self::with_ndigits(res_ndigits);
927        let data = result.digits.to_mut();
928        let res_digits = data.digits_mut(res_ndigits);
929        let mut carry = 0;
930        for i in (0..res_ndigits).rev() {
931            let mut new_dig = unsafe { dig.get_unchecked(i as usize) } + carry;
932            if new_dig >= NBASE {
933                carry = new_dig / NBASE;
934                new_dig -= carry * NBASE;
935            } else {
936                carry = 0;
937            }
938            let res_digit = unsafe { res_digits.get_unchecked_mut(i as usize) };
939            *res_digit = new_dig as NumericDigit;
940        }
941        debug_assert_eq!(carry, 0);
942
943        // Finally, round the result to the requested precision.
944
945        result.weight = res_weight;
946        result.sign = res_sign;
947
948        // Round to target rscale (and set result->dscale)
949        result.round_common(rscale);
950
951        // Strip leading and trailing zeroes
952        result.strip();
953
954        result
955    }
956
957    /// Default scale selection for division
958    ///
959    /// Returns the appropriate result scale for the division result.
960    pub fn select_div_scale(&self, other: &Self) -> i32 {
961        // The result scale of a division isn't specified in any SQL standard. For
962        // PostgreSQL we select a result scale that will give at least
963        // NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
964        // result no less accurate than f64; but use a scale not less than
965        // either input's display scale.
966
967        // Get the actual (normalized) weight and first digit of each input.
968
969        let mut weight1 = 0; // values to use if self is zero
970        let mut first_digit1 = 0;
971        let var1_digits = self.digits();
972        for i in 0..self.ndigits {
973            first_digit1 = unsafe { *var1_digits.get_unchecked(i as usize) };
974            if first_digit1 != 0 {
975                weight1 = self.weight - i;
976                break;
977            }
978        }
979
980        let mut weight2 = 0; // values to use if other is zero
981        let mut first_digit2 = 0;
982        let var2_digits = other.digits();
983        for i in 0..other.ndigits {
984            first_digit2 = unsafe { *var2_digits.get_unchecked(i as usize) };
985            if first_digit2 != 0 {
986                weight2 = other.weight - i;
987                break;
988            }
989        }
990
991        // Estimate weight of quotient.  If the two first digits are equal, we
992        // can't be sure, but assume that self is less than other.
993        let qweight = {
994            let mut w = weight1 - weight2;
995            if first_digit1 <= first_digit2 {
996                w -= 1;
997            }
998            w
999        };
1000
1001        // Select result scale
1002        (NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS)
1003            .max(self.dscale)
1004            .max(other.dscale)
1005            .max(NUMERIC_MIN_DISPLAY_SCALE)
1006            .min(NUMERIC_MAX_DISPLAY_SCALE)
1007    }
1008
1009    /// Division on variable level. Quotient of `self` / `other` is returned.
1010    /// The quotient is figured to exactly rscale fractional digits.
1011    /// If round is true, it is rounded at the rscale'th digit; if false, it
1012    /// is truncated (towards zero) at that digit.
1013    ///
1014    /// Returns `None` if `other == 0`.
1015    #[allow(clippy::cognitive_complexity)]
1016    pub fn div_common(&self, other: &Self, rscale: i32, round: bool) -> Option<Self> {
1017        debug_assert!(!self.is_nan());
1018        debug_assert!(!other.is_nan());
1019
1020        // copy these values into local vars for speed in inner loop
1021        let var1_ndigits = self.ndigits;
1022        let var2_ndigits = other.ndigits;
1023
1024        // First of all division by zero check; we must not be handed an
1025        // unnormalized divisor.
1026        if var2_ndigits == 0 || other.digits[0] == 0 {
1027            return None;
1028        }
1029
1030        // Now result zero check
1031        if var1_ndigits == 0 {
1032            return Some(Self::zero_scaled(rscale));
1033        }
1034
1035        // Determine the result sign, weight and number of digits to calculate.
1036        // The weight figured here is correct if the emitted quotient has no
1037        // leading zero digits; otherwise strip() will fix things up.
1038        let res_sign = if self.sign == other.sign {
1039            NUMERIC_POS
1040        } else {
1041            NUMERIC_NEG
1042        };
1043        let res_weight = self.weight - other.weight;
1044        let res_ndigits = {
1045            // The number of accurate result digits we need to produce
1046            let mut ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
1047            // ... but always at least 1
1048            ndigits = ndigits.max(1);
1049            // If rounding needed, figure one more digit to ensure correct result
1050            if round {
1051                ndigits += 1;
1052            }
1053            ndigits
1054        };
1055
1056        // The working dividend normally requires res_ndigits + var2_ndigits
1057        // digits, but make it at least var1_ndigits so we can load all of var1
1058        // into it.  (There will be an additional digit dividend[0] in the
1059        // dividend space, but for consistency with Knuth's notation we don't
1060        // count that in div_ndigits.)
1061        let div_ndigits = {
1062            let ndigits = res_ndigits + var2_ndigits;
1063            ndigits.max(var1_ndigits)
1064        };
1065
1066        // We need a workspace with room for the working dividend (div_ndigits+1
1067        // digits) plus room for the possibly-normalized divisor (var2_ndigits
1068        // digits).  It is convenient also to have a zero at divisor[0] with the
1069        // actual divisor data in divisor[1 .. var2_ndigits].  Transferring the
1070        // digits into the workspace also allows us to realloc the result (which
1071        // might be the same as either input var) before we begin the main loop.
1072        // Note that we use palloc0 to ensure that divisor[0], dividend[0], and
1073        // any additional dividend positions beyond var1_ndigits, start out 0.
1074        let mut workspace = vec![0 as NumericDigit; (div_ndigits + var2_ndigits + 2) as usize];
1075        let (dividend, divisor) = workspace.split_at_mut(div_ndigits as usize + 1);
1076        dividend[1..=var1_ndigits as usize].copy_from_slice(self.digits());
1077        divisor[1..=var2_ndigits as usize].copy_from_slice(other.digits());
1078
1079        // Now we can alloc the result to hold the generated quotient digits.
1080        let mut result = Self::with_ndigits(res_ndigits);
1081        let data = result.digits.to_mut();
1082        let res_digits = data.digits_mut(res_ndigits);
1083
1084        if var2_ndigits == 1 {
1085            // If there's only a single divisor digit, we can use a fast path (cf.
1086            // Knuth section 4.3.1 exercise 16).
1087            let divisor1 = divisor[1] as i32;
1088            let mut carry = 0i32;
1089            for i in 0..res_ndigits as usize {
1090                carry = carry * NBASE + unsafe { *dividend.get_unchecked(i + 1) } as i32;
1091                let res_digit = unsafe { res_digits.get_unchecked_mut(i) };
1092                *res_digit = (carry / divisor1) as NumericDigit;
1093                carry %= divisor1;
1094            }
1095        } else {
1096            // The full multiple-place algorithm is taken from Knuth volume 2,
1097            // Algorithm 4.3.1D.
1098            //
1099            // We need the first divisor digit to be >= NBASE/2.  If it isn't,
1100            // make it so by scaling up both the divisor and dividend by the
1101            // factor "d".  (The reason for allocating dividend[0] above is to
1102            // leave room for possible carry here.)
1103            if divisor[1] < HALF_NBASE {
1104                let d = NBASE / (divisor[1] + 1) as i32;
1105
1106                let mut carry = 0i32;
1107                for i in (1..=var2_ndigits as usize).rev() {
1108                    let div = unsafe { divisor.get_unchecked_mut(i) };
1109                    carry += *div as i32 * d;
1110                    *div = (carry % NBASE) as NumericDigit;
1111                    carry /= NBASE;
1112                }
1113                debug_assert_eq!(carry, 0);
1114
1115                carry = 0;
1116                // at this point only var1_ndigits of dividend can be nonzero
1117                for i in (0..=var1_ndigits as usize).rev() {
1118                    let div = unsafe { dividend.get_unchecked_mut(i) };
1119                    carry += *div as i32 * d;
1120                    *div = (carry % NBASE) as NumericDigit;
1121                    carry /= NBASE;
1122                }
1123                debug_assert_eq!(carry, 0);
1124                debug_assert!(divisor[1] >= HALF_NBASE);
1125            }
1126
1127            // First 2 divisor digits are used repeatedly in main loop
1128            let divisor1 = divisor[1];
1129            let divisor2 = divisor[2];
1130
1131            // Begin the main loop.  Each iteration of this loop produces the j'th
1132            // quotient digit by dividing dividend[j .. j + var2ndigits] by the
1133            // divisor; this is essentially the same as the common manual
1134            // procedure for long division.
1135            for (j, res_digit) in res_digits.iter_mut().enumerate() {
1136                // Estimate quotient digit from the first two dividend digits
1137                let next2digits = unsafe {
1138                    *dividend.get_unchecked(j) as i32 * NBASE
1139                        + *dividend.get_unchecked(j + 1) as i32
1140                };
1141
1142                // If next2digits are 0, then quotient digit must be 0 and there's
1143                // no need to adjust the working dividend.  It's worth testing
1144                // here to fall out ASAP when processing trailing zeroes in a
1145                // dividend.
1146                if next2digits == 0 {
1147                    *res_digit = 0;
1148                    continue;
1149                }
1150
1151                let mut qhat = if unsafe { *dividend.get_unchecked(j) } == divisor1 {
1152                    NBASE - 1
1153                } else {
1154                    next2digits / divisor1 as i32
1155                };
1156
1157                // Adjust quotient digit if it's too large.  Knuth proves that
1158                // after this step, the quotient digit will be either correct or
1159                // just one too large.  (Note: it's OK to use dividend[j+2] here
1160                // because we know the divisor length is at least 2.)
1161                while divisor2 as i32 * qhat
1162                    > (next2digits - qhat * divisor1 as i32) * NBASE
1163                        + unsafe { *dividend.get_unchecked(j + 2) } as i32
1164                {
1165                    qhat -= 1;
1166                }
1167
1168                // As above, need do nothing more when quotient digit is 0
1169                if qhat > 0 {
1170                    // Multiply the divisor by qhat, and subtract that from the
1171                    // working dividend.  "carry" tracks the multiplication,
1172                    // "borrow" the subtraction (could we fold these together?)
1173                    let mut carry = 0;
1174                    let mut borrow = 0;
1175                    for i in (0..=var2_ndigits as usize).rev() {
1176                        carry += unsafe { *divisor.get_unchecked(i) } as i32 * qhat;
1177                        borrow -= carry % NBASE;
1178                        carry /= NBASE;
1179                        let div = unsafe { dividend.get_unchecked_mut(j + i) };
1180                        borrow += *div as i32;
1181                        if borrow < 0 {
1182                            *div = (borrow + NBASE) as NumericDigit;
1183                            borrow = -1;
1184                        } else {
1185                            *div = borrow as NumericDigit;
1186                            borrow = 0;
1187                        }
1188                    }
1189                    debug_assert_eq!(carry, 0);
1190
1191                    // If we got a borrow out of the top dividend digit, then
1192                    // indeed qhat was one too large.  Fix it, and add back the
1193                    // divisor to correct the working dividend.  (Knuth proves
1194                    // that this will occur only about 3/NBASE of the time; hence,
1195                    // it's a good idea to test this code with small NBASE to be
1196                    // sure this section gets exercised.)
1197                    if borrow != 0 {
1198                        qhat -= 1;
1199                        carry = 0;
1200                        for i in (0..=var2_ndigits as usize).rev() {
1201                            let div = unsafe { dividend.get_unchecked_mut(j + i) };
1202                            carry += *div as i32 + unsafe { *divisor.get_unchecked(i) } as i32;
1203                            if carry >= NBASE {
1204                                *div = (carry - NBASE) as NumericDigit;
1205                                carry = 1;
1206                            } else {
1207                                *div = carry as NumericDigit;
1208                                carry = 0;
1209                            }
1210                        }
1211                        // A carry should occur here to cancel the borrow above
1212                        debug_assert_eq!(carry, 1);
1213                    }
1214                }
1215
1216                // And we're done with this quotient digit
1217                *res_digit = qhat as NumericDigit;
1218            }
1219        }
1220
1221        // Finally, round or truncate the result to the requested precision.
1222
1223        result.weight = res_weight;
1224        result.sign = res_sign;
1225
1226        // Round or truncate to target rscale (and set result->dscale)
1227        if round {
1228            result.round_common(rscale);
1229        } else {
1230            result.trunc_common(rscale);
1231        }
1232
1233        // Strip leading and trailing zeroes
1234        result.strip();
1235
1236        Some(result)
1237    }
1238
1239    /// This has the same API as `div_common()`, but is implemented using the division
1240    /// algorithm from the "FM" library, rather than Knuth's schoolbook-division
1241    /// approach.  This is significantly faster but can produce inaccurate
1242    /// results, because it sometimes has to propagate rounding to the left,
1243    /// and so we can never be entirely sure that we know the requested digits
1244    /// exactly.  We compute DIV_GUARD_DIGITS extra digits, but there is
1245    /// no certainty that that's enough.  We use this only in the transcendental
1246    /// function calculation routines, where everything is approximate anyway.
1247    ///
1248    /// Although we provide a "round" argument for consistency with `div()`,
1249    /// it is unwise to use this function with round=false.  In truncation mode
1250    /// it is possible to get a result with no significant digits, for example
1251    /// with rscale=0 we might compute 0.99999... and truncate that to 0 when
1252    /// the correct answer is 1.
1253    ///
1254    /// Returns `None` if `other == 0`.
1255    #[allow(clippy::cognitive_complexity)]
1256    pub fn div_fast_common(&self, other: &Self, rscale: i32, round: bool) -> Option<Self> {
1257        debug_assert!(!self.is_nan());
1258        debug_assert!(!other.is_nan());
1259
1260        // copy these values into local vars for speed in inner loop
1261        let var1_ndigits = self.ndigits;
1262        let var1_digits = self.digits();
1263        let var2_ndigits = other.ndigits;
1264        let var2_digits = other.digits();
1265
1266        // First of all division by zero check; we must not be handed an
1267        // unnormalized divisor.
1268        if var2_ndigits == 0 || var2_digits[0] == 0 {
1269            return None;
1270        }
1271
1272        // Now result zero check
1273        if var1_ndigits == 0 {
1274            return Some(Self::zero_scaled(rscale));
1275        }
1276
1277        // Determine the result sign, weight and number of digits to calculate
1278        let res_sign = if self.sign == other.sign {
1279            NUMERIC_POS
1280        } else {
1281            NUMERIC_NEG
1282        };
1283        let res_weight = self.weight - other.weight + 1;
1284        let div_ndigits = {
1285            // The number of accurate result digits we need to produce
1286            let mut ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
1287            // Add guard digits for roundoff error
1288            ndigits += DIV_GUARD_DIGITS;
1289            if ndigits < DIV_GUARD_DIGITS {
1290                ndigits = DIV_GUARD_DIGITS;
1291            }
1292            // Must be at least var1_ndigits, too, to simplify data-loading loop
1293            if ndigits < var1_ndigits {
1294                ndigits = var1_ndigits;
1295            }
1296            ndigits
1297        };
1298
1299        // We do the arithmetic in an array "div[]" of signed int32's.  Since
1300        // INT32_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
1301        // to avoid normalizing carries immediately.
1302        //
1303        // We start with div[] containing one zero digit followed by the
1304        // dividend's digits (plus appended zeroes to reach the desired precision
1305        // including guard digits).  Each step of the main loop computes an
1306        // (approximate) quotient digit and stores it into div[], removing one
1307        // position of dividend space.  A final pass of carry propagation takes
1308        // care of any mistaken quotient digits.
1309        let mut div = vec![0i32; div_ndigits as usize + 1];
1310        for i in 0..var1_ndigits as usize {
1311            let d = unsafe { div.get_unchecked_mut(i + 1) };
1312            *d = unsafe { *var1_digits.get_unchecked(i) } as i32;
1313        }
1314
1315        // We estimate each quotient digit using floating-point arithmetic, taking
1316        // the first four digits of the (current) dividend and divisor.  This must
1317        // be float to avoid overflow.  The quotient digits will generally be off
1318        // by no more than one from the exact answer.
1319        let mut fdivisor = var2_digits[0] as f64;
1320        for i in 1..4 {
1321            fdivisor *= NBASE as f64;
1322            if i < var2_ndigits {
1323                fdivisor += unsafe { *var2_digits.get_unchecked(i as usize) } as f64;
1324            }
1325        }
1326        let fdivisor_inverse = 1.0 / fdivisor;
1327
1328        // max_div tracks the maximum possible absolute value of any div[] entry;
1329        // when this threatens to exceed INT_MAX, we take the time to propagate
1330        // carries.  Furthermore, we need to ensure that overflow doesn't occur
1331        // during the carry propagation passes either.  The carry values may have
1332        // an absolute value as high as INT_MAX/NBASE + 1, so really we must
1333        // normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
1334        //
1335        // To avoid overflow in max_div itself, it represents the max absolute
1336        // value divided by NBASE-1, ie, at the top of the loop it is known that
1337        // no div[] entry has an absolute value exceeding max_div * (NBASE-1).
1338        //
1339        // Actually, though, that holds good only for div[] entries after div[qi];
1340        // the adjustment done at the bottom of the loop may cause div[qi + 1] to
1341        // exceed the max_div limit, so that div[qi] in the next iteration is
1342        // beyond the limit.  This does not cause problems, as explained below.
1343        let mut max_div = 1;
1344
1345        // Outer loop computes next quotient digit, which will go into div[qi]
1346        for qi in 0..div_ndigits as usize {
1347            // Approximate the current dividend value
1348            let mut fdividend = unsafe { *div.get_unchecked(qi) } as f64;
1349            for i in 1..4usize {
1350                fdividend *= NBASE as f64;
1351                if (qi + i) as i32 <= div_ndigits {
1352                    fdividend += unsafe { *div.get_unchecked(qi + i) } as f64;
1353                }
1354            }
1355            // Compute the (approximate) quotient digit
1356            let mut fquotient = fdividend * fdivisor_inverse;
1357            let mut qdigit = if fquotient >= 0.0 {
1358                fquotient as i32
1359            } else {
1360                // truncate towards -infinity
1361                fquotient as i32 - 1
1362            };
1363
1364            if qdigit != 0 {
1365                // Do we need to normalize now?
1366                max_div += qdigit.abs();
1367                if max_div > (i32::max_value() - i32::max_value() / NBASE - 1) / (NBASE - 1) {
1368                    // Yes, do it
1369                    let mut carry = 0;
1370                    let mut new_dig;
1371                    for i in (qi + 1..=div_ndigits as usize).rev() {
1372                        let div_i = unsafe { div.get_unchecked_mut(i) };
1373                        new_dig = *div_i + carry;
1374                        if new_dig < 0 {
1375                            carry = -((-new_dig - 1) / NBASE) - 1;
1376                            new_dig -= carry * NBASE;
1377                        } else if new_dig >= NBASE {
1378                            carry = new_dig / NBASE;
1379                            new_dig -= carry * NBASE;
1380                        } else {
1381                            carry = 0;
1382                        }
1383                        *div_i = new_dig;
1384                    }
1385                    let div_qi = unsafe { div.get_unchecked_mut(qi) };
1386                    new_dig = *div_qi + carry;
1387                    *div_qi = new_dig;
1388
1389                    // All the div[] digits except possibly div[qi] are now in the
1390                    // range 0..NBASE-1.  We do not need to consider div[qi] in
1391                    // the max_div value anymore, so we can reset max_div to 1.
1392                    max_div = 1;
1393
1394                    // Recompute the quotient digit since new info may have
1395                    // propagated into the top four dividend digits
1396                    fdividend = *div_qi as f64;
1397                    for i in 1..4usize {
1398                        fdividend *= NBASE as f64;
1399                        if (qi + i) as i32 <= div_ndigits {
1400                            fdividend += unsafe { *div.get_unchecked(qi + i) } as f64;
1401                        }
1402                    }
1403                    // Compute the (approximate) quotient digit
1404                    fquotient = fdividend * fdivisor_inverse;
1405                    qdigit = if fquotient >= 0.0 {
1406                        fquotient as i32
1407                    } else {
1408                        // truncate towards -infinity
1409                        fquotient as i32 - 1
1410                    };
1411                    max_div += qdigit.abs();
1412                }
1413
1414                // Subtract off the appropriate multiple of the divisor.
1415                //
1416                // The digits beyond div[qi] cannot overflow, because we know they
1417                // will fall within the max_div limit.  As for div[qi] itself, note
1418                // that qdigit is approximately trunc(div[qi] / vardigits[0]),
1419                // which would make the new value simply div[qi] mod vardigits[0].
1420                // The lower-order terms in qdigit can change this result by not
1421                // more than about twice INT_MAX/NBASE, so overflow is impossible.
1422                if qdigit != 0 {
1423                    let istop = var2_ndigits.min(div_ndigits - qi as i32 + 1);
1424                    for i in 0..istop as usize {
1425                        let div_qi_i = unsafe { div.get_unchecked_mut(qi + i) };
1426                        *div_qi_i -= qdigit * unsafe { *var2_digits.get_unchecked(i) } as i32;
1427                    }
1428                }
1429            }
1430
1431            // The dividend digit we are about to replace might still be nonzero.
1432            // Fold it into the next digit position.
1433            //
1434            // There is no risk of overflow here, although proving that requires
1435            // some care.  Much as with the argument for div[qi] not overflowing,
1436            // if we consider the first two terms in the numerator and denominator
1437            // of qdigit, we can see that the final value of div[qi + 1] will be
1438            // approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
1439            // Accounting for the lower-order terms is a bit complicated but ends
1440            // up adding not much more than INT_MAX/NBASE to the possible range.
1441            // Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
1442            // in the next loop iteration, it can't be large enough to cause
1443            // overflow in the carry propagation step (if any), either.
1444            //
1445            // But having said that: div[qi] can be more than INT_MAX/NBASE, as
1446            // noted above, which means that the product div[qi] * NBASE *can*
1447            // overflow.  When that happens, adding it to div[qi + 1] will always
1448            // cause a canceling overflow so that the end result is correct.  We
1449            // could avoid the intermediate overflow by doing the multiplication
1450            // and addition in int64 arithmetic, but so far there appears no need.
1451            let div_qi = unsafe { *div.get_unchecked(qi) };
1452            let div_qi_1 = unsafe { div.get_unchecked_mut(qi + 1) };
1453            *div_qi_1 += div_qi * NBASE;
1454
1455            let div_qi = unsafe { div.get_unchecked_mut(qi) };
1456            *div_qi = qdigit;
1457        }
1458
1459        // Approximate and store the last quotient digit (div[div_ndigits])
1460        let mut fdividend = div[div_ndigits as usize] as f64;
1461        for _ in 1..4usize {
1462            fdividend *= NBASE as f64;
1463        }
1464        let fquotient = fdividend * fdivisor_inverse;
1465        let qdigit = if fquotient >= 0.0 {
1466            fquotient as i32
1467        } else {
1468            // truncate towards -infinity
1469            fquotient as i32 - 1
1470        };
1471        div[div_ndigits as usize] = qdigit;
1472
1473        // Because the quotient digits might be off by one, some of them might be
1474        // -1 or NBASE at this point.  The represented value is correct in a
1475        // mathematical sense, but it doesn't look right.  We do a final carry
1476        // propagation pass to normalize the digits, which we combine with storing
1477        // the result digits into the output.  Note that this is still done at
1478        // full precision w/guard digits.
1479        let mut result = Self::with_ndigits(div_ndigits + 1);
1480        let data = result.digits.to_mut();
1481        let res_digits = data.digits_mut(result.ndigits);
1482
1483        let mut carry = 0;
1484        for i in (0..=div_ndigits as usize).rev() {
1485            let mut new_dig = unsafe { *div.get_unchecked(i) } + carry;
1486            if new_dig < 0 {
1487                carry = -((-new_dig - 1) / NBASE) - 1;
1488                new_dig -= carry * NBASE;
1489            } else if new_dig >= NBASE {
1490                carry = new_dig / NBASE;
1491                new_dig -= carry * NBASE;
1492            } else {
1493                carry = 0;
1494            }
1495            let res_digit_i = unsafe { res_digits.get_unchecked_mut(i) };
1496            *res_digit_i = new_dig as NumericDigit;
1497        }
1498        debug_assert_eq!(carry, 0);
1499
1500        // Finally, round the result to the requested precision.
1501
1502        result.weight = res_weight;
1503        result.sign = res_sign;
1504
1505        // Round to target rscale (and set result->dscale)
1506        if round {
1507            result.round_common(rscale);
1508        } else {
1509            result.trunc_common(rscale);
1510        }
1511
1512        // Strip leading and trailing zeroes
1513        result.strip();
1514
1515        Some(result)
1516    }
1517
1518    /// Calculate the modulo of two numerics at variable level.
1519    #[inline]
1520    pub fn mod_common(&self, other: &Self) -> Option<Self> {
1521        debug_assert!(!self.is_nan());
1522        debug_assert!(!other.is_nan());
1523
1524        // We do this using the equation
1525        // mod(x,y) = x - trunc(x/y)*y
1526        // div() can be persuaded to give us trunc(x/y) directly.
1527        let mut result = self.div_common(other, 0, false)?;
1528        result = result.mul_common(other, other.dscale);
1529        result = self.sub_common(&result);
1530
1531        Some(result)
1532    }
1533
1534    /// Compare two values on variable level.
1535    /// We assume zeroes have been truncated to no digits.
1536    #[inline]
1537    pub fn cmp_common(&self, other: &Self) -> i32 {
1538        debug_assert!(!self.is_nan());
1539        debug_assert!(!other.is_nan());
1540
1541        if self.ndigits == 0 {
1542            if other.ndigits == 0 {
1543                0
1544            } else if other.is_negative() {
1545                1
1546            } else {
1547                -1
1548            }
1549        } else if other.ndigits == 0 {
1550            if self.is_positive() {
1551                1
1552            } else {
1553                -1
1554            }
1555        } else if self.is_positive() {
1556            if other.is_negative() {
1557                1
1558            } else {
1559                self.cmp_abs(other)
1560            }
1561        } else if other.is_positive() {
1562            -1
1563        } else {
1564            other.cmp_abs(self)
1565        }
1566    }
1567
1568    /// Compute the square root of x using Newton's algorithm.
1569    pub fn sqrt_common(&self, rscale: i32) -> Self {
1570        debug_assert!(self.is_positive());
1571
1572        let local_rscale = rscale + 8;
1573
1574        if self.ndigits == 0 {
1575            return Self::zero_scaled(rscale);
1576        }
1577
1578        // Initialize the result to the first guess
1579        let mut result = Self::with_ndigits(1);
1580        let data = result.digits.to_mut();
1581        data.digits_mut(1)[0] = {
1582            let i = self.digits[0] / 2;
1583            if i == 0 {
1584                1
1585            } else {
1586                i
1587            }
1588        };
1589        result.weight = self.weight / 2;
1590
1591        let mut last_val = result.clone();
1592
1593        loop {
1594            let val = self
1595                .div_fast_common(&result, local_rscale, true)
1596                .expect("should not be zero");
1597            result = result.add_common(&val);
1598            result = result.mul_common(&ZERO_POINT_FIVE, local_rscale);
1599
1600            if result.cmp_common(&last_val) == 0 {
1601                break;
1602            }
1603
1604            last_val = result.clone();
1605        }
1606
1607        // Round to requested precision
1608        result.round_common(rscale);
1609
1610        result
1611    }
1612
1613    /// Raise `self` to the power of exp, where exp is an integer.
1614    ///
1615    /// Returns `None` if overflows.
1616    ///
1617    /// # Panics
1618    /// Panics if self is zero and exp is less than zero.
1619    pub fn power_int(&self, exp: i32, rscale: i32) -> Option<Self> {
1620        debug_assert!(!self.is_nan());
1621
1622        // Handle some common special cases, as well as corner cases
1623        match exp {
1624            0 => {
1625                // While 0 ^ 0 can be either 1 or indeterminate (error), we treat
1626                // it as 1 because most programming languages do this. SQL:2003
1627                // also requires a return value of 1.
1628                // https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
1629                let mut result = ONE.clone();
1630                result.dscale = rscale; // no need to round
1631                return Some(result);
1632            }
1633            1 => {
1634                let mut result = self.clone();
1635                result.round_common(rscale);
1636                return Some(result);
1637            }
1638            -1 => {
1639                let result = ONE
1640                    .div_common(self, rscale, true)
1641                    .expect(DIVIDE_BY_ZERO_MSG);
1642                return Some(result);
1643            }
1644            2 => {
1645                let result = self.mul_common(self, rscale);
1646                return Some(result);
1647            }
1648            _ => (),
1649        }
1650
1651        // Handle the special case where the base is zero
1652        if self.ndigits == 0 {
1653            assert!(exp >= 0, DIVIDE_BY_ZERO_MSG);
1654            return Some(Self::zero_scaled(rscale));
1655        }
1656
1657        // The general case repeatedly multiplies base according to the bit
1658        // pattern of exp.
1659        //
1660        // First we need to estimate the weight of the result so that we know how
1661        // many significant digits are needed.
1662        let digits = self.digits();
1663        let mut f = digits[0] as f64;
1664        let mut p = self.weight * DEC_DIGITS;
1665
1666        for (i, &digit) in digits.iter().enumerate().skip(1) {
1667            if (i * DEC_DIGITS as usize) < 16 {
1668                break;
1669            }
1670
1671            f = f * NBASE as f64 + digit as f64;
1672            p -= DEC_DIGITS;
1673        }
1674
1675        // We have base ~= f * 10^p
1676        // so log10(result) = log10(base^exp) ~= exp * (log10(f) + p)
1677        f = exp as f64 * (f.log10() + p as f64);
1678
1679        // Apply crude overflow/underflow tests so we can exit early if the result
1680        // certainly will overflow/underflow.
1681        if f > 3.0 * i16::max_value() as f64 * DEC_DIGITS as f64 {
1682            return None;
1683        }
1684
1685        if f + 1.0 < (-rscale) as f64 || f + 1.0 < (-NUMERIC_MAX_DISPLAY_SCALE) as f64 {
1686            return Some(Self::zero_scaled(rscale));
1687        }
1688
1689        // Approximate number of significant digits in the result.  Note that the
1690        // underflow test above means that this is necessarily >= 0.
1691        let mut sig_digits = 1 + rscale + f as i32;
1692
1693        // The multiplications to produce the result may introduce an error of up
1694        // to around log10(abs(exp)) digits, so work with this many extra digits
1695        // of precision (plus a few more for good measure).
1696        sig_digits += (exp.abs() as f64).ln() as i32 + 8;
1697
1698        // Now we can proceed with the multiplications.
1699        let mut neg = exp < 0;
1700        let mut mask = exp.abs();
1701
1702        let mut base_prod = self.clone();
1703
1704        let mut result = if mask & 1 != 0 {
1705            self.clone()
1706        } else {
1707            ONE.clone()
1708        };
1709
1710        loop {
1711            mask >>= 1;
1712            if mask <= 0 {
1713                break;
1714            }
1715
1716            // Do the multiplications using rscales large enough to hold the
1717            // results to the required number of significant digits, but don't
1718            // waste time by exceeding the scales of the numbers themselves.
1719            let local_rscale = (sig_digits - 2 * base_prod.weight * DEC_DIGITS)
1720                .min(2 * base_prod.dscale)
1721                .max(NUMERIC_MIN_DISPLAY_SCALE);
1722
1723            base_prod = base_prod.mul_common(&base_prod, local_rscale);
1724
1725            if mask & 1 != 0 {
1726                let local_rscale = (sig_digits - (base_prod.weight + result.weight) * DEC_DIGITS)
1727                    .min(base_prod.dscale + result.dscale)
1728                    .max(NUMERIC_MIN_DISPLAY_SCALE);
1729
1730                result = base_prod.mul_common(&result, local_rscale);
1731            }
1732
1733            // When abs(base) > 1, the number of digits to the left of the decimal
1734            // point in base_prod doubles at each iteration, so if exp is large we
1735            // could easily spend large amounts of time and memory space doing the
1736            // multiplications.  But once the weight exceeds what will fit in
1737            // int16, the final result is guaranteed to overflow (or underflow, if
1738            // exp < 0), so we can give up before wasting too many cycles.
1739            if base_prod.weight > i16::max_value() as i32 || result.weight > i16::max_value() as i32
1740            {
1741                // overflow, unless neg, in which case result should be 0
1742                if !neg {
1743                    return None;
1744                }
1745                result = ZERO.clone();
1746                neg = false;
1747                break;
1748            }
1749        }
1750
1751        // Compensate for input sign, and round to requested rscale
1752        if neg {
1753            result = ONE
1754                .div_fast_common(&result, rscale, true)
1755                .expect(DIVIDE_BY_ZERO_MSG);
1756        } else {
1757            result.round_common(rscale);
1758        }
1759
1760        Some(result)
1761    }
1762
1763    /// Compute the natural log of `self`
1764    pub fn ln_common(&self, rscale: i32) -> Self {
1765        debug_assert!(!self.is_nan());
1766        debug_assert!(self.cmp_common(&ZERO) > 0);
1767
1768        let mut x = self.clone();
1769        let mut fact = TWO.clone();
1770
1771        // Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
1772        //
1773        // The final logarithm will have up to around rscale+6 significant digits.
1774        // Each sqrt() will roughly halve the weight of x, so adjust the local
1775        // rscale as we work so that we keep this many significant digits at each
1776        // step (plus a few more for good measure).
1777        while x.cmp_common(&ZERO_POINT_NINE) <= 0 {
1778            let mut local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
1779            local_rscale = local_rscale.max(NUMERIC_MIN_DISPLAY_SCALE);
1780            x = x.sqrt_common(local_rscale);
1781            fact = fact.mul_common(&TWO, 0);
1782        }
1783        while x.cmp_common(&ONE_POINT_ONE) >= 0 {
1784            let mut local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
1785            local_rscale = local_rscale.max(NUMERIC_MIN_DISPLAY_SCALE);
1786            x = x.sqrt_common(local_rscale);
1787            fact = fact.mul_common(&TWO, 0);
1788        }
1789
1790        // We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
1791        //
1792        // z + z^3/3 + z^5/5 + ...
1793        //
1794        // where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
1795        // due to the above range-reduction of x.
1796        //
1797        // The convergence of this is not as fast as one would like, but is
1798        // tolerable given that z is small.
1799        let local_rscale = rscale + 8;
1800
1801        let mut result = x.sub_common(&ONE);
1802        let mut elem = x.add_common(&ONE);
1803        result = result
1804            .div_fast_common(&elem, local_rscale, true)
1805            .expect(DIVIDE_BY_ZERO_MSG);
1806        let mut xx = result.clone();
1807        x = result.mul_common(&result, local_rscale);
1808
1809        let mut ni = ONE.clone();
1810
1811        loop {
1812            ni = ni.add_common(&TWO);
1813            xx = xx.mul_common(&x, local_rscale);
1814            elem = xx
1815                .div_fast_common(&ni, local_rscale, true)
1816                .expect(DIVIDE_BY_ZERO_MSG);
1817
1818            if elem.ndigits == 0 {
1819                break;
1820            }
1821
1822            result = result.add_common(&elem);
1823
1824            if elem.weight < (result.weight - local_rscale * 2 / DEC_DIGITS) {
1825                break;
1826            }
1827        }
1828
1829        // Compensate for argument range reduction, round to requested rscale
1830        result = result.mul_common(&fact, rscale);
1831
1832        result
1833    }
1834
1835    /// Estimate the dweight of the most significant decimal digit of the natural
1836    /// logarithm of a number.
1837    ///
1838    /// Essentially, we're approximating `log10(abs(ln(self)))`.  This is used to
1839    /// determine the appropriate rscale when computing natural logarithms.
1840    pub fn estimate_ln_dweight(&self) -> i32 {
1841        debug_assert!(!self.is_nan());
1842
1843        let ln_dweight: i32;
1844
1845        if self.cmp_common(&ZERO_POINT_NINE) >= 0 && self.cmp_common(&ONE_POINT_ONE) <= 0 {
1846            // 0.9 <= self <= 1.1
1847            //
1848            // ln(self) has a negative weight (possibly very large).  To get a
1849            // reasonably accurate result, estimate it using ln(1+x) ~= x.
1850            let x = self.sub_common(&ONE);
1851            if x.ndigits > 0 {
1852                // Use weight of most significant decimal digit of x
1853                ln_dweight = x.weight * DEC_DIGITS + (x.digits()[0] as f64).log10() as i32;
1854            } else {
1855                // x = 0.  Since ln(1) = 0 exactly, we don't need extra digits
1856                ln_dweight = 0;
1857            }
1858        } else {
1859            // Estimate the logarithm using the first couple of digits from the
1860            // input number.  This will give an accurate result whenever the input
1861            // is not too close to 1.
1862            if self.ndigits > 0 {
1863                let d = self.digits();
1864
1865                let mut digits = d[0] as i32;
1866                let mut dweight = self.weight * DEC_DIGITS;
1867
1868                if self.ndigits > 1 {
1869                    digits = digits * NBASE + d[1] as i32;
1870                    dweight -= DEC_DIGITS;
1871                }
1872
1873                // We have self ~= digits * 10^dweight
1874                // so ln(self) ~= ln(digits) + dweight * ln(10)
1875                let ln_var = (digits as f64).ln() + dweight as f64 * LN_10;
1876                ln_dweight = ln_var.abs().log10() as i32;
1877            } else {
1878                ln_dweight = 0;
1879            }
1880        }
1881
1882        ln_dweight
1883    }
1884
1885    /// Compute the logarithm of `self` in a given base.
1886    ///
1887    /// Note: this routine chooses dscale of the result.
1888    pub fn log_common(&self, base: &Self) -> Self {
1889        debug_assert!(!self.is_nan());
1890        debug_assert!(!base.is_nan());
1891        debug_assert!(self.cmp_common(&ZERO) > 0);
1892
1893        // Estimated dweights of ln(base), ln(self) and the final result
1894        let ln_base_dweight = base.estimate_ln_dweight();
1895        let ln_num_dweight = self.estimate_ln_dweight();
1896        let result_dweight = ln_num_dweight - ln_base_dweight;
1897
1898        // Select the scale of the result so that it will have at least
1899        // NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
1900        // input's display scale.
1901        let rscale = (NUMERIC_MIN_SIG_DIGITS - result_dweight)
1902            .max(base.dscale)
1903            .max(self.dscale)
1904            .max(NUMERIC_MIN_DISPLAY_SCALE)
1905            .min(NUMERIC_MAX_DISPLAY_SCALE);
1906
1907        // Set the scales for ln(base) and ln(num) so that they each have more
1908        // significant digits than the final result.
1909        let ln_base_rscale =
1910            (rscale + result_dweight - ln_base_dweight + 8).max(NUMERIC_MIN_DISPLAY_SCALE);
1911        let ln_num_rscale =
1912            (rscale + result_dweight - ln_num_dweight + 8).max(NUMERIC_MIN_DISPLAY_SCALE);
1913
1914        // Form natural logarithms
1915        let ln_base = base.ln_common(ln_base_rscale);
1916        let ln_num = self.ln_common(ln_num_rscale);
1917
1918        // Divide and round to the required scale
1919        ln_num
1920            .div_fast_common(&ln_base, rscale, true)
1921            .expect(DIVIDE_BY_ZERO_MSG)
1922    }
1923
1924    /// Raise e to the power of x, computed to rscale fractional digits.
1925    ///
1926    /// Returns `None` if overflows.
1927    pub fn exp_common(&self, rscale: i32) -> Option<Self> {
1928        debug_assert!(!self.is_nan());
1929
1930        let mut x = self.clone();
1931
1932        // Estimate the dweight of the result using floating point arithmetic, so
1933        // that we can choose an appropriate local rscale for the calculation.
1934        let mut val: f64 = TryFrom::try_from(&x).unwrap();
1935
1936        // Guard against overflow
1937        // If you change this limit, see also power_common()'s limit
1938        if val.abs() >= NUMERIC_MAX_RESULT_SCALE as f64 * 3.0 {
1939            // value overflows numeric format
1940            return None;
1941        }
1942
1943        // decimal weight = log10(e^x) = x * log10(e)
1944        let dweight = (val * LOG10_E) as i32;
1945        let mut ndiv2: i32;
1946
1947        // Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
1948        // 2^n, to improve the convergence rate of the Taylor series.
1949        if val.abs() > 0.01 {
1950            let mut tmp = TWO.clone();
1951
1952            ndiv2 = 1;
1953            val /= 2.0;
1954
1955            while val.abs() > 0.01 {
1956                ndiv2 += 1;
1957                val /= 2.0;
1958                tmp = tmp.add_common(&tmp);
1959            }
1960
1961            let local_rscale = x.dscale + ndiv2;
1962            x = x
1963                .div_fast_common(&tmp, local_rscale, true)
1964                .expect(DIVIDE_BY_ZERO_MSG);
1965        } else {
1966            ndiv2 = 0;
1967        }
1968
1969        // Set the scale for the Taylor series expansion.  The final result has
1970        // (dweight + rscale + 1) significant digits.  In addition, we have to
1971        // raise the Taylor series result to the power 2^ndiv2, which introduces
1972        // an error of up to around log10(2^ndiv2) digits, so work with this many
1973        // extra digits of precision (plus a few more for good measure).
1974        let mut sig_digits = 1 + dweight + rscale + (ndiv2 as f64 * LOG10_2) as i32;
1975        sig_digits = sig_digits.max(0) + 8;
1976
1977        let local_rscale = sig_digits - 1;
1978
1979        // Use the Taylor series
1980        //
1981        // exp(x) = 1 + x + x^2/2! + x^3/3! + ...
1982        //
1983        // Given the limited range of x, this should converge reasonably quickly.
1984        // We run the series until the terms fall below the local_rscale limit.
1985        let mut result = ONE.add_common(&x);
1986
1987        let mut elem = x.mul_common(&x, local_rscale);
1988        let mut ni = TWO.clone();
1989        elem = elem
1990            .div_fast_common(&ni, local_rscale, true)
1991            .expect(DIVIDE_BY_ZERO_MSG);
1992
1993        while elem.ndigits != 0 {
1994            result = result.add_common(&elem);
1995
1996            elem = elem.mul_common(&x, local_rscale);
1997            ni = ni.add_common(&ONE);
1998            elem = elem
1999                .div_fast_common(&ni, local_rscale, true)
2000                .expect(DIVIDE_BY_ZERO_MSG);
2001        }
2002
2003        // Compensate for the argument range reduction.  Since the weight of the
2004        // result doubles with each multiplication, we can reduce the local rscale
2005        // as we proceed.
2006        for _ in 1..=ndiv2 {
2007            let mut local_rscale = sig_digits - result.weight * 2 * DEC_DIGITS;
2008            local_rscale = local_rscale.max(NUMERIC_MIN_DISPLAY_SCALE);
2009            result = result.mul_common(&result, local_rscale);
2010        }
2011
2012        // Round to requested rscale
2013        result.round_common(rscale);
2014
2015        Some(result)
2016    }
2017
2018    /// Raise `self` to the power of `exp`
2019    ///
2020    /// Returns `None` if overflows.
2021    ///
2022    /// Note: this routine chooses dscale of the result.
2023    ///
2024    /// # Panics
2025    /// Panics if self is zero and exp is less than zero.
2026    pub fn power_common(&self, exp: &Self) -> Option<Self> {
2027        debug_assert!(!self.is_nan());
2028        debug_assert!(!exp.is_nan());
2029
2030        // If exp can be represented as an integer, use power_int()
2031        if exp.ndigits == 0 || exp.ndigits <= exp.weight + 1 {
2032            // exact integer, but does it fit in i32?
2033            if let Ok(exp_val) = TryInto::<i32>::try_into(exp) {
2034                // Okay, select rscale
2035                let rscale = NUMERIC_MIN_SIG_DIGITS
2036                    .max(self.dscale)
2037                    .max(NUMERIC_MIN_DISPLAY_SCALE)
2038                    .min(NUMERIC_MAX_DISPLAY_SCALE);
2039
2040                let result = self.power_int(exp_val, rscale);
2041                return result;
2042            }
2043        }
2044
2045        // This avoids log(0) for cases of 0 raised to a non-integer.  0 ^ 0 is
2046        // handled by power_int().
2047        if self.cmp_common(&ZERO) == 0 {
2048            return Some(Self::zero_scaled(NUMERIC_MIN_SIG_DIGITS));
2049        }
2050
2051        // Decide on the scale for the ln() calculation.  For this we need an
2052        // estimate of the weight of the result, which we obtain by doing an
2053        // initial low-precision calculation of exp * ln(base).
2054        //
2055        // We want result = e ^ (exp * ln(base))
2056        // so result dweight = log10(result) = exp * ln(base) * log10(e)
2057        //
2058        // We also perform a crude overflow test here so that we can exit early if
2059        // the full-precision result is sure to overflow, and to guard against
2060        // integer overflow when determining the scale for the real calculation.
2061        // exp_common() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
2062        // result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
2063        // Since the values here are only approximations, we apply a small fuzz
2064        // factor to this overflow test and let exp_common() determine the exact
2065        // overflow threshold so that it is consistent for all inputs.
2066        let ln_dweight = self.estimate_ln_dweight();
2067
2068        let local_rscale = (8 - ln_dweight)
2069            .max(NUMERIC_MIN_DISPLAY_SCALE)
2070            .min(NUMERIC_MAX_DISPLAY_SCALE);
2071
2072        let mut ln_base = self.ln_common(local_rscale);
2073        let mut ln_num = ln_base.mul_common(exp, local_rscale);
2074
2075        let mut val: f64 = TryFrom::try_from(&ln_num).unwrap();
2076
2077        // initial overflow test with fuzz factor
2078        if val.abs() > NUMERIC_MAX_RESULT_SCALE as f64 * 3.01 {
2079            // value overflows numeric format
2080            return None;
2081        }
2082
2083        val *= LOG10_E; // approximate decimal result weight
2084
2085        // choose the result scale
2086        let rscale = (NUMERIC_MIN_SIG_DIGITS - val as i32)
2087            .max(self.dscale)
2088            .max(exp.dscale)
2089            .max(NUMERIC_MIN_DISPLAY_SCALE)
2090            .min(NUMERIC_MAX_DISPLAY_SCALE);
2091
2092        // set the scale for the real exp * ln(base) calculation
2093        let local_rscale = (rscale + val as i32 - ln_dweight + 8).max(NUMERIC_MIN_DISPLAY_SCALE);
2094
2095        // and do the real calculation
2096        ln_base = self.ln_common(local_rscale);
2097        ln_num = ln_base.mul_common(exp, local_rscale);
2098        ln_num.exp_common(rscale)
2099    }
2100
2101    /// Convert `self` to text representation.
2102    /// `self` is displayed to the number of digits indicated by its dscale.
2103    pub fn write<W: fmt::Write>(&self, f: &mut W) -> Result<(), fmt::Error> {
2104        if self.is_nan() {
2105            return f.write_str("NaN");
2106        }
2107
2108        // Output a dash for negative values.
2109        if self.sign == NUMERIC_NEG {
2110            f.write_char('-')?;
2111        }
2112
2113        // Output all digits before the decimal point.
2114        if self.weight < 0 {
2115            f.write_char('0')?;
2116        } else {
2117            let digits = self.digits();
2118            debug_assert_eq!(digits.len(), self.ndigits as usize);
2119
2120            for d in 0..=self.weight {
2121                let dig = if d < self.ndigits {
2122                    digits[d as usize]
2123                } else {
2124                    0
2125                };
2126
2127                debug_assert!(dig >= 0);
2128
2129                // In the first digit, suppress extra leading decimal zeroes.
2130                if d > 0 {
2131                    write!(f, "{:>0width$}", dig, width = DEC_DIGITS as usize)?;
2132                } else {
2133                    write!(f, "{}", dig)?;
2134                }
2135            }
2136        }
2137
2138        // If requested, output a decimal point and all the digits that follow it.
2139        if self.dscale > 0 {
2140            f.write_char('.')?;
2141
2142            let digits = self.digits();
2143            debug_assert_eq!(digits.len(), self.ndigits as usize);
2144
2145            let mut d = self.weight + 1;
2146
2147            for scale in (0..self.dscale).step_by(DEC_DIGITS as usize) {
2148                let dig = if d >= 0 && d < self.ndigits {
2149                    digits[d as usize]
2150                } else {
2151                    0
2152                };
2153
2154                if scale + DEC_DIGITS <= self.dscale {
2155                    write!(f, "{:>0width$}", dig, width = DEC_DIGITS as usize)?;
2156                } else {
2157                    // truncate the last digit
2158                    let width = (self.dscale - scale) as usize;
2159                    let dig = (0..DEC_DIGITS as usize - width).fold(dig, |acc, _| acc / 10);
2160                    write!(f, "{:>0width$}", dig, width = width)?;
2161                }
2162
2163                d += 1;
2164            }
2165        }
2166
2167        Ok(())
2168    }
2169
2170    /// Convert `self` to a normalised scientific notation text representation.
2171    ///
2172    /// This notation has the general form a * 10^b, where a is known as the
2173    /// "significand" and b is known as the "exponent".
2174    ///
2175    /// Because we can't do superscript in ASCII (and because we want to copy
2176    /// printf's behaviour) we display the exponent using E notation, with a
2177    /// minimum of two exponent digits.
2178    ///
2179    /// For example, the value 1234 could be output as 1.2e+03.
2180    ///
2181    /// We assume that the exponent can fit into an int32.
2182    ///
2183    /// `rscale` is the number of decimal digits desired after the decimal point in
2184    /// the output, negative values will be treated as meaning zero.
2185    ///
2186    /// `lower_exp` indicates use 'e' if true or else use 'E'.
2187    pub fn write_sci<W: fmt::Write>(
2188        &self,
2189        f: &mut W,
2190        rscale: i32,
2191        lower_exp: bool,
2192    ) -> Result<(), fmt::Error> {
2193        if self.is_nan() {
2194            return write!(f, "NaN");
2195        }
2196
2197        let rscale = if rscale < 0 { 0 } else { rscale };
2198
2199        // Determine the exponent of this number in normalised form.
2200        //
2201        // This is the exponent required to represent the number with only one
2202        // significant digit before the decimal place.
2203        let exponent = if self.ndigits > 0 {
2204            let mut exp = (self.weight + 1) * DEC_DIGITS;
2205            // Compensate for leading decimal zeroes in the first numeric digit by
2206            // decrementing the exponent.
2207            exp -= DEC_DIGITS - (self.digits[0] as f64).log10() as i32;
2208            exp
2209        } else {
2210            // If has no digits, then it must be zero.
2211            //
2212            // Zero doesn't technically have a meaningful exponent in normalised
2213            // notation, but we just display the exponent as zero for consistency
2214            // of output.
2215            0
2216        };
2217
2218        // The denominator is set to 10 raised to the power of the exponent.
2219        //
2220        // We then divide var by the denominator to get the significand, rounding
2221        // to rscale decimal digits in the process.
2222        let denom_scale = if exponent < 0 { -exponent } else { 0 };
2223
2224        let denominator = TEN
2225            .power_int(exponent, denom_scale)
2226            .expect("attempt to multiply with overflow");
2227        let significand = self
2228            .div_common(&denominator, rscale, true)
2229            .expect(DIVIDE_BY_ZERO_MSG);
2230
2231        if lower_exp {
2232            write!(f, "{}e{:<+03}", significand, exponent)
2233        } else {
2234            write!(f, "{}E{:<+03}", significand, exponent)
2235        }
2236    }
2237
2238    /// Returns the appropriate result scale for scientific notation representation.
2239    pub fn select_sci_scale(&self) -> i32 {
2240        // 1 => (1, 0)
2241        // 10 => (1, 1)
2242        // 11 => (2, 0)
2243        // 100 => (1, 2)
2244        // 101 => (3, 0)
2245        // 1010 => (3, 1)
2246        fn count_zeros(digit: NumericDigit) -> (i32, i32) {
2247            let mut val = digit;
2248            let mut n = 0;
2249            let mut zero = 0;
2250
2251            for _ in 0..DEC_DIGITS {
2252                let d = val % 10;
2253                val /= 10;
2254
2255                if d == 0 && n == 0 {
2256                    // all previous d are zeros.
2257                    zero += 1;
2258                } else {
2259                    n += 1;
2260                }
2261
2262                if val == 0 {
2263                    break;
2264                }
2265            }
2266
2267            (n, zero)
2268        }
2269
2270        let digits = self.digits();
2271
2272        // find first non-zero digit from front to end
2273        let (i, digit) = match digits.iter().enumerate().find(|(_, &d)| d != 0) {
2274            Some((i, &digit)) => (i, digit),
2275            None => {
2276                // all digits are 0
2277                return 0;
2278            }
2279        };
2280
2281        // find first non-zero digit from end to front
2282        let (ri, rdigit) = match digits.iter().enumerate().rfind(|(_, &d)| d != 0) {
2283            Some((ri, &rdigit)) => (ri, rdigit),
2284            None => {
2285                // all digits are 0, actually unreachable!
2286                return 0;
2287            }
2288        };
2289
2290        debug_assert!(i <= ri);
2291
2292        if i == ri {
2293            // only one digit
2294            let (n, _) = count_zeros(digit);
2295            return n - 1;
2296        }
2297
2298        let (n, zero) = count_zeros(digit);
2299        let (_, rzero) = count_zeros(rdigit);
2300
2301        let front = n + zero;
2302        let end = DEC_DIGITS - rzero;
2303
2304        front + end + (ri - i - 1) as i32 * DEC_DIGITS - 1
2305    }
2306
2307    /// Make `self` to be a result numeric.
2308    /// We assume that `self` is not overflowed.
2309    #[inline]
2310    pub fn make_result_no_overflow(mut self) -> NumericBuf {
2311        debug_assert!(!self.is_nan());
2312        debug_assert!(
2313            self.weight <= NUMERIC_WEIGHT_MAX as i32
2314                || self.weight >= NUMERIC_WEIGHT_MIN as i32
2315                || self.dscale <= NUMERIC_DSCALE_MAX as i32
2316                || self.dscale >= 0
2317        );
2318
2319        self.strip();
2320
2321        self.into_numeric_buf()
2322    }
2323
2324    /// Make `self` to be a result numeric.
2325    /// Returns `None` if overflows.
2326    #[inline]
2327    pub fn make_result(self) -> Option<NumericBuf> {
2328        debug_assert!(!self.is_nan());
2329        debug_assert!(self.dscale >= 0);
2330
2331        if self.weight > NUMERIC_WEIGHT_MAX as i32
2332            || self.weight < NUMERIC_WEIGHT_MIN as i32
2333            || self.dscale > NUMERIC_DSCALE_MAX as i32
2334        {
2335            return None;
2336        }
2337
2338        Some(self.make_result_no_overflow())
2339    }
2340
2341    /// Negate this value.
2342    #[inline]
2343    pub fn negate(&mut self) {
2344        debug_assert!(!self.is_nan());
2345
2346        if self.ndigits > 0 {
2347            if self.is_positive() {
2348                self.sign = NUMERIC_NEG;
2349            } else if self.is_negative() {
2350                self.sign = NUMERIC_POS;
2351            }
2352        }
2353    }
2354
2355    /// Returns a numeric that represents the sign of self.
2356    /// * -1 if `self` is less than 0
2357    /// * 0 if `self` is equal to 0
2358    /// * 1 if `self` is greater than zero
2359    /// * `NaN` if `self` is `NaN`
2360    #[inline]
2361    pub fn signum(&self) -> Self {
2362        debug_assert!(!self.is_nan());
2363
2364        if self.ndigits == 0 {
2365            ZERO.clone()
2366        } else {
2367            let mut result = ONE.clone();
2368            result.sign = self.sign;
2369            result
2370        }
2371    }
2372
2373    /// Increment `self` by one.
2374    #[inline]
2375    pub fn inc(&self) -> Self {
2376        debug_assert!(!self.is_nan());
2377
2378        // Compute the result and return it
2379        self.add_common(&ONE)
2380    }
2381
2382    /// Checked numeric division.
2383    /// Computes `self / other`, returning `None` if `other == 0`.
2384    #[inline]
2385    pub fn checked_div(&self, other: &Self) -> Option<Self> {
2386        debug_assert!(!self.is_nan());
2387        debug_assert!(!other.is_nan());
2388
2389        // Select scale for division result
2390        let rscale = self.select_div_scale(&other);
2391
2392        self.div_common(&other, rscale, true)
2393    }
2394
2395    /// Computes `self / other`, truncating the result to an integer.
2396    ///
2397    /// Returns `None` if `other == 0`.
2398    #[inline]
2399    pub fn checked_div_trunc(&self, other: &Self) -> Option<Self> {
2400        debug_assert!(!self.is_nan());
2401        debug_assert!(!other.is_nan());
2402
2403        self.div_common(&other, 0, false)
2404    }
2405
2406    /// Round a value to have `scale` digits after the decimal point.
2407    /// We allow negative `scale`, implying rounding before the decimal
2408    /// point --- Oracle interprets rounding that way.
2409    #[inline]
2410    pub fn round(&mut self, scale: i32) {
2411        debug_assert!(!self.is_nan());
2412
2413        // Limit the scale value to avoid possible overflow in calculations
2414        let rscale = scale
2415            .max(-NUMERIC_MAX_DISPLAY_SCALE)
2416            .min(NUMERIC_MAX_DISPLAY_SCALE);
2417
2418        self.round_common(rscale);
2419
2420        // We don't allow negative output dscale
2421        if rscale < 0 {
2422            self.dscale = 0;
2423        }
2424    }
2425
2426    /// Truncate a value to have `scale` digits after the decimal point.
2427    /// We allow negative `scale`, implying a truncation before the decimal
2428    /// point --- Oracle interprets truncation that way.
2429    #[inline]
2430    pub fn trunc(&mut self, scale: i32) {
2431        debug_assert!(!self.is_nan());
2432
2433        // Limit the scale value to avoid possible overflow in calculations
2434        let rscale = scale
2435            .max(-NUMERIC_MAX_DISPLAY_SCALE)
2436            .min(NUMERIC_MAX_DISPLAY_SCALE);
2437
2438        self.trunc_common(rscale);
2439
2440        // We don't allow negative output dscale
2441        if rscale < 0 {
2442            self.dscale = 0;
2443        }
2444    }
2445
2446    /// Return the smallest integer greater than or equal to the argument.
2447    #[inline]
2448    pub fn ceil(&self) -> Self {
2449        debug_assert!(!self.is_nan());
2450        self.ceil_common()
2451    }
2452
2453    /// Return the largest integer equal to or less than the argument.
2454    #[inline]
2455    pub fn floor(&self) -> Self {
2456        debug_assert!(!self.is_nan());
2457        self.floor_common()
2458    }
2459
2460    /// Compute the absolute value of `self`.
2461    #[inline]
2462    pub fn abs(&mut self) {
2463        debug_assert!(!self.is_nan());
2464
2465        if self.is_negative() {
2466            self.sign = NUMERIC_POS;
2467        }
2468    }
2469
2470    /// Compute the square root of a numeric.
2471    #[inline]
2472    pub fn sqrt(&self) -> Self {
2473        debug_assert!(!self.is_negative());
2474        debug_assert!(!self.is_nan());
2475
2476        // Determine the result scale.
2477        // We choose a scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
2478        // but in any case not less than the input's dscale.
2479
2480        // Assume the input was normalized, so arg.weight is accurate
2481        let sweight = (self.weight + 1) * DEC_DIGITS / 2 - 1;
2482
2483        let rscale = (NUMERIC_MIN_SIG_DIGITS - sweight)
2484            .max(self.dscale)
2485            .max(NUMERIC_MIN_DISPLAY_SCALE)
2486            .min(NUMERIC_MAX_DISPLAY_SCALE);
2487
2488        self.sqrt_common(rscale)
2489    }
2490
2491    /// Compute the natural logarithm of `self`.
2492    ///
2493    /// # Panics
2494    /// Panics if `self <= 0`.
2495    #[inline]
2496    pub fn ln(&self) -> Self {
2497        debug_assert!(!self.is_nan());
2498
2499        let cmp = self.cmp_common(&ZERO);
2500        assert_ne!(cmp, 0, "cannot take logarithm of zero");
2501        assert!(cmp > 0, "cannot take logarithm of a negative number");
2502
2503        // Estimated dweight of logarithm
2504        let ln_dweight = self.estimate_ln_dweight();
2505
2506        let rscale = (NUMERIC_MIN_SIG_DIGITS - ln_dweight)
2507            .max(self.dscale)
2508            .max(NUMERIC_MIN_DISPLAY_SCALE)
2509            .min(NUMERIC_MAX_DISPLAY_SCALE);
2510
2511        self.ln_common(rscale)
2512    }
2513
2514    /// Compute the logarithm of `self` in a given base.
2515    ///
2516    /// # Panics
2517    /// Panics if `self <= 0` or `base <= 0`.
2518    #[inline]
2519    pub fn log(&self, base: &Self) -> Self {
2520        debug_assert!(!self.is_nan());
2521        debug_assert!(!base.is_nan());
2522
2523        let cmp = self.cmp_common(&ZERO);
2524        assert_ne!(cmp, 0, "cannot take logarithm of zero");
2525        assert!(cmp > 0, "cannot take logarithm of a negative number");
2526
2527        let cmp = base.cmp_common(&ZERO);
2528        assert_ne!(cmp, 0, "cannot take logarithm of zero");
2529        assert!(cmp > 0, "cannot take logarithm of a negative number");
2530
2531        //  Call log_common() to compute and return the result;
2532        //	note it handles scale selection itself.
2533        self.log_common(&base)
2534    }
2535
2536    /// Compute the base 2 logarithm of `self`.
2537    ///
2538    /// # Panics
2539    /// Panics if `self <= 0`.
2540    #[inline]
2541    pub fn log2(&self) -> Self {
2542        self.log(&TWO)
2543    }
2544
2545    /// Compute the base 10 logarithm of `self`.
2546    ///
2547    /// # Panics
2548    /// Panics if `self <= 0`.
2549    #[inline]
2550    pub fn log10(&self) -> Self {
2551        self.log(&TEN)
2552    }
2553
2554    /// Raise e to the power of `self` (`e^(self)`).
2555    ///
2556    /// Returns `None` if overflows.
2557    ///
2558    #[inline]
2559    pub fn exp(&self) -> Option<Self> {
2560        debug_assert!(!self.is_nan());
2561
2562        // Determine the result scale.  We choose a scale
2563        // to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
2564        // but in any case not less than the input's dscale.
2565
2566        let mut val: f64 = TryFrom::try_from(self).unwrap();
2567
2568        // log10(result) = num * log10(e), so this is approximately the decimal
2569        // weight of the result:
2570        val *= LOG10_E;
2571
2572        // limit to something that won't cause integer overflow
2573        val = val
2574            .max(-NUMERIC_MAX_RESULT_SCALE as f64)
2575            .min(NUMERIC_MAX_RESULT_SCALE as f64);
2576
2577        let rscale = (NUMERIC_MIN_SIG_DIGITS - val as i32)
2578            .max(self.dscale)
2579            .max(NUMERIC_MIN_DISPLAY_SCALE)
2580            .min(NUMERIC_MAX_DISPLAY_SCALE);
2581
2582        // Let exp_common() do the calculation and return the result.
2583        self.exp_common(rscale)
2584    }
2585
2586    /// Raise `self` to the power of `exp`.
2587    ///
2588    /// Returns `None` if overflows.
2589    ///
2590    /// # Panics
2591    /// if arguments are invalid:
2592    ///   - `self` is zero and `exp` is less than zero
2593    ///   - `self` is less than zero and `exp` is not a integer.
2594    #[inline]
2595    pub fn pow(&self, exp: &Self) -> Option<Self> {
2596        // Handle NaN cases.  We follow the POSIX spec for pow(3), which says that
2597        // NaN ^ 0 = 1, and 1 ^ NaN = 1, while all other cases with NaN inputs
2598        // yield NaN (with no error).
2599        if self.is_nan() {
2600            if !exp.is_nan() && exp.cmp_common(&ZERO) == 0 {
2601                return Some(ONE.clone());
2602            }
2603            return Some(Self::nan());
2604        } else if exp.is_nan() {
2605            if self.cmp_common(&ONE) == 0 {
2606                return Some(ONE.clone());
2607            }
2608            return Some(Self::nan());
2609        }
2610
2611        if self.cmp_common(&ZERO) == 0 && exp.cmp_common(&ZERO) < 0 {
2612            panic!("zero raised to a negative power is undefined")
2613        }
2614
2615        let mut exp_trunc = exp.clone();
2616        exp_trunc.trunc_common(0);
2617
2618        if self.cmp_common(&ZERO) < 0 && exp.cmp_common(&exp_trunc) != 0 {
2619            panic!("a negative number raised to a non-integer power yields a complex result")
2620        }
2621
2622        // Call power_common() to compute and return the result; note it handles
2623        // scale selection itself.
2624        self.power_common(&exp)
2625    }
2626
2627    /// Do bounds checking and rounding according to `typmod`.
2628    ///
2629    /// Returns true if overflows.
2630    ///
2631    /// Notes that no matter whether overflows, `self` will be rounded.
2632    pub fn apply_typmod(&mut self, typmod: Typmod) -> bool {
2633        // Do nothing if we have a default typmod (-1)
2634        if typmod.value() < VAR_HEADER_SIZE {
2635            return false;
2636        }
2637
2638        let (precision, scale) = typmod.extract();
2639        let max_digits = precision - scale;
2640
2641        // Round to target scale (and set self.dscale)
2642        self.round_common(scale);
2643
2644        // Check for overflow - note we can't do this before rounding, because
2645        // rounding could raise the weight.  Also note that the self's weight could
2646        // be inflated by leading zeroes, which will be stripped before storage
2647        // but perhaps might not have been yet. In any case, we must recognize a
2648        // true zero, whose weight doesn't mean anything.
2649        let mut ddigits = (self.weight + 1) * DEC_DIGITS;
2650        if ddigits > max_digits {
2651            // Determine true weight; and check for all-zero result
2652            for &dig in self.digits().iter() {
2653                if dig != 0 {
2654                    // Adjust for any high-order decimal zero digits
2655                    debug_assert_eq!(DEC_DIGITS, 4);
2656                    if dig < 10 {
2657                        ddigits -= 3;
2658                    } else if dig < 100 {
2659                        ddigits -= 2;
2660                    } else if dig < 1000 {
2661                        ddigits -= 1;
2662                    }
2663
2664                    if ddigits > max_digits {
2665                        return true;
2666                    }
2667
2668                    break;
2669                }
2670
2671                ddigits -= DEC_DIGITS;
2672            }
2673        }
2674
2675        false
2676    }
2677
2678    /// Returns a normalized string, suppressing insignificant
2679    /// trailing zeroes and then any trailing decimal point.
2680    ///
2681    /// The intent of this is to produce strings that are equal
2682    /// if and only if the input numeric values compare equal.
2683    pub fn normalize(&self) -> String {
2684        if self.is_nan() {
2685            return String::from("NaN");
2686        }
2687
2688        let mut s = self.to_string();
2689
2690        // If there's no decimal point, there's certainly nothing to remove.
2691        if s.find('.').is_some() {
2692            // Back up over trailing fractional zeroes.  Since there is a decimal
2693            // point, this loop will terminate safely.
2694            let mut new_len = s.len();
2695            let bytes = s.as_bytes();
2696            let count_zeros = bytes.iter().rev().take_while(|i| **i == b'0').count();
2697            new_len -= count_zeros;
2698
2699            // We want to get rid of the decimal point too, if it's now last.
2700            if bytes[new_len - 1] == b'.' {
2701                new_len -= 1;
2702            }
2703
2704            // Delete whatever we backed up over.
2705            s.truncate(new_len);
2706        }
2707
2708        s
2709    }
2710
2711    /// Compute factorial.
2712    ///
2713    /// Returns `None` if overflows.
2714    pub fn factorial(num: i64) -> Option<Self> {
2715        if num <= 1 {
2716            return Some(ONE.clone());
2717        }
2718
2719        // Fail immediately if the result would overflow
2720        if num > 32177 {
2721            // value overflows numeric format
2722            return None;
2723        }
2724
2725        let mut result: NumericVar = From::from(num);
2726
2727        for n in (2..num).rev() {
2728            let fact = From::from(n);
2729            result = result.mul_common(&fact, 0);
2730        }
2731
2732        Some(result)
2733    }
2734}
2735
2736impl<'a> fmt::Display for NumericVar<'a> {
2737    #[inline]
2738    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
2739        self.write(f)
2740    }
2741}