1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package apd
16
17 import (
18 "errors"
19 "fmt"
20 "math"
21 )
22
23
24
25
26 type Context struct {
27
28
29
30 Precision uint32
31
32
33
34
35 MaxExponent int32
36
37
38 MinExponent int32
39
40
41 Traps Condition
42
43
44 Rounding Rounder
45 }
46
47 const (
48
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
63 var BaseContext = Context{
64
65 Precision: 0,
66
67 MaxExponent: MaxExponent,
68 MinExponent: MinExponent,
69
70 Traps: DefaultTraps,
71 }
72
73
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
82
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
91 func (c *Context) etiny() int32 {
92 return c.MinExponent - int32(c.Precision) + 1
93 }
94
95
96
97
98
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
105
106
107 func (c *Context) setAsNaN(d *Decimal, x, y *Decimal) (Condition, error) {
108 var nan *Decimal
109
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
174 func (c *Context) Add(d, x, y *Decimal) (Condition, error) {
175 return c.add(d, x, y, false)
176 }
177
178
179 func (c *Context) Sub(d, x, y *Decimal) (Condition, error) {
180 return c.add(d, x, y, true)
181 }
182
183
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
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
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
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
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
272
273 return true, 0, errors.New(errZeroPrecisionStr)
274 }
275
276 return false, 0, nil
277 }
278
279
280
281
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
288 neg := x.Negative != y.Negative
289
290
291
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
307
308
309
310 ndDividend := NumDigits(÷nd)
311 ndDivisor := NumDigits(&divisor)
312 ndDiff := ndDividend - ndDivisor
313 var tmpE BigInt
314 if ndDiff < 0 {
315
316 dividend.Mul(÷nd, tableExp10(-ndDiff, &tmpE))
317 } else if ndDiff > 0 {
318
319 divisor.Mul(&divisor, tableExp10(ndDiff, &tmpE))
320 }
321 adjCoeffs := -ndDiff
322 if dividend.Cmp(&divisor) < 0 {
323
324 dividend.Mul(÷nd, bigTen)
325 adjCoeffs++
326 }
327
328
329
330
331
332
333 adjExp10 := int64(c.Precision - 1)
334 dividend.Mul(÷nd, tableExp10(adjExp10, &tmpE))
335
336
337 var rem BigInt
338 d.Coeff.QuoRem(÷nd, &divisor, &rem)
339 d.Form = Finite
340 d.Negative = neg
341
342
343
344
345 nd := NumDigits(&d.Coeff)
346 if rem.Sign() != 0 {
347
348
349
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
358
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
369
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
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
396
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
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
471
472
473 func (c *Context) Sqrt(d, x *Decimal) (Condition, error) {
474
475
476
477
478 if set, res, err := c.rootSpecials(d, x, 2); set {
479 return res, err
480 }
481
482
483
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
501
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
516
517 p := uint32(3)
518 var tmp Decimal
519
520
521
522
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
530 ed.Quo(&tmp, &f, &approx)
531
532 ed.Add(&tmp, &tmp, &approx)
533
534 ed.Mul(&approx, &tmp, decimalHalf)
535 }
536
537
538
539
540
541
542
543
544
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
559 func (c *Context) Cbrt(d, x *Decimal) (Condition, error) {
560
561
562
563
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
578
579
580
581
582
583
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
595
596
597
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
614 for loop := nc.newLoop("cbrt", &z, c.Precision+1, 1); ; {
615
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
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
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
681 func (c *Context) Ln(d, x *Decimal) (Condition, error) {
682
683
684
685
686 if set, res, err := c.logSpecials(d, x); set {
687 return res, err
688 }
689
690
691
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
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724 ed.Sub(&tmp1, &z, decimalOne)
725
726 tmp3.SetFinite(1, -1)
727
728 usePowerSeries := false
729
730 if tmp2.Abs(&tmp1).Cmp(&tmp3) <= 0 {
731 usePowerSeries = true
732 } else {
733
734 expDelta := int32(z.NumDigits()) + z.Exponent
735 z.Exponent -= expDelta
736
737
738
739
740 resAdjust.setCoefficient(int64(expDelta))
741 ed.Mul(&resAdjust, &resAdjust, decimalLn10.get(p))
742
743
744 ed.Sub(&tmp1, &z, decimalOne)
745
746 if tmp2.Abs(&tmp1).Cmp(&tmp3) <= 0 {
747 usePowerSeries = true
748 } else {
749
750 zFloat, err := z.Float64()
751 if err != nil {
752
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
763
764
765
766
767
768
769
770
771 ed.Add(&tmp3, &tmp1, decimalTwo)
772
773
774 ed.Quo(&tmp2, &tmp1, &tmp3)
775
776
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
786 ed.Mul(&tmp3, &tmp3, &tmp2)
787 ed.Mul(&tmp3, &tmp3, &tmp2)
788
789
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
802
803
804 for loop := nc.newLoop("ln", x, c.Precision+1, 1); ; {
805
806
807
808 ed.Exp(&tmp2, &tmp1)
809
810
811 ed.Sub(&tmp3, &tmp2, &z)
812
813
814 ed.Add(&tmp3, &tmp3, &tmp3)
815
816
817 ed.Add(&tmp4, &tmp2, &z)
818
819
820 ed.Quo(&tmp2, &tmp3, &tmp4)
821
822
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
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
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
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
874 func (c *Context) Exp(d, x *Decimal) (Condition, error) {
875
876
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
902 cp := c.Precision
903 var tmp1 Decimal
904 tmp1.Abs(x)
905 if f, err := tmp1.Float64(); err == nil {
906
907
908
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
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
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
935
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
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
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
972 ed.Quo(&tmp1, &r, &tmp2)
973
974 ed.Mul(&sum, &tmp1, &sum)
975
976 ed.Add(&sum, &sum, decimalOne)
977 }
978 if err != ed.Err() {
979 return 0, err
980 }
981
982
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
999 func (c *Context) integerPower(d, x *Decimal, y *BigInt) (Condition, error) {
1000
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
1021
1022 if b.Sign() > 0 {
1023 ed.Mul(&n, &n, &n)
1024 }
1025 if err := ed.Err(); err != nil {
1026
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
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
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:
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
1099
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
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
1130 ed.Abs(&tmp, x)
1131 ed.Ln(&tmp, &tmp)
1132 ed.Mul(&tmp, &tmp, &frac)
1133 ed.Exp(&tmp, &tmp)
1134
1135
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
1148
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
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205 d.Exponent = -diff
1206
1207 res = nc.Rounding.Round(nc, d, d, false )
1208
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
1236
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
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
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
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
1276
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
1291
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 }
1298
View as plain text