github.com/cockroachdb/apd/v3@v3.2.0/context.go (about) 1 // Copyright 2016 The Cockroach Authors. 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 12 // implied. See the License for the specific language governing 13 // permissions and limitations under the License. 14 15 package apd 16 17 import ( 18 "errors" 19 "fmt" 20 "math" 21 ) 22 23 // Context maintains options for Decimal operations. It can safely be used 24 // concurrently, but not modified concurrently. Arguments for any method 25 // can safely be used as both result and operand. 26 type Context struct { 27 // Precision is the number of places to round during rounding; this is 28 // effectively the total number of digits (before and after the decimal 29 // point). 30 Precision uint32 31 // MaxExponent specifies the largest effective exponent. The 32 // effective exponent is the value of the Decimal in scientific notation. That 33 // is, for 10e2, the effective exponent is 3 (1.0e3). Zero (0) is not a special 34 // value; it does not disable this check. 35 MaxExponent int32 36 // MinExponent is similar to MaxExponent, but for the smallest effective 37 // exponent. 38 MinExponent int32 39 // Traps are the conditions which will trigger an error result if the 40 // corresponding Flag condition occurred. 41 Traps Condition 42 // Rounding specifies the Rounder to use during rounding. RoundHalfUp is used if 43 // empty or not present in Roundings. 44 Rounding Rounder 45 } 46 47 const ( 48 // DefaultTraps is the default trap set used by BaseContext. 49 DefaultTraps = SystemOverflow | 50 SystemUnderflow | 51 Overflow | 52 Underflow | 53 Subnormal | 54 DivisionUndefined | 55 DivisionByZero | 56 DivisionImpossible | 57 InvalidOperation 58 59 errZeroPrecisionStr = "Context may not have 0 Precision for this operation" 60 ) 61 62 // BaseContext is a useful default Context. Should not be mutated. 63 var BaseContext = Context{ 64 // Disable rounding. 65 Precision: 0, 66 // MaxExponent and MinExponent are set to the packages's limits. 67 MaxExponent: MaxExponent, 68 MinExponent: MinExponent, 69 // Default error conditions. 70 Traps: DefaultTraps, 71 } 72 73 // WithPrecision returns a copy of c but with the specified precision. 74 func (c *Context) WithPrecision(p uint32) *Context { 75 r := new(Context) 76 *r = *c 77 r.Precision = p 78 return r 79 } 80 81 // goError converts flags into an error based on c.Traps. 82 //gcassert:inline 83 func (c *Context) goError(flags Condition) (Condition, error) { 84 if flags == 0 { 85 return flags, nil 86 } 87 return flags.GoError(c.Traps) 88 } 89 90 // etiny returns the smallest value an Exponent can contain. 91 func (c *Context) etiny() int32 { 92 return c.MinExponent - int32(c.Precision) + 1 93 } 94 95 // shouldSetAsNaN determines whether setAsNaN should be called, given 96 // the provided values, where x is required and y is optional. It is 97 // split from setAsNaN to permit inlining of this function. 98 //gcassert:inline 99 func (c *Context) shouldSetAsNaN(x, y *Decimal) bool { 100 return x.Form == NaNSignaling || x.Form == NaN || 101 (y != nil && (y.Form == NaNSignaling || y.Form == NaN)) 102 } 103 104 // setAsNaN sets d to the first NaNSignaling, or otherwise first NaN, of 105 // x and y. x is required, y is optional. Expects one of the two inputs 106 // to be NaN. 107 func (c *Context) setAsNaN(d *Decimal, x, y *Decimal) (Condition, error) { 108 var nan *Decimal 109 // Per the method contract, NaNSignaling takes precedence over NaN. 110 if x.Form == NaNSignaling { 111 nan = x 112 } else if y != nil && y.Form == NaNSignaling { 113 nan = y 114 } else if x.Form == NaN { 115 nan = x 116 } else if y != nil && y.Form == NaN { 117 nan = y 118 } else { 119 return 0, errors.New("no NaN value found; was shouldSetAsNaN called?") 120 } 121 d.Set(nan) 122 var res Condition 123 if nan.Form == NaNSignaling { 124 res = InvalidOperation 125 d.Form = NaN 126 } 127 _, err := c.goError(res) 128 return res, err 129 } 130 131 func (c *Context) add(d, x, y *Decimal, subtract bool) (Condition, error) { 132 if c.shouldSetAsNaN(x, y) { 133 return c.setAsNaN(d, x, y) 134 } 135 xn := x.Negative 136 yn := y.Negative != subtract 137 if xi, yi := x.Form == Infinite, y.Form == Infinite; xi || yi { 138 if xi && yi && xn != yn { 139 d.Set(decimalNaN) 140 return c.goError(InvalidOperation) 141 } else if xi { 142 d.Set(x) 143 } else { 144 d.Set(decimalInfinity) 145 d.Negative = yn 146 } 147 return 0, nil 148 } 149 var tmp BigInt 150 a, b, s, err := upscale(x, y, &tmp) 151 if err != nil { 152 return 0, fmt.Errorf("add: %w", err) 153 } 154 d.Negative = xn 155 if xn == yn { 156 d.Coeff.Add(a, b) 157 } else { 158 d.Coeff.Sub(a, b) 159 switch d.Coeff.Sign() { 160 case -1: 161 d.Negative = !d.Negative 162 d.Coeff.Neg(&d.Coeff) 163 case 0: 164 d.Negative = c.Rounding == RoundFloor 165 } 166 } 167 d.Exponent = s 168 d.Form = Finite 169 res := c.round(d, d) 170 return c.goError(res) 171 } 172 173 // Add sets d to the sum x+y. 174 func (c *Context) Add(d, x, y *Decimal) (Condition, error) { 175 return c.add(d, x, y, false) 176 } 177 178 // Sub sets d to the difference x-y. 179 func (c *Context) Sub(d, x, y *Decimal) (Condition, error) { 180 return c.add(d, x, y, true) 181 } 182 183 // Abs sets d to |x| (the absolute value of x). 184 func (c *Context) Abs(d, x *Decimal) (Condition, error) { 185 if c.shouldSetAsNaN(x, nil) { 186 return c.setAsNaN(d, x, nil) 187 } 188 d.Abs(x) 189 res := c.round(d, d) 190 return c.goError(res) 191 } 192 193 // Neg sets d to -x. 194 func (c *Context) Neg(d, x *Decimal) (Condition, error) { 195 if c.shouldSetAsNaN(x, nil) { 196 return c.setAsNaN(d, x, nil) 197 } 198 d.Neg(x) 199 res := c.round(d, d) 200 return c.goError(res) 201 } 202 203 // Mul sets d to the product x*y. 204 func (c *Context) Mul(d, x, y *Decimal) (Condition, error) { 205 if c.shouldSetAsNaN(x, y) { 206 return c.setAsNaN(d, x, y) 207 } 208 // The sign of the result is the exclusive or of the signs of the operands. 209 neg := x.Negative != y.Negative 210 if xi, yi := x.Form == Infinite, y.Form == Infinite; xi || yi { 211 if x.IsZero() || y.IsZero() { 212 d.Set(decimalNaN) 213 return c.goError(InvalidOperation) 214 } 215 d.Set(decimalInfinity) 216 d.Negative = neg 217 return 0, nil 218 } 219 220 d.Coeff.Mul(&x.Coeff, &y.Coeff) 221 d.Negative = neg 222 d.Form = Finite 223 res := d.setExponent(c, unknownNumDigits, 0, int64(x.Exponent), int64(y.Exponent)) 224 res |= c.round(d, d) 225 return c.goError(res) 226 } 227 228 func (c *Context) quoSpecials(d, x, y *Decimal, canClamp bool) (bool, Condition, error) { 229 if c.shouldSetAsNaN(x, y) { 230 res, err := c.setAsNaN(d, x, y) 231 return true, res, err 232 } 233 234 // The sign of the result is the exclusive or of the signs of the operands. 235 neg := x.Negative != y.Negative 236 if xi, yi := x.Form == Infinite, y.Form == Infinite; xi || yi { 237 var res Condition 238 if xi && yi { 239 d.Set(decimalNaN) 240 res = InvalidOperation 241 } else if xi { 242 d.Set(decimalInfinity) 243 d.Negative = neg 244 } else { 245 d.SetInt64(0) 246 d.Negative = neg 247 if canClamp { 248 d.Exponent = c.etiny() 249 res = Clamped 250 } 251 } 252 res, err := c.goError(res) 253 return true, res, err 254 } 255 256 if y.IsZero() { 257 var res Condition 258 if x.IsZero() { 259 res |= DivisionUndefined 260 d.Set(decimalNaN) 261 } else { 262 res |= DivisionByZero 263 d.Set(decimalInfinity) 264 d.Negative = neg 265 } 266 res, err := c.goError(res) 267 return true, res, err 268 } 269 270 if c.Precision == 0 { 271 // 0 precision is disallowed because we compute the required number of digits 272 // during the 10**x calculation using the precision. 273 return true, 0, errors.New(errZeroPrecisionStr) 274 } 275 276 return false, 0, nil 277 } 278 279 // Quo sets d to the quotient x/y for y != 0. c.Precision must be > 0. If an 280 // exact division is required, use a context with high precision and verify 281 // it was exact by checking the Inexact flag on the return Condition. 282 func (c *Context) Quo(d, x, y *Decimal) (Condition, error) { 283 if set, res, err := c.quoSpecials(d, x, y, true); set { 284 return res, err 285 } 286 287 // The sign of the result is the exclusive or of the signs of the operands. 288 neg := x.Negative != y.Negative 289 290 // Shift the resulting exponent by the difference between the dividend and 291 // the divisor's exponent after performing arithmetic on the coefficients. 292 shift := int64(x.Exponent - y.Exponent) 293 294 var res Condition 295 if x.IsZero() { 296 d.Set(decimalZero) 297 d.Negative = neg 298 res |= d.setExponent(c, unknownNumDigits, res, shift) 299 return c.goError(res) 300 } 301 302 var dividend, divisor BigInt 303 dividend.Abs(&x.Coeff) 304 divisor.Abs(&y.Coeff) 305 306 // The operand coefficients are adjusted so that the coefficient of the 307 // dividend is greater than or equal to the coefficient of the divisor and 308 // is also less than ten times the coefficient of the divisor. While doing 309 // so, keep track of how far the two have been adjusted. 310 ndDividend := NumDigits(÷nd) 311 ndDivisor := NumDigits(&divisor) 312 ndDiff := ndDividend - ndDivisor 313 var tmpE BigInt 314 if ndDiff < 0 { 315 // numDigits(dividend) < numDigits(divisor), multiply dividend by 10^diff. 316 dividend.Mul(÷nd, tableExp10(-ndDiff, &tmpE)) 317 } else if ndDiff > 0 { 318 // numDigits(dividend) > numDigits(divisor), multiply divisor by 10^diff. 319 divisor.Mul(&divisor, tableExp10(ndDiff, &tmpE)) 320 } 321 adjCoeffs := -ndDiff 322 if dividend.Cmp(&divisor) < 0 { 323 // dividend < divisor, multiply dividend by 10. 324 dividend.Mul(÷nd, bigTen) 325 adjCoeffs++ 326 } 327 328 // In order to compute the decimal remainder part, add enough 0s to the 329 // numerator to accurately round with the given precision. -1 because the 330 // previous adjustment ensured that the dividend is already greater than or 331 // equal to the divisor, so the result will always be greater than or equal 332 // to 1. 333 adjExp10 := int64(c.Precision - 1) 334 dividend.Mul(÷nd, tableExp10(adjExp10, &tmpE)) 335 336 // Perform the division. 337 var rem BigInt 338 d.Coeff.QuoRem(÷nd, &divisor, &rem) 339 d.Form = Finite 340 d.Negative = neg 341 342 // If there was a remainder, it is taken into account for rounding. To do 343 // so, we determine whether the remainder was more or less than half of the 344 // divisor and round accordingly. 345 nd := NumDigits(&d.Coeff) 346 if rem.Sign() != 0 { 347 // Use the adjusted exponent to determine if we are Subnormal. 348 // If so, don't round. This computation of adj and the check 349 // against MinExponent mirrors the logic in setExponent. 350 adj := shift + (-adjCoeffs) + (-adjExp10) + nd - 1 351 if adj >= int64(c.MinExponent) { 352 res |= Inexact | Rounded 353 rem.Mul(&rem, bigTwo) 354 half := rem.Cmp(&divisor) 355 if c.Rounding.ShouldAddOne(&d.Coeff, d.Negative, half) { 356 d.Coeff.Add(&d.Coeff, bigOne) 357 // The coefficient changed, so recompute num digits in 358 // setExponent. 359 nd = unknownNumDigits 360 } 361 } 362 } 363 364 res |= d.setExponent(c, nd, res, shift, -adjCoeffs, -adjExp10) 365 return c.goError(res) 366 } 367 368 // QuoInteger sets d to the integer part of the quotient x/y. If the result 369 // cannot fit in d.Precision digits, an error is returned. 370 func (c *Context) QuoInteger(d, x, y *Decimal) (Condition, error) { 371 if set, res, err := c.quoSpecials(d, x, y, false); set { 372 return res, err 373 } 374 375 // The sign of the result is the exclusive or of the signs of the operands. 376 neg := x.Negative != y.Negative 377 var res Condition 378 379 var tmp BigInt 380 a, b, _, err := upscale(x, y, &tmp) 381 if err != nil { 382 return 0, fmt.Errorf("QuoInteger: %w", err) 383 } 384 d.Coeff.Quo(a, b) 385 d.Form = Finite 386 if d.NumDigits() > int64(c.Precision) { 387 d.Set(decimalNaN) 388 res |= DivisionImpossible 389 } 390 d.Exponent = 0 391 d.Negative = neg 392 return c.goError(res) 393 } 394 395 // Rem sets d to the remainder part of the quotient x/y. If 396 // the integer part cannot fit in d.Precision digits, an error is returned. 397 func (c *Context) Rem(d, x, y *Decimal) (Condition, error) { 398 if c.shouldSetAsNaN(x, y) { 399 return c.setAsNaN(d, x, y) 400 } 401 402 if x.Form != Finite { 403 d.Set(decimalNaN) 404 return c.goError(InvalidOperation) 405 } 406 if y.Form == Infinite { 407 d.Set(x) 408 return 0, nil 409 } 410 411 var res Condition 412 if y.IsZero() { 413 if x.IsZero() { 414 res |= DivisionUndefined 415 } else { 416 res |= InvalidOperation 417 } 418 d.Set(decimalNaN) 419 return c.goError(res) 420 } 421 var tmp1 BigInt 422 a, b, s, err := upscale(x, y, &tmp1) 423 if err != nil { 424 return 0, fmt.Errorf("Rem: %w", err) 425 } 426 var tmp2 BigInt 427 tmp2.QuoRem(a, b, &d.Coeff) 428 if NumDigits(&tmp2) > int64(c.Precision) { 429 d.Set(decimalNaN) 430 return c.goError(DivisionImpossible) 431 } 432 d.Form = Finite 433 d.Exponent = s 434 // The sign of the result is sign if the dividend. 435 d.Negative = x.Negative 436 res |= c.round(d, d) 437 return c.goError(res) 438 } 439 440 func (c *Context) rootSpecials(d, x *Decimal, factor int32) (bool, Condition, error) { 441 if c.shouldSetAsNaN(x, nil) { 442 res, err := c.setAsNaN(d, x, nil) 443 return true, res, err 444 } 445 if x.Form == Infinite { 446 if x.Negative { 447 d.Set(decimalNaN) 448 res, err := c.goError(InvalidOperation) 449 return true, res, err 450 } 451 d.Set(decimalInfinity) 452 return true, 0, nil 453 } 454 455 switch x.Sign() { 456 case -1: 457 if factor%2 == 0 { 458 d.Set(decimalNaN) 459 res, err := c.goError(InvalidOperation) 460 return true, res, err 461 } 462 case 0: 463 d.Set(x) 464 d.Exponent /= factor 465 return true, 0, nil 466 } 467 return false, 0, nil 468 } 469 470 // Sqrt sets d to the square root of x. Sqrt uses the Babylonian method 471 // for computing the square root, which uses O(log p) steps for p digits 472 // of precision. 473 func (c *Context) Sqrt(d, x *Decimal) (Condition, error) { 474 // See: Properly Rounded Variable Precision Square Root by T. E. Hull 475 // and A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, 476 // pp229–237, ACM, September 1985. 477 478 if set, res, err := c.rootSpecials(d, x, 2); set { 479 return res, err 480 } 481 482 // workp is the number of digits of precision used. We use the same precision 483 // as in decNumber. 484 workp := c.Precision + 1 485 if nd := uint32(x.NumDigits()); workp < nd { 486 workp = nd 487 } 488 if workp < 7 { 489 workp = 7 490 } 491 492 var f Decimal 493 f.Set(x) 494 nd := x.NumDigits() 495 e := nd + int64(x.Exponent) 496 f.Exponent = int32(-nd) 497 nc := c.WithPrecision(workp) 498 nc.Rounding = RoundHalfEven 499 ed := MakeErrDecimal(nc) 500 // Set approx to the first guess, based on whether e (the exponent part of x) 501 // is odd or even. 502 var approx Decimal 503 if e%2 == 0 { 504 approx.SetFinite(819, -3) 505 ed.Mul(&approx, &approx, &f) 506 ed.Add(&approx, &approx, New(259, -3)) 507 } else { 508 f.Exponent-- 509 e++ 510 approx.SetFinite(259, -2) 511 ed.Mul(&approx, &approx, &f) 512 ed.Add(&approx, &approx, New(819, -4)) 513 } 514 515 // Now we repeatedly improve approx. Our precision improves quadratically, 516 // which we keep track of in p. 517 p := uint32(3) 518 var tmp Decimal 519 520 // The algorithm in the paper says to use c.Precision + 2. decNumber uses 521 // workp + 2. But we use workp + 5 to make the tests pass. This means it is 522 // possible there are inputs we don't compute correctly and could be 1ulp off. 523 for maxp := workp + 5; p != maxp; { 524 p = 2*p - 2 525 if p > maxp { 526 p = maxp 527 } 528 nc.Precision = p 529 // tmp = f / approx 530 ed.Quo(&tmp, &f, &approx) 531 // tmp = approx + f / approx 532 ed.Add(&tmp, &tmp, &approx) 533 // approx = 0.5 * (approx + f / approx) 534 ed.Mul(&approx, &tmp, decimalHalf) 535 } 536 537 // At this point the paper says: "approx is now within 1 ulp of the properly 538 // rounded square root off; to ensure proper rounding, compare squares of 539 // (approx - l/2 ulp) and (approx + l/2 ulp) with f." We originally implemented 540 // the proceeding algorithm from the paper. However none of the tests take 541 // any of the branches that modify approx. Our best guess as to why is that 542 // since we use workp + 5 instead of the + 2 as described in the paper, 543 // we are more accurate than this section needed to account for. Thus, 544 // we have removed the block from this implementation. 545 546 if err := ed.Err(); err != nil { 547 return 0, err 548 } 549 550 d.Set(&approx) 551 d.Exponent += int32(e / 2) 552 nc.Precision = c.Precision 553 nc.Rounding = RoundHalfEven 554 res := nc.round(d, d) 555 return nc.goError(res) 556 } 557 558 // Cbrt sets d to the cube root of x. 559 func (c *Context) Cbrt(d, x *Decimal) (Condition, error) { 560 // The cube root calculation is implemented using Newton-Raphson 561 // method. We start with an initial estimate for cbrt(d), and 562 // then iterate: 563 // x_{n+1} = 1/3 * ( 2 * x_n + (d / x_n / x_n) ). 564 565 if set, res, err := c.rootSpecials(d, x, 3); set { 566 return res, err 567 } 568 569 var ax, z Decimal 570 ax.Abs(x) 571 z.Set(&ax) 572 neg := x.Negative 573 nc := BaseContext.WithPrecision(c.Precision*2 + 2) 574 ed := MakeErrDecimal(nc) 575 exp8 := 0 576 577 // See: Turkowski, Ken. Computing the cube root. technical report, Apple 578 // Computer, 1998. 579 // https://people.freebsd.org/~lstewart/references/apple_tr_kt32_cuberoot.pdf 580 // 581 // Computing the cube root of any number is reduced to computing 582 // the cube root of a number between 0.125 and 1. After the next loops, 583 // x = z * 8^exp8 will hold. 584 for z.Cmp(decimalOneEighth) < 0 { 585 exp8-- 586 ed.Mul(&z, &z, decimalEight) 587 } 588 589 for z.Cmp(decimalOne) > 0 { 590 exp8++ 591 ed.Mul(&z, &z, decimalOneEighth) 592 } 593 594 // Use this polynomial to approximate the cube root between 0.125 and 1. 595 // z = (-0.46946116 * z + 1.072302) * z + 0.3812513 596 // It will serve as an initial estimate, hence the precision of this 597 // computation may only impact performance, not correctness. 598 var z0 Decimal 599 z0.Set(&z) 600 ed.Mul(&z, &z, decimalCbrtC1) 601 ed.Add(&z, &z, decimalCbrtC2) 602 ed.Mul(&z, &z, &z0) 603 ed.Add(&z, &z, decimalCbrtC3) 604 605 for ; exp8 < 0; exp8++ { 606 ed.Mul(&z, &z, decimalHalf) 607 } 608 609 for ; exp8 > 0; exp8-- { 610 ed.Mul(&z, &z, decimalTwo) 611 } 612 613 // Loop until convergence. 614 for loop := nc.newLoop("cbrt", &z, c.Precision+1, 1); ; { 615 // z = (2.0 * z0 + x / (z0 * z0) ) / 3.0; 616 z0.Set(&z) 617 ed.Mul(&z, &z, &z0) 618 ed.Quo(&z, &ax, &z) 619 ed.Add(&z, &z, &z0) 620 ed.Add(&z, &z, &z0) 621 ed.Quo(&z, &z, decimalThree) 622 623 if err := ed.Err(); err != nil { 624 return 0, err 625 } 626 if done, err := loop.done(&z); err != nil { 627 return 0, err 628 } else if done { 629 break 630 } 631 } 632 633 z0.Set(x) 634 res := c.round(d, &z) 635 res, err := c.goError(res) 636 d.Negative = neg 637 638 // Set z = d^3 to check for exactness. 639 ed.Mul(&z, d, d) 640 ed.Mul(&z, &z, d) 641 642 if err := ed.Err(); err != nil { 643 return 0, err 644 } 645 646 // Result is exact 647 if z0.Cmp(&z) == 0 { 648 return 0, nil 649 } 650 return res, err 651 } 652 653 func (c *Context) logSpecials(d, x *Decimal) (bool, Condition, error) { 654 if c.shouldSetAsNaN(x, nil) { 655 res, err := c.setAsNaN(d, x, nil) 656 return true, res, err 657 } 658 if x.Sign() < 0 { 659 d.Set(decimalNaN) 660 res, err := c.goError(InvalidOperation) 661 return true, res, err 662 } 663 if x.Form == Infinite { 664 d.Set(decimalInfinity) 665 return true, 0, nil 666 } 667 if x.Cmp(decimalZero) == 0 { 668 d.Set(decimalInfinity) 669 d.Negative = true 670 return true, 0, nil 671 } 672 if x.Cmp(decimalOne) == 0 { 673 d.Set(decimalZero) 674 return true, 0, nil 675 } 676 677 return false, 0, nil 678 } 679 680 // Ln sets d to the natural log of x. 681 func (c *Context) Ln(d, x *Decimal) (Condition, error) { 682 // See: On the Use of Iteration Methods for Approximating the Natural 683 // Logarithm, James F. Epperson, The American Mathematical Monthly, Vol. 96, 684 // No. 9, November 1989, pp. 831-835. 685 686 if set, res, err := c.logSpecials(d, x); set { 687 return res, err 688 } 689 690 // The internal precision needs to be a few digits higher because errors in 691 // series/iterations add up. 692 p := c.Precision + 2 693 694 nc := c.WithPrecision(p) 695 nc.Rounding = RoundHalfEven 696 ed := MakeErrDecimal(nc) 697 698 var tmp1, tmp2, tmp3, tmp4, z, resAdjust Decimal 699 z.Set(x) 700 701 // To get an initial estimate, we first reduce the input range to the interval 702 // [0.1, 1) by changing the exponent, and later adjust the result by a 703 // multiple of ln(10). 704 // 705 // However, this does not work well for z very close to 1, where the result is 706 // very close to 0. For example: 707 // z = 1.00001 708 // ln(z) = 0.00000999995 709 // If we adjust by 10: 710 // z' = 0.100001 711 // ln(z') = -2.30257509304 712 // ln(10) = 2.30258509299 713 // ln(z) = 0.00001000... 714 // 715 // The issue is that we may need to calculate a much higher (~double) 716 // precision for ln(z) because many of the significant digits cancel out. 717 // 718 // Halley's iteration has a similar problem when z is close to 1: in this case 719 // the correction term (exp(a_n) - z) needs to be calculated to a high 720 // precision. So for z close to 1 (before scaling) we use a power series 721 // instead (which converges very rapidly in this range). 722 723 // tmp1 = z - 1 724 ed.Sub(&tmp1, &z, decimalOne) 725 // tmp3 = 0.1 726 tmp3.SetFinite(1, -1) 727 728 usePowerSeries := false 729 730 if tmp2.Abs(&tmp1).Cmp(&tmp3) <= 0 { 731 usePowerSeries = true 732 } else { 733 // Reduce input to range [0.1, 1). 734 expDelta := int32(z.NumDigits()) + z.Exponent 735 z.Exponent -= expDelta 736 737 // We multiplied the input by 10^-expDelta, we will need to add 738 // ln(10^expDelta) = expDelta * ln(10) 739 // to the result. 740 resAdjust.setCoefficient(int64(expDelta)) 741 ed.Mul(&resAdjust, &resAdjust, decimalLn10.get(p)) 742 743 // tmp1 = z - 1 744 ed.Sub(&tmp1, &z, decimalOne) 745 746 if tmp2.Abs(&tmp1).Cmp(&tmp3) <= 0 { 747 usePowerSeries = true 748 } else { 749 // Compute an initial estimate using floats. 750 zFloat, err := z.Float64() 751 if err != nil { 752 // We know that z is in a reasonable range; no errors should happen during conversion. 753 return 0, err 754 } 755 if _, err := tmp1.SetFloat64(math.Log(zFloat)); err != nil { 756 return 0, err 757 } 758 } 759 } 760 761 if usePowerSeries { 762 // We use the power series: 763 // ln(1+x) = 2 sum [ 1 / (2n+1) * (x / (x+2))^(2n+1) ] 764 // 765 // This converges rapidly for small x. 766 // See https://en.wikipedia.org/wiki/Logarithm#Power_series 767 768 // tmp1 is already x 769 770 // tmp3 = x + 2 771 ed.Add(&tmp3, &tmp1, decimalTwo) 772 773 // tmp2 = (x / (x+2)) 774 ed.Quo(&tmp2, &tmp1, &tmp3) 775 776 // tmp1 = tmp3 = 2 * (x / (x+2)) 777 ed.Add(&tmp3, &tmp2, &tmp2) 778 tmp1.Set(&tmp3) 779 780 var eps Decimal 781 eps.Coeff.Set(bigOne) 782 eps.Exponent = -int32(p) 783 for n := 1; ; n++ { 784 785 // tmp3 *= (x / (x+2))^2 786 ed.Mul(&tmp3, &tmp3, &tmp2) 787 ed.Mul(&tmp3, &tmp3, &tmp2) 788 789 // tmp4 = 2n+1 790 tmp4.SetFinite(int64(2*n+1), 0) 791 792 ed.Quo(&tmp4, &tmp3, &tmp4) 793 794 ed.Add(&tmp1, &tmp1, &tmp4) 795 796 if tmp4.Abs(&tmp4).Cmp(&eps) <= 0 { 797 break 798 } 799 } 800 } else { 801 // Use Halley's Iteration. 802 // We use a bit more precision than the context asks for in newLoop because 803 // this is not the final result. 804 for loop := nc.newLoop("ln", x, c.Precision+1, 1); ; { 805 // tmp1 = a_n (either from initial estimate or last iteration) 806 807 // tmp2 = exp(a_n) 808 ed.Exp(&tmp2, &tmp1) 809 810 // tmp3 = exp(a_n) - z 811 ed.Sub(&tmp3, &tmp2, &z) 812 813 // tmp3 = 2 * (exp(a_n) - z) 814 ed.Add(&tmp3, &tmp3, &tmp3) 815 816 // tmp4 = exp(a_n) + z 817 ed.Add(&tmp4, &tmp2, &z) 818 819 // tmp2 = 2 * (exp(a_n) - z) / (exp(a_n) + z) 820 ed.Quo(&tmp2, &tmp3, &tmp4) 821 822 // tmp1 = a_(n+1) = a_n - 2 * (exp(a_n) - z) / (exp(a_n) + z) 823 ed.Sub(&tmp1, &tmp1, &tmp2) 824 825 if done, err := loop.done(&tmp1); err != nil { 826 return 0, err 827 } else if done { 828 break 829 } 830 if err := ed.Err(); err != nil { 831 return 0, err 832 } 833 } 834 } 835 836 // Apply the adjustment due to the initial rescaling. 837 ed.Add(&tmp1, &tmp1, &resAdjust) 838 839 if err := ed.Err(); err != nil { 840 return 0, err 841 } 842 res := c.round(d, &tmp1) 843 res |= Inexact 844 return c.goError(res) 845 } 846 847 // Log10 sets d to the base 10 log of x. 848 func (c *Context) Log10(d, x *Decimal) (Condition, error) { 849 if set, res, err := c.logSpecials(d, x); set { 850 return res, err 851 } 852 853 // TODO(mjibson): This is exact under some conditions. 854 res := Inexact 855 856 nc := BaseContext.WithPrecision(c.Precision + 2) 857 nc.Rounding = RoundHalfEven 858 var z Decimal 859 _, err := nc.Ln(&z, x) 860 if err != nil { 861 return 0, fmt.Errorf("ln: %w", err) 862 } 863 nc.Precision = c.Precision 864 865 qr, err := nc.Mul(d, &z, decimalInvLn10.get(c.Precision+2)) 866 if err != nil { 867 return 0, err 868 } 869 res |= qr 870 return c.goError(res) 871 } 872 873 // Exp sets d = e**x. 874 func (c *Context) Exp(d, x *Decimal) (Condition, error) { 875 // See: Variable Precision Exponential Function, T. E. Hull and A. Abrham, ACM 876 // Transactions on Mathematical Software, Vol 12 #2, pp79-91, ACM, June 1986. 877 878 if c.shouldSetAsNaN(x, nil) { 879 return c.setAsNaN(d, x, nil) 880 } 881 if x.Form == Infinite { 882 if x.Negative { 883 d.Set(decimalZero) 884 } else { 885 d.Set(decimalInfinity) 886 } 887 return 0, nil 888 } 889 890 if x.IsZero() { 891 d.Set(decimalOne) 892 return 0, nil 893 } 894 895 if c.Precision == 0 { 896 return 0, errors.New(errZeroPrecisionStr) 897 } 898 899 res := Inexact | Rounded 900 901 // Stage 1 902 cp := c.Precision 903 var tmp1 Decimal 904 tmp1.Abs(x) 905 if f, err := tmp1.Float64(); err == nil { 906 // This algorithm doesn't work if currentprecision*23 < |x|. Attempt to 907 // increase the working precision if needed as long as it isn't too large. If 908 // it is too large, don't bump the precision, causing an early overflow return. 909 if ncp := f / 23; ncp > float64(cp) && ncp < 1000 { 910 cp = uint32(math.Ceil(ncp)) 911 } 912 } 913 var tmp2 Decimal 914 tmp2.SetInt64(int64(cp) * 23) 915 // if abs(x) > 23*currentprecision; assert false 916 if tmp1.Cmp(&tmp2) > 0 { 917 res |= Overflow 918 if x.Sign() < 0 { 919 res = res.negateOverflowFlags() 920 res |= Clamped 921 d.SetFinite(0, c.etiny()) 922 } else { 923 d.Set(decimalInfinity) 924 } 925 return c.goError(res) 926 } 927 // if abs(x) <= setexp(.9, -currentprecision); then result 1 928 tmp2.SetFinite(9, int32(-cp)-1) 929 if tmp1.Cmp(&tmp2) <= 0 { 930 d.Set(decimalOne) 931 return c.goError(res) 932 } 933 934 // Stage 2 935 // Add x.NumDigits because the paper assumes that x.Coeff [0.1, 1). 936 t := x.Exponent + int32(x.NumDigits()) 937 if t < 0 { 938 t = 0 939 } 940 var k, r Decimal 941 k.SetFinite(1, t) 942 nc := c.WithPrecision(cp) 943 nc.Rounding = RoundHalfEven 944 if _, err := nc.Quo(&r, x, &k); err != nil { 945 return 0, fmt.Errorf("Quo: %w", err) 946 } 947 var ra Decimal 948 ra.Abs(&r) 949 p := int64(cp) + int64(t) + 2 950 951 // Stage 3 952 rf, err := ra.Float64() 953 if err != nil { 954 return 0, fmt.Errorf("r.Float64: %w", err) 955 } 956 pf := float64(p) 957 nf := math.Ceil((1.435*pf - 1.182) / math.Log10(pf/rf)) 958 if nf > 1000 || math.IsNaN(nf) { 959 return 0, errors.New("too many iterations") 960 } 961 n := int64(nf) 962 963 // Stage 4 964 nc.Precision = uint32(p) 965 ed := MakeErrDecimal(nc) 966 var sum Decimal 967 sum.SetInt64(1) 968 tmp2.Exponent = 0 969 for i := n - 1; i > 0; i-- { 970 tmp2.setCoefficient(i) 971 // tmp1 = r / i 972 ed.Quo(&tmp1, &r, &tmp2) 973 // sum = sum * r / i 974 ed.Mul(&sum, &tmp1, &sum) 975 // sum = sum + 1 976 ed.Add(&sum, &sum, decimalOne) 977 } 978 if err != ed.Err() { 979 return 0, err 980 } 981 982 // sum ** k 983 var tmpE BigInt 984 ki, err := exp10(int64(t), &tmpE) 985 if err != nil { 986 return 0, fmt.Errorf("ki: %w", err) 987 } 988 ires, err := nc.integerPower(d, &sum, ki) 989 if err != nil { 990 return 0, fmt.Errorf("integer power: %w", err) 991 } 992 res |= ires 993 nc.Precision = c.Precision 994 res |= nc.round(d, d) 995 return c.goError(res) 996 } 997 998 // integerPower sets d = x**y. d and x must not point to the same Decimal. 999 func (c *Context) integerPower(d, x *Decimal, y *BigInt) (Condition, error) { 1000 // See: https://en.wikipedia.org/wiki/Exponentiation_by_squaring. 1001 1002 var b BigInt 1003 b.Set(y) 1004 neg := b.Sign() < 0 1005 if neg { 1006 b.Abs(&b) 1007 } 1008 1009 var n Decimal 1010 n.Set(x) 1011 z := d 1012 z.Set(decimalOne) 1013 ed := MakeErrDecimal(c) 1014 for b.Sign() > 0 { 1015 if b.Bit(0) == 1 { 1016 ed.Mul(z, z, &n) 1017 } 1018 b.Rsh(&b, 1) 1019 1020 // Only compute the next n if we are going to use it. Otherwise n can overflow 1021 // on the last iteration causing this to error. 1022 if b.Sign() > 0 { 1023 ed.Mul(&n, &n, &n) 1024 } 1025 if err := ed.Err(); err != nil { 1026 // In the negative case, convert overflow to underflow. 1027 if neg { 1028 ed.Flags = ed.Flags.negateOverflowFlags() 1029 } 1030 return ed.Flags, err 1031 } 1032 } 1033 1034 if neg { 1035 ed.Quo(z, decimalOne, z) 1036 } 1037 return ed.Flags, ed.Err() 1038 } 1039 1040 // Pow sets d = x**y. 1041 func (c *Context) Pow(d, x, y *Decimal) (Condition, error) { 1042 if c.shouldSetAsNaN(x, y) { 1043 return c.setAsNaN(d, x, y) 1044 } 1045 1046 var integ, frac Decimal 1047 y.Modf(&integ, &frac) 1048 yIsInt := frac.IsZero() 1049 neg := x.Negative && y.Form == Finite && yIsInt && integ.Coeff.Bit(0) == 1 && integ.Exponent == 0 1050 1051 if x.Form == Infinite { 1052 var res Condition 1053 if y.Sign() == 0 { 1054 d.Set(decimalOne) 1055 } else if x.Negative && (y.Form == Infinite || !yIsInt) { 1056 d.Set(decimalNaN) 1057 res = InvalidOperation 1058 } else if y.Negative { 1059 d.Set(decimalZero) 1060 } else { 1061 d.Set(decimalInfinity) 1062 } 1063 d.Negative = neg 1064 return c.goError(res) 1065 } 1066 1067 // Check if y is of type int. 1068 var tmp Decimal 1069 tmp.Abs(y) 1070 1071 xs := x.Sign() 1072 ys := y.Sign() 1073 1074 if xs == 0 { 1075 var res Condition 1076 switch ys { 1077 case 0: 1078 d.Set(decimalNaN) 1079 res = InvalidOperation 1080 case 1: 1081 d.Set(decimalZero) 1082 default: // -1 1083 d.Set(decimalInfinity) 1084 } 1085 d.Negative = neg 1086 return c.goError(res) 1087 } 1088 if ys == 0 { 1089 d.Set(decimalOne) 1090 return 0, nil 1091 } 1092 1093 if xs < 0 && !yIsInt { 1094 d.Set(decimalNaN) 1095 return c.goError(InvalidOperation) 1096 } 1097 1098 // decNumber sets the precision to be max(x digits, c.Precision) + 1099 // len(exponent) + 4. 6 is used as the exponent maximum length. 1100 p := c.Precision 1101 if nd := uint32(x.NumDigits()); p < nd { 1102 p = nd 1103 } 1104 p += 4 + 6 1105 1106 nc := BaseContext.WithPrecision(p) 1107 1108 z := d 1109 if z == x { 1110 z = new(Decimal) 1111 } 1112 1113 // If integ.Exponent > 0, we need to add trailing 0s to integ.Coeff. 1114 res := c.quantize(&integ, &integ, 0) 1115 nres, err := nc.integerPower(z, x, integ.setBig(&integ.Coeff)) 1116 res |= nres 1117 if err != nil { 1118 d.Set(decimalNaN) 1119 return res, err 1120 } 1121 1122 if yIsInt { 1123 res |= c.round(d, z) 1124 return c.goError(res) 1125 } 1126 1127 ed := MakeErrDecimal(nc) 1128 1129 // Compute x**frac(y) 1130 ed.Abs(&tmp, x) 1131 ed.Ln(&tmp, &tmp) 1132 ed.Mul(&tmp, &tmp, &frac) 1133 ed.Exp(&tmp, &tmp) 1134 1135 // Join integer and frac parts back. 1136 ed.Mul(&tmp, z, &tmp) 1137 1138 if err := ed.Err(); err != nil { 1139 return ed.Flags, err 1140 } 1141 res |= c.round(d, &tmp) 1142 d.Negative = neg 1143 res |= Inexact 1144 return c.goError(res) 1145 } 1146 1147 // Quantize adjusts and rounds x as necessary so it is represented with 1148 // exponent exp and stores the result in d. 1149 func (c *Context) Quantize(d, x *Decimal, exp int32) (Condition, error) { 1150 if c.shouldSetAsNaN(x, nil) { 1151 return c.setAsNaN(d, x, nil) 1152 } 1153 if x.Form == Infinite || exp < c.etiny() { 1154 d.Set(decimalNaN) 1155 return c.goError(InvalidOperation) 1156 } 1157 res := c.quantize(d, x, exp) 1158 if nd := d.NumDigits(); nd > int64(c.Precision) || exp > c.MaxExponent { 1159 res = InvalidOperation 1160 d.Set(decimalNaN) 1161 } else { 1162 res |= c.round(d, d) 1163 if res.Overflow() || res.Underflow() { 1164 res = InvalidOperation 1165 d.Set(decimalNaN) 1166 } 1167 } 1168 return c.goError(res) 1169 } 1170 1171 func (c *Context) quantize(d, v *Decimal, exp int32) Condition { 1172 diff := exp - v.Exponent 1173 d.Set(v) 1174 var res Condition 1175 if diff < 0 { 1176 if diff < MinExponent { 1177 return SystemUnderflow | Underflow 1178 } 1179 var tmpE BigInt 1180 d.Coeff.Mul(&d.Coeff, tableExp10(-int64(diff), &tmpE)) 1181 } else if diff > 0 { 1182 p := int32(d.NumDigits()) - diff 1183 if p < 0 { 1184 if !d.IsZero() { 1185 d.Coeff.SetInt64(0) 1186 res = Inexact | Rounded 1187 } 1188 } else { 1189 nc := c.WithPrecision(uint32(p)) 1190 1191 // The idea here is that the resulting d.Exponent after rounding will be 0. We 1192 // have a number of, say, 5 digits, but p (our precision) above is set at, say, 1193 // 3. So here d.Exponent is set to `-2`. We have a number like `NNN.xx`, where 1194 // the `.xx` part will be rounded away. However during rounding of 0.9 to 1.0, 1195 // d.Exponent could be set to 1 instead of 0, so we have to reduce it and 1196 // increase the coefficient below. 1197 1198 // Another solution is to set d.Exponent = v.Exponent and adjust it to exp, 1199 // instead of setting d.Exponent = -diff and adjusting it to zero. Although 1200 // this computes the correct result, it fails the Max/MinExponent checks 1201 // during Round and raises underflow flags. Quantize (as per the spec) 1202 // is guaranteed to not raise underflow, and using 0 instead of exp as the 1203 // target eliminates this problem. 1204 1205 d.Exponent = -diff 1206 // Round even if nc.Precision == 0. 1207 res = nc.Rounding.Round(nc, d, d, false /* disableIfPrecisionZero */) 1208 // Adjust for 0.9 -> 1.0 rollover. 1209 if d.Exponent > 0 { 1210 d.Coeff.Mul(&d.Coeff, bigTen) 1211 } 1212 } 1213 } 1214 d.Exponent = exp 1215 return res 1216 } 1217 1218 func (c *Context) toIntegral(d, x *Decimal) Condition { 1219 res := c.quantize(d, x, 0) 1220 return res 1221 } 1222 1223 func (c *Context) toIntegralSpecials(d, x *Decimal) (bool, Condition, error) { 1224 if c.shouldSetAsNaN(x, nil) { 1225 res, err := c.setAsNaN(d, x, nil) 1226 return true, res, err 1227 } 1228 if x.Form != Finite { 1229 d.Set(x) 1230 return true, 0, nil 1231 } 1232 return false, 0, nil 1233 } 1234 1235 // RoundToIntegralValue sets d to integral value of x. Inexact and Rounded flags 1236 // are ignored and removed. 1237 func (c *Context) RoundToIntegralValue(d, x *Decimal) (Condition, error) { 1238 if set, res, err := c.toIntegralSpecials(d, x); set { 1239 return res, err 1240 } 1241 res := c.toIntegral(d, x) 1242 res &= ^(Inexact | Rounded) 1243 return c.goError(res) 1244 } 1245 1246 // RoundToIntegralExact sets d to integral value of x. 1247 func (c *Context) RoundToIntegralExact(d, x *Decimal) (Condition, error) { 1248 if set, res, err := c.toIntegralSpecials(d, x); set { 1249 return res, err 1250 } 1251 res := c.toIntegral(d, x) 1252 return c.goError(res) 1253 } 1254 1255 // Ceil sets d to the smallest integer >= x. 1256 func (c *Context) Ceil(d, x *Decimal) (Condition, error) { 1257 var frac Decimal 1258 x.Modf(d, &frac) 1259 if frac.Sign() > 0 { 1260 return c.Add(d, d, decimalOne) 1261 } 1262 return 0, nil 1263 } 1264 1265 // Floor sets d to the largest integer <= x. 1266 func (c *Context) Floor(d, x *Decimal) (Condition, error) { 1267 var frac Decimal 1268 x.Modf(d, &frac) 1269 if frac.Sign() < 0 { 1270 return c.Sub(d, d, decimalOne) 1271 } 1272 return 0, nil 1273 } 1274 1275 // Reduce sets d to x with all trailing zeros removed and returns the number 1276 // of zeros removed. 1277 func (c *Context) Reduce(d, x *Decimal) (int, Condition, error) { 1278 if c.shouldSetAsNaN(x, nil) { 1279 res, err := c.setAsNaN(d, x, nil) 1280 return 0, res, err 1281 } 1282 neg := x.Negative 1283 _, n := d.Reduce(x) 1284 d.Negative = neg 1285 res := c.round(d, d) 1286 res, err := c.goError(res) 1287 return n, res, err 1288 } 1289 1290 // exp10 returns x, 10^x. An error is returned if x is too large. 1291 // The returned value must not be mutated. 1292 func exp10(x int64, tmp *BigInt) (exp *BigInt, err error) { 1293 if x > MaxExponent || x < MinExponent { 1294 return nil, errors.New(errExponentOutOfRangeStr) 1295 } 1296 return tableExp10(x, tmp), nil 1297 }