...

Source file src/github.com/cockroachdb/apd/v3/decimal.go

Documentation: github.com/cockroachdb/apd/v3

     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  	"strconv"
    21  	"strings"
    22  	"unsafe"
    23  
    24  	"database/sql/driver"
    25  )
    26  
    27  // Decimal is an arbitrary-precision decimal. Its value is:
    28  //
    29  //	Negative × Coeff × 10**Exponent
    30  //
    31  // Coeff must be positive. If it is negative results may be incorrect and
    32  // apd may panic.
    33  type Decimal struct {
    34  	Form     Form
    35  	Negative bool
    36  	Exponent int32
    37  	Coeff    BigInt
    38  }
    39  
    40  // Form specifies the form of a Decimal.
    41  type Form int8
    42  
    43  const (
    44  	// These constants must be in the following order. CmpTotal assumes that
    45  	// the order of these constants reflects the total order on decimals.
    46  
    47  	// Finite is the finite form.
    48  	Finite Form = iota
    49  	// Infinite is the infinite form.
    50  	Infinite
    51  	// NaNSignaling is the signaling NaN form. It will always raise the
    52  	// InvalidOperation condition during an operation.
    53  	NaNSignaling
    54  	// NaN is the NaN form.
    55  	NaN
    56  )
    57  
    58  var (
    59  	decimalNaN      = &Decimal{Form: NaN}
    60  	decimalInfinity = &Decimal{Form: Infinite}
    61  )
    62  
    63  //go:generate stringer -type=Form
    64  
    65  const (
    66  	// TODO(mjibson): MaxExponent is set because both upscale and Round
    67  	// perform a calculation of 10^x, where x is an exponent. This is done by
    68  	// big.Int.Exp. This restriction could be lifted if better algorithms were
    69  	// determined during upscale and Round that don't need to perform Exp.
    70  
    71  	// MaxExponent is the highest exponent supported. Exponents near this range will
    72  	// perform very slowly (many seconds per operation).
    73  	MaxExponent = 100000
    74  	// MinExponent is the lowest exponent supported with the same limitations as
    75  	// MaxExponent.
    76  	MinExponent = -MaxExponent
    77  )
    78  
    79  // New creates a new decimal with the given coefficient and exponent.
    80  func New(coeff int64, exponent int32) *Decimal {
    81  	d := new(Decimal)
    82  	d.SetFinite(coeff, exponent)
    83  	return d
    84  }
    85  
    86  // NewWithBigInt creates a new decimal with the given coefficient and exponent.
    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  	// Until there are no parse errors, leave as NaN.
   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  			// We ignore these digits, but must verify them.
   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  	// No parse errors, can now flag as finite.
   163  	d.Form = Finite
   164  	return c.goError(d.setExponent(c, unknownNumDigits, 0, exps...))
   165  }
   166  
   167  // NewFromString creates a new decimal from s. It has no restrictions on
   168  // exponents or precision.
   169  func NewFromString(s string) (*Decimal, Condition, error) {
   170  	return BaseContext.NewFromString(s)
   171  }
   172  
   173  // SetString sets d to s and returns d. It has no restrictions on exponents
   174  // or precision.
   175  func (d *Decimal) SetString(s string) (*Decimal, Condition, error) {
   176  	return BaseContext.SetString(d, s)
   177  }
   178  
   179  // NewFromString creates a new decimal from s. The returned Decimal has its
   180  // exponents restricted by the context and its value rounded if it contains more
   181  // digits than the context's precision.
   182  func (c *Context) NewFromString(s string) (*Decimal, Condition, error) {
   183  	d := new(Decimal)
   184  	return c.SetString(d, s)
   185  }
   186  
   187  // SetString sets d to s and returns d. The returned Decimal has its exponents
   188  // restricted by the context and its value rounded if it contains more digits
   189  // than the context's precision.
   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  // Set sets d's fields to the values of x and returns d.
   201  //
   202  //gcassert:inline
   203  func (d *Decimal) Set(x *Decimal) *Decimal {
   204  	if d == x {
   205  		return d
   206  	}
   207  	return d.setSlow(x)
   208  }
   209  
   210  // setSlow is split from Set to allow the aliasing fast-path to be
   211  // inlined in callers.
   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  // SetInt64 sets d to x and returns d.
   221  func (d *Decimal) SetInt64(x int64) *Decimal {
   222  	return d.SetFinite(x, 0)
   223  }
   224  
   225  // SetFinite sets d to x with exponent e and returns d.
   226  func (d *Decimal) SetFinite(x int64, e int32) *Decimal {
   227  	d.setCoefficient(x)
   228  	d.Exponent = e
   229  	return d
   230  }
   231  
   232  // setCoefficient sets d's coefficient and negative value to x and its Form
   233  // to Finite The exponent is not changed. Since the exponent is not changed
   234  // (and this is thus easy to misuse), this is unexported for internal use only.
   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  // SetFloat64 sets d's Coefficient and Exponent to x and returns d. d will
   243  // hold the exact value of f.
   244  func (d *Decimal) SetFloat64(f float64) (*Decimal, error) {
   245  	var buf [32]byte // Avoid most of the allocations in strconv.
   246  	_, _, err := d.SetString(string(strconv.AppendFloat(buf[:0], f, 'E', -1, 64)))
   247  	return d, err
   248  }
   249  
   250  // Int64 returns the int64 representation of x. If x cannot be represented in an
   251  // int64, an error is returned.
   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  // Float64 returns the float64 representation of x. This conversion may lose
   282  // data (see strconv.ParseFloat for caveats).
   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  // setExponent sets d's Exponent to the sum of xs. Each value and the sum
   294  // of xs must fit within an int32. An error occurs if the sum is outside of
   295  // the MaxExponent or MinExponent range. nd is the number of digits in d, as
   296  // computed by NumDigits. Callers can pass unknownNumDigits to indicate that
   297  // they have not yet computed this digit count, in which case setExponent will
   298  // do so. res is any Condition previously set for this operation, which can
   299  // cause Underflow to be set if, for example, Inexact is already set.
   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  	// adj is the adjusted exponent: exponent + clength - 1
   317  	adj := sum + nd - 1
   318  	// Make sure it is less than the system limits.
   319  	if adj > MaxExponent {
   320  		return SystemOverflow | Overflow
   321  	}
   322  	if adj < MinExponent {
   323  		return SystemUnderflow | Underflow
   324  	}
   325  	v := int32(adj)
   326  
   327  	// d is subnormal.
   328  	if v < c.MinExponent {
   329  		if !d.IsZero() {
   330  			res |= Subnormal
   331  		}
   332  		Etiny := c.MinExponent - (int32(c.Precision) - 1)
   333  		// Only need to round if exponent < Etiny.
   334  		if r < Etiny {
   335  			// We need to take off (r - Etiny) digits. Split up d.Coeff into integer and
   336  			// fractional parts and do operations similar Round. We avoid calling Round
   337  			// directly because it calls setExponent and modifies the result's exponent
   338  			// and coeff in ways that would be wrong here.
   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  // upscale converts a and b to BigInts with the same scaling. It returns
   377  // them with this scaling, along with the scaling. An error can be produced
   378  // if the resulting scale factor is out of range. The tmp argument must be
   379  // provided and can be (but won't always be) one of the return values.
   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  	// TODO(mjibson): figure out a better way to upscale numbers with highly
   391  	// differing exponents.
   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  // setBig sets b to d's coefficient with negative.
   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  // CmpTotal compares d and x using their abstract representation rather
   415  // than their numerical value. A total ordering is defined for all possible
   416  // abstract representations, as described below. If the first operand is
   417  // lower in the total order than the second operand then the result is -1,
   418  // if the operands have the same abstract representation then the result is
   419  // 0, and if the first operand is higher in the total order than the second
   420  // operand then the result is 1.
   421  //
   422  // Numbers (representations which are not NaNs) are ordered such that a
   423  // larger numerical value is higher in the ordering. If two representations
   424  // have the same numerical value then the exponent is taken into account;
   425  // larger (more positive) exponents are higher in the ordering.
   426  //
   427  // For example, the following values are ordered from lowest to highest. Note
   428  // the difference in ordering between 1.2300 and 1.23.
   429  //
   430  //	-NaN
   431  //	-NaNSignaling
   432  //	-Infinity
   433  //	-127
   434  //	-1.00
   435  //	-1
   436  //	-0.000
   437  //	-0
   438  //	0
   439  //	1.2300
   440  //	1.23
   441  //	1E+9
   442  //	Infinity
   443  //	NaNSignaling
   444  //	NaN
   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  		// d and x have the same sign and form, compare their value.
   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  		// Values are equal, compare exponents.
   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  // Cmp compares x and y and sets d to:
   496  //
   497  //	-1 if x <  y
   498  //	 0 if x == y
   499  //	+1 if x >  y
   500  //
   501  // This comparison respects the normal rules of special values (like NaN),
   502  // and does not compare them.
   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  // Cmp compares d and x and returns:
   513  //
   514  //	-1 if d <  x
   515  //	 0 if d == x
   516  //	+1 if d >  x
   517  //	undefined if d or x are NaN
   518  func (d *Decimal) Cmp(x *Decimal) int {
   519  	ds := d.Sign()
   520  	xs := x.Sign()
   521  
   522  	// First compare signs.
   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  	// Use gt and lt here with flipped signs if d is negative. gt and lt then
   532  	// allow for simpler comparisons since we can ignore the sign of the decimals
   533  	// and only worry about the form and value.
   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  	// Next compare adjusted exponents.
   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  	// Now have to use aligned BigInts. This function previously used upscale to
   568  	// align in all cases, but that requires an error in the return value. upscale
   569  	// does that so that it can fail if it needs to take the Exp of too-large a
   570  	// number, which is very slow. The only way for that to happen here is for d
   571  	// and x's coefficients to be of hugely differing values. That is practically
   572  	// more difficult, so we are assuming the user is already comfortable with
   573  	// slowness in those operations.
   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  // Sign returns, if d is Finite:
   594  //
   595  //	-1 if d <  0
   596  //	 0 if d == 0 or -0
   597  //	+1 if d >  0
   598  //
   599  // Otherwise (if d is Infinite or NaN):
   600  //
   601  //	-1 if d.Negative == true
   602  //	+1 if d.Negative == false
   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  // IsZero returns true if d == 0 or -0.
   614  func (d *Decimal) IsZero() bool {
   615  	return d.Sign() == 0
   616  }
   617  
   618  // Modf sets integ to the integral part of d and frac to the fractional part
   619  // such that d = integ+frac. If d is negative, both integ or frac will be either
   620  // 0 or negative. integ.Exponent will be >= 0; frac.Exponent will be <= 0.
   621  // Either argument can be nil, preventing it from being set.
   622  func (d *Decimal) Modf(integ, frac *Decimal) {
   623  	if integ == nil && frac == nil {
   624  		return
   625  	}
   626  
   627  	neg := d.Negative
   628  
   629  	// No fractional part.
   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  	// d < 0 because exponent is larger than number of digits.
   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  		// This is the integ == nil branch, and we already checked if both integ and
   666  		// frac were nil above, so frac can never be nil in this branch.
   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  		// This is the frac == nil, which means integ must not be nil since they both
   676  		// can't be due to the check above.
   677  		icoeff.Quo(&d.Coeff, e)
   678  	}
   679  }
   680  
   681  // Neg sets d to -x and returns d.
   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  // Abs sets d to |x| and returns d.
   693  func (d *Decimal) Abs(x *Decimal) *Decimal {
   694  	d.Set(x)
   695  	d.Negative = false
   696  	return d
   697  }
   698  
   699  // Reduce sets d to x with all trailing zeros removed and returns d and the
   700  // number of zeros removed.
   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  	// Use a uint64 for the division if possible.
   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  	// Divide by 10 in a loop. In benchmarks of reduce0.decTest, this is 20%
   738  	// faster than converting to a string and trimming the 0s from the end.
   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  // Size returns the total memory footprint of d in bytes.
   757  func (d *Decimal) Size() uintptr {
   758  	return decimalSize - bigIntSize + d.Coeff.Size()
   759  }
   760  
   761  // Value implements the database/sql/driver.Valuer interface. It converts d to a
   762  // string.
   763  func (d Decimal) Value() (driver.Value, error) {
   764  	return d.String(), nil
   765  }
   766  
   767  // Scan implements the database/sql.Scanner interface. It supports string,
   768  // []byte, int64, float64.
   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  // UnmarshalText implements the encoding.TextUnmarshaler interface.
   789  func (d *Decimal) UnmarshalText(b []byte) error {
   790  	_, _, err := d.SetString(string(b))
   791  	return err
   792  }
   793  
   794  // MarshalText implements the encoding.TextMarshaler interface.
   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  // NullDecimal represents a string that may be null. NullDecimal implements
   803  // the database/sql.Scanner interface so it can be used as a scan destination:
   804  //
   805  //	var d NullDecimal
   806  //	err := db.QueryRow("SELECT num FROM foo WHERE id=?", id).Scan(&d)
   807  //	...
   808  //	if d.Valid {
   809  //	   // use d.Decimal
   810  //	} else {
   811  //	   // NULL value
   812  //	}
   813  type NullDecimal struct {
   814  	Decimal Decimal
   815  	Valid   bool // Valid is true if Decimal is not NULL
   816  }
   817  
   818  // Scan implements the database/sql.Scanner interface.
   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  // Value implements the database/sql/driver.Valuer interface.
   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