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}