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 "strconv"
21 "strings"
22 "unsafe"
23
24 "database/sql/driver"
25 )
26
27
28
29
30
31
32
33 type Decimal struct {
34 Form Form
35 Negative bool
36 Exponent int32
37 Coeff BigInt
38 }
39
40
41 type Form int8
42
43 const (
44
45
46
47
48 Finite Form = iota
49
50 Infinite
51
52
53 NaNSignaling
54
55 NaN
56 )
57
58 var (
59 decimalNaN = &Decimal{Form: NaN}
60 decimalInfinity = &Decimal{Form: Infinite}
61 )
62
63
64
65 const (
66
67
68
69
70
71
72
73 MaxExponent = 100000
74
75
76 MinExponent = -MaxExponent
77 )
78
79
80 func New(coeff int64, exponent int32) *Decimal {
81 d := new(Decimal)
82 d.SetFinite(coeff, exponent)
83 return d
84 }
85
86
87 func NewWithBigInt(coeff *BigInt, exponent int32) *Decimal {
88 d := new(Decimal)
89 d.Coeff.Set(coeff)
90 if d.Coeff.Sign() < 0 {
91 d.Negative = true
92 d.Coeff.Abs(&d.Coeff)
93 }
94 d.Exponent = exponent
95 return d
96 }
97
98 func consumePrefix(s, prefix string) (string, bool) {
99 if strings.HasPrefix(s, prefix) {
100 return s[len(prefix):], true
101 }
102 return s, false
103 }
104
105 func (d *Decimal) setString(c *Context, s string) (Condition, error) {
106 orig := s
107 s, d.Negative = consumePrefix(s, "-")
108 if !d.Negative {
109 s, _ = consumePrefix(s, "+")
110 }
111 s = strings.ToLower(s)
112 d.Exponent = 0
113 d.Coeff.SetInt64(0)
114
115 d.Form = NaN
116 if strings.HasPrefix(s, "-") || strings.HasPrefix(s, "+") {
117 return 0, fmt.Errorf("could not parse: %s", orig)
118 }
119 switch s {
120 case "infinity", "inf":
121 d.Form = Infinite
122 return 0, nil
123 }
124 isNaN := false
125 s, consumed := consumePrefix(s, "nan")
126 if consumed {
127 isNaN = true
128 }
129 s, consumed = consumePrefix(s, "snan")
130 if consumed {
131 isNaN = true
132 d.Form = NaNSignaling
133 }
134 if isNaN {
135 if s != "" {
136
137 _, err := strconv.ParseUint(s, 10, 64)
138 if err != nil {
139 return 0, fmt.Errorf("parse payload: %s: %w", s, err)
140 }
141 }
142 return 0, nil
143 }
144
145 exps := make([]int64, 0, 2)
146 if i := strings.IndexByte(s, 'e'); i >= 0 {
147 exp, err := strconv.ParseInt(s[i+1:], 10, 32)
148 if err != nil {
149 return 0, fmt.Errorf("parse exponent: %s: %w", s[i+1:], err)
150 }
151 exps = append(exps, exp)
152 s = s[:i]
153 }
154 if i := strings.IndexByte(s, '.'); i >= 0 {
155 exp := int64(len(s) - i - 1)
156 exps = append(exps, -exp)
157 s = s[:i] + s[i+1:]
158 }
159 if _, ok := d.Coeff.SetString(s, 10); !ok {
160 return 0, fmt.Errorf("parse mantissa: %s", s)
161 }
162
163 d.Form = Finite
164 return c.goError(d.setExponent(c, unknownNumDigits, 0, exps...))
165 }
166
167
168
169 func NewFromString(s string) (*Decimal, Condition, error) {
170 return BaseContext.NewFromString(s)
171 }
172
173
174
175 func (d *Decimal) SetString(s string) (*Decimal, Condition, error) {
176 return BaseContext.SetString(d, s)
177 }
178
179
180
181
182 func (c *Context) NewFromString(s string) (*Decimal, Condition, error) {
183 d := new(Decimal)
184 return c.SetString(d, s)
185 }
186
187
188
189
190 func (c *Context) SetString(d *Decimal, s string) (*Decimal, Condition, error) {
191 res, err := d.setString(c, s)
192 if err != nil {
193 return nil, 0, err
194 }
195 res |= c.round(d, d)
196 _, err = c.goError(res)
197 return d, res, err
198 }
199
200
201
202
203 func (d *Decimal) Set(x *Decimal) *Decimal {
204 if d == x {
205 return d
206 }
207 return d.setSlow(x)
208 }
209
210
211
212 func (d *Decimal) setSlow(x *Decimal) *Decimal {
213 d.Form = x.Form
214 d.Negative = x.Negative
215 d.Exponent = x.Exponent
216 d.Coeff.Set(&x.Coeff)
217 return d
218 }
219
220
221 func (d *Decimal) SetInt64(x int64) *Decimal {
222 return d.SetFinite(x, 0)
223 }
224
225
226 func (d *Decimal) SetFinite(x int64, e int32) *Decimal {
227 d.setCoefficient(x)
228 d.Exponent = e
229 return d
230 }
231
232
233
234
235 func (d *Decimal) setCoefficient(x int64) {
236 d.Negative = x < 0
237 d.Coeff.SetInt64(x)
238 d.Coeff.Abs(&d.Coeff)
239 d.Form = Finite
240 }
241
242
243
244 func (d *Decimal) SetFloat64(f float64) (*Decimal, error) {
245 var buf [32]byte
246 _, _, err := d.SetString(string(strconv.AppendFloat(buf[:0], f, 'E', -1, 64)))
247 return d, err
248 }
249
250
251
252 func (d *Decimal) Int64() (int64, error) {
253 if d.Form != Finite {
254 return 0, fmt.Errorf("%s is not finite", d.String())
255 }
256 var integ, frac Decimal
257 d.Modf(&integ, &frac)
258 if !frac.IsZero() {
259 return 0, fmt.Errorf("%s: has fractional part", d.String())
260 }
261 var ed ErrDecimal
262 if integ.Cmp(decimalMaxInt64) > 0 {
263 return 0, fmt.Errorf("%s: greater than max int64", d.String())
264 }
265 if integ.Cmp(decimalMinInt64) < 0 {
266 return 0, fmt.Errorf("%s: less than min int64", d.String())
267 }
268 if err := ed.Err(); err != nil {
269 return 0, err
270 }
271 v := integ.Coeff.Int64()
272 for i := int32(0); i < integ.Exponent; i++ {
273 v *= 10
274 }
275 if d.Negative {
276 v = -v
277 }
278 return v, nil
279 }
280
281
282
283 func (d *Decimal) Float64() (float64, error) {
284 return strconv.ParseFloat(d.String(), 64)
285 }
286
287 const (
288 errExponentOutOfRangeStr = "exponent out of range"
289
290 unknownNumDigits = int64(-1)
291 )
292
293
294
295
296
297
298
299
300 func (d *Decimal) setExponent(c *Context, nd int64, res Condition, xs ...int64) Condition {
301 var sum int64
302 for _, x := range xs {
303 if x > MaxExponent {
304 return SystemOverflow | Overflow
305 }
306 if x < MinExponent {
307 return SystemUnderflow | Underflow
308 }
309 sum += x
310 }
311 r := int32(sum)
312
313 if nd == unknownNumDigits {
314 nd = d.NumDigits()
315 }
316
317 adj := sum + nd - 1
318
319 if adj > MaxExponent {
320 return SystemOverflow | Overflow
321 }
322 if adj < MinExponent {
323 return SystemUnderflow | Underflow
324 }
325 v := int32(adj)
326
327
328 if v < c.MinExponent {
329 if !d.IsZero() {
330 res |= Subnormal
331 }
332 Etiny := c.MinExponent - (int32(c.Precision) - 1)
333
334 if r < Etiny {
335
336
337
338
339 var tmp Decimal
340 tmp.Coeff.Set(&d.Coeff)
341 tmp.Exponent = r - Etiny
342 var integ, frac Decimal
343 tmp.Modf(&integ, &frac)
344 frac.Abs(&frac)
345 if !frac.IsZero() {
346 res |= Inexact
347 if c.Rounding.ShouldAddOne(&integ.Coeff, integ.Negative, frac.Cmp(decimalHalf)) {
348 integ.Coeff.Add(&integ.Coeff, bigOne)
349 }
350 }
351 if integ.IsZero() {
352 res |= Clamped
353 }
354 r = Etiny
355 d.Coeff.Set(&integ.Coeff)
356 res |= Rounded
357 }
358 } else if v > c.MaxExponent {
359 if d.IsZero() {
360 res |= Clamped
361 r = c.MaxExponent
362 } else {
363 res |= Overflow | Inexact
364 d.Form = Infinite
365 }
366 }
367
368 if res.Inexact() && res.Subnormal() {
369 res |= Underflow
370 }
371
372 d.Exponent = r
373 return res
374 }
375
376
377
378
379
380 func upscale(a, b *Decimal, tmp *BigInt) (*BigInt, *BigInt, int32, error) {
381 if a.Exponent == b.Exponent {
382 return &a.Coeff, &b.Coeff, a.Exponent, nil
383 }
384 swapped := false
385 if a.Exponent < b.Exponent {
386 swapped = true
387 b, a = a, b
388 }
389 s := int64(a.Exponent) - int64(b.Exponent)
390
391
392 if s > MaxExponent {
393 return nil, nil, 0, errors.New(errExponentOutOfRangeStr)
394 }
395 x := tmp
396 e := tableExp10(s, x)
397 x.Mul(&a.Coeff, e)
398 y := &b.Coeff
399 if swapped {
400 x, y = y, x
401 }
402 return x, y, b.Exponent, nil
403 }
404
405
406 func (d *Decimal) setBig(b *BigInt) *BigInt {
407 b.Set(&d.Coeff)
408 if d.Negative {
409 b.Neg(b)
410 }
411 return b
412 }
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445 func (d *Decimal) CmpTotal(x *Decimal) int {
446 do := d.cmpOrder()
447 xo := x.cmpOrder()
448
449 if do < xo {
450 return -1
451 }
452 if do > xo {
453 return 1
454 }
455
456 switch d.Form {
457 case Finite:
458
459 if c := d.Cmp(x); c != 0 {
460 return c
461 }
462
463 lt := -1
464 gt := 1
465 if d.Negative {
466 lt = 1
467 gt = -1
468 }
469
470
471 if d.Exponent < x.Exponent {
472 return lt
473 }
474 if d.Exponent > x.Exponent {
475 return gt
476 }
477 return 0
478
479 case Infinite:
480 return 0
481
482 default:
483 return d.Coeff.Cmp(&x.Coeff)
484 }
485 }
486
487 func (d *Decimal) cmpOrder() int {
488 v := int(d.Form) + 1
489 if d.Negative {
490 v = -v
491 }
492 return v
493 }
494
495
496
497
498
499
500
501
502
503 func (c *Context) Cmp(d, x, y *Decimal) (Condition, error) {
504 if c.shouldSetAsNaN(x, y) {
505 return c.setAsNaN(d, x, y)
506 }
507 v := x.Cmp(y)
508 d.SetInt64(int64(v))
509 return 0, nil
510 }
511
512
513
514
515
516
517
518 func (d *Decimal) Cmp(x *Decimal) int {
519 ds := d.Sign()
520 xs := x.Sign()
521
522
523 if ds < xs {
524 return -1
525 } else if ds > xs {
526 return 1
527 } else if ds == 0 && xs == 0 {
528 return 0
529 }
530
531
532
533
534 gt := 1
535 lt := -1
536 if ds == -1 {
537 gt = -1
538 lt = 1
539 }
540
541 if d.Form == Infinite {
542 if x.Form == Infinite {
543 return 0
544 }
545 return gt
546 } else if x.Form == Infinite {
547 return lt
548 }
549
550 if d.Exponent == x.Exponent {
551 cmp := d.Coeff.Cmp(&x.Coeff)
552 if ds < 0 {
553 cmp = -cmp
554 }
555 return cmp
556 }
557
558
559 dn := d.NumDigits() + int64(d.Exponent)
560 xn := x.NumDigits() + int64(x.Exponent)
561 if dn < xn {
562 return lt
563 } else if dn > xn {
564 return gt
565 }
566
567
568
569
570
571
572
573
574
575 var cmp int
576 if d.Exponent < x.Exponent {
577 var xScaled, tmpE BigInt
578 xScaled.Set(&x.Coeff)
579 xScaled.Mul(&xScaled, tableExp10(int64(x.Exponent)-int64(d.Exponent), &tmpE))
580 cmp = d.Coeff.Cmp(&xScaled)
581 } else {
582 var dScaled, tmpE BigInt
583 dScaled.Set(&d.Coeff)
584 dScaled.Mul(&dScaled, tableExp10(int64(d.Exponent)-int64(x.Exponent), &tmpE))
585 cmp = dScaled.Cmp(&x.Coeff)
586 }
587 if ds < 0 {
588 cmp = -cmp
589 }
590 return cmp
591 }
592
593
594
595
596
597
598
599
600
601
602
603 func (d *Decimal) Sign() int {
604 if d.Form == Finite && d.Coeff.Sign() == 0 {
605 return 0
606 }
607 if d.Negative {
608 return -1
609 }
610 return 1
611 }
612
613
614 func (d *Decimal) IsZero() bool {
615 return d.Sign() == 0
616 }
617
618
619
620
621
622 func (d *Decimal) Modf(integ, frac *Decimal) {
623 if integ == nil && frac == nil {
624 return
625 }
626
627 neg := d.Negative
628
629
630 if d.Exponent > 0 {
631 if frac != nil {
632 frac.Negative = neg
633 frac.Exponent = 0
634 frac.Coeff.SetInt64(0)
635 }
636 if integ != nil {
637 integ.Set(d)
638 }
639 return
640 }
641 nd := d.NumDigits()
642 exp := -int64(d.Exponent)
643
644 if exp > nd {
645 if integ != nil {
646 integ.Negative = neg
647 integ.Exponent = 0
648 integ.Coeff.SetInt64(0)
649 }
650 if frac != nil {
651 frac.Set(d)
652 }
653 return
654 }
655
656 var tmpE BigInt
657 e := tableExp10(exp, &tmpE)
658
659 var icoeff *BigInt
660 if integ != nil {
661 icoeff = &integ.Coeff
662 integ.Exponent = 0
663 integ.Negative = neg
664 } else {
665
666
667 icoeff = new(BigInt)
668 }
669
670 if frac != nil {
671 icoeff.QuoRem(&d.Coeff, e, &frac.Coeff)
672 frac.Exponent = d.Exponent
673 frac.Negative = neg
674 } else {
675
676
677 icoeff.Quo(&d.Coeff, e)
678 }
679 }
680
681
682 func (d *Decimal) Neg(x *Decimal) *Decimal {
683 d.Set(x)
684 if d.IsZero() {
685 d.Negative = false
686 } else {
687 d.Negative = !d.Negative
688 }
689 return d
690 }
691
692
693 func (d *Decimal) Abs(x *Decimal) *Decimal {
694 d.Set(x)
695 d.Negative = false
696 return d
697 }
698
699
700
701 func (d *Decimal) Reduce(x *Decimal) (*Decimal, int) {
702 if x.Form != Finite {
703 d.Set(x)
704 return d, 0
705 }
706 var nd int
707 neg := false
708 switch x.Sign() {
709 case 0:
710 nd = int(d.NumDigits())
711 d.SetInt64(0)
712 return d, nd - 1
713 case -1:
714 neg = true
715 }
716 d.Set(x)
717
718
719 if d.Coeff.IsUint64() {
720 i := d.Coeff.Uint64()
721 for i >= 10000 && i%10000 == 0 {
722 i /= 10000
723 nd += 4
724 }
725 for i%10 == 0 {
726 i /= 10
727 nd++
728 }
729 if nd != 0 {
730 d.Exponent += int32(nd)
731 d.Coeff.SetUint64(i)
732 d.Negative = neg
733 }
734 return d, nd
735 }
736
737
738
739 var z, r BigInt
740 d.setBig(&z)
741 for {
742 z.QuoRem(&d.Coeff, bigTen, &r)
743 if r.Sign() == 0 {
744 d.Coeff.Set(&z)
745 nd++
746 } else {
747 break
748 }
749 }
750 d.Exponent += int32(nd)
751 return d, nd
752 }
753
754 const decimalSize = unsafe.Sizeof(Decimal{})
755
756
757 func (d *Decimal) Size() uintptr {
758 return decimalSize - bigIntSize + d.Coeff.Size()
759 }
760
761
762
763 func (d Decimal) Value() (driver.Value, error) {
764 return d.String(), nil
765 }
766
767
768
769 func (d *Decimal) Scan(src interface{}) error {
770 switch src := src.(type) {
771 case []byte:
772 _, _, err := d.SetString(string(src))
773 return err
774 case string:
775 _, _, err := d.SetString(src)
776 return err
777 case int64:
778 d.SetInt64(src)
779 return nil
780 case float64:
781 _, err := d.SetFloat64(src)
782 return err
783 default:
784 return fmt.Errorf("could not convert %T to Decimal", src)
785 }
786 }
787
788
789 func (d *Decimal) UnmarshalText(b []byte) error {
790 _, _, err := d.SetString(string(b))
791 return err
792 }
793
794
795 func (d *Decimal) MarshalText() ([]byte, error) {
796 if d == nil {
797 return []byte("<nil>"), nil
798 }
799 return []byte(d.String()), nil
800 }
801
802
803
804
805
806
807
808
809
810
811
812
813 type NullDecimal struct {
814 Decimal Decimal
815 Valid bool
816 }
817
818
819 func (nd *NullDecimal) Scan(value interface{}) error {
820 if value == nil {
821 nd.Valid = false
822 return nil
823 }
824 nd.Valid = true
825 return nd.Decimal.Scan(value)
826 }
827
828
829 func (nd NullDecimal) Value() (driver.Value, error) {
830 if !nd.Valid {
831 return nil, nil
832 }
833 return nd.Decimal.Value()
834 }
835
View as plain text