// Round rounds z down to n digits of precision and returns z. The result is // undefined if n is less than zero. No rounding will occur if n is zero. // The result of Round will always be within the interval [āzā, z]. func (z *Big) Round(n int32) *Big { zp := z.Prec() if n <= 0 || int(n) < zp-int(z.scale) || z.form != finite { return z } shift, ok := checked.Sub(int64(zp), int64(n)) if !ok { z.form = inf return z } if shift <= 0 { return z } z.scale -= int32(shift) if z.isCompact() { val, ok := pow.Ten64(shift) if ok { return z.quoAndRound(z.compact, val) } z.mantissa.SetInt64(z.compact) } val := pow.BigTen(shift) return z.quoBigAndRound(&z.mantissa, &val) }
// Int64 returns x as an int64, truncating the fractional portion, if any. func (x *Big) Int64() int64 { var b int64 if x.isCompact() { b = x.compact } else { b = x.mantissa.Int64() } if x.scale == 0 { return b } if x.scale < 0 { // Undefined. checked.MulPow10 returns 0 when ok is false. // IMO, 0 is a better choice than 1 << 64 - 1 because it could cause a // division by zero panic which would be a clear indication something is // incorrect. b, _ = checked.MulPow10(b, -x.scale) return b } p, ok := pow.Ten64(int64(x.scale)) // See above comment. if !ok { return 0 } return b / p }
// MulPow10 computes 10 * x ** n and a bool indicating whether // the multiplcation was successful. func MulPow10(x int64, n int32) (p int64, ok bool) { if x == 0 || n <= 0 || x == c.Inflated { return x, true } if n < pow.Tab64Len && n < pow.ThreshLen { if x == 1 { return pow.Ten64(int64(n)) } if arith.Abs(int64(n)) < pow.Thresh(n) { p, ok := pow.Ten64(int64(n)) if !ok { return 0, false } return Mul(x, p) } } return 0, false }
func ilog10(x int64) int { // From https://graphics.stanford.edu/~seander/bithacks.html t := ((64 - CLZ(x) + 1) * 1233) >> 12 v, ok := pow.Ten64(int64(t)) if !ok { return bigIlog10(big.NewInt(x)) } if x < v { return t } return t + 1 }
// mod splits fr, a scaled decimal, into its integeral and fractional parts. func mod(fr int64, scale int32) (dec int64, frac int64, ok bool) { if fr < 0 { dec, frac, ok = mod(-fr, scale) return -dec, -frac, ok } exp, ok := pow.Ten64(int64(scale)) if !ok { return 0, 0, false } if exp == 0 { return fr, 0, true } dec = fr / exp frac = fr - (dec * exp) return dec, frac, true }