func (d Decimal64) IsSubnormal() bool {
	flav, _, _, significand := d.parts()
	return significand != 0 && significand < decimal64Base && flav == flNormal
}
IsSubnormal returns true iff d is a subnormal.
package decimal
import (
	"math"
	"math/bits"
)
type flavor int
type roundingMode int
type discardedDigit int
const (
	eq0 discardedDigit = 1 << iota
	lt5
	eq5
	gt5
)
const (
	flNormal flavor = iota
	flInf
	flQNaN
	flSNaN
)
const (
	roundHalfUp roundingMode = iota
	roundHalfEven
	roundDown
)
type Decimal64 struct {
	bits uint64
}
type decParts struct {
	fl          flavor
	sign        int
	exp         int
	significand uint128T
	original    Decimal64
}
type Context64 struct {
	roundingMode roundingMode
}
var powersOf10 = []uint64{
	1,
	10,
	100,
	1000,
	10000,
	100000,
	1000000,
	10000000,
	100000000,
	1000000000,
	10000000000,
	100000000000,
	1000000000000,
	10000000000000,
	100000000000000,
	1000000000000000,
	10000000000000000,
	100000000000000000,
	1000000000000000000,
	10000000000000000000,
}
func (context roundingMode) round(significand uint64, rndStatus discardedDigit) uint64 {
	switch context {
	case roundHalfUp:
		if rndStatus&(gt5|eq5) != 0 {
			return significand + 1
		}
	case roundHalfEven:
		if (rndStatus == eq5 && significand%2 == 1) || rndStatus == gt5 {
			return significand + 1
		}
	case roundDown:  
		return significand
	}
	return significand
}
func signalNaN64() {
	panic("sNaN64")
}
func checkSignificandIsNormal(significand uint64) {
	logicCheck(decimal64Base <= significand, "%d <= %d", decimal64Base, significand)
	logicCheck(significand < 10*decimal64Base, "%d < %d", significand, 10*decimal64Base)
}
func New64FromInt64(value int64) Decimal64 {
	if value == 0 {
		return Zero64
	}
	sign := 0
	if value < 0 {
		sign = 1
		value = -value
	}
	exp, significand := renormalize(0, uint64(value))
	checkSignificandIsNormal(significand)
	return newFromParts(sign, exp, significand)
}
func renormalize(exp int, significand uint64) (int, uint64) {
	numBits := 64 - bits.LeadingZeros64(significand)
	numDigits := numBits * 3 / 10
	normExp := 15 - numDigits
	if normExp > 0 {
		if exp-normExp < -expOffset {
			normExp = exp + expOffset
		}
		exp -= normExp
		significand *= powersOf10[normExp]
	} else if normExp < -1 {
		normExp++
		if exp-normExp > expMax {
			normExp = exp - expMax
		}
		exp -= normExp
		significand /= powersOf10[-normExp]
	}
	for significand < decimal64Base && exp > -expOffset {
		exp--
		significand *= 10
	}
	for significand >= 10*decimal64Base && exp < expMax {
		exp++
		significand /= 10
	}
	return exp, significand
}
func roundStatus(significand uint64, exp int, targetExp int) discardedDigit {
	expDiff := targetExp - exp
	if expDiff > 19 && significand != 0 {
		return lt5
	}
	remainder := significand % powersOf10[expDiff]
	midpoint := 5 * powersOf10[expDiff-1]
	if remainder == 0 {
		return eq0
	} else if remainder < midpoint {
		return lt5
	} else if remainder == midpoint {
		return eq5
	}
	return gt5
}
func countTrailingZeros(n uint64) int {
	zeros := 0
	if n%10000000000000000 == 0 {
		zeros += 16
		n /= 10000000000000000
	}
	if n%100000000 == 0 {
		zeros += 8
		n /= 100000000
	}
	if n%10000 == 0 {
		zeros += 4
		n /= 10000
	}
	if n%100 == 0 {
		zeros += 2
		n /= 100
	}
	if n%10 == 0 {
		zeros++
	}
	return zeros
}
func newFromParts(sign int, exp int, significand uint64) Decimal64 {
	s := uint64(sign) << 63
	if significand < 0x8<<50 {
		return Decimal64{s | uint64(exp+expOffset)<<(63-10) | significand}
	}
	significand &= 0x8<<50 - 1
	return Decimal64{s | uint64(0xc00|(exp+expOffset))<<(63-12) | significand}
}
func (d Decimal64) parts() (fl flavor, sign int, exp int, significand uint64) {
	sign = int(d.bits >> 63)
	switch (d.bits >> (63 - 4)) & 0xf {
	case 15:
		switch (d.bits >> (63 - 6)) & 3 {
		case 0, 1:
			fl = flInf
		case 2:
			fl = flQNaN
			significand = d.bits & (1<<53 - 1)
		case 3:
			fl = flSNaN
			significand = d.bits & (1<<53 - 1)
		}
	case 12, 13, 14:
		fl = flNormal
		exp = int((d.bits>>(63-12))&(1<<10-1)) - expOffset
		significand = d.bits&(1<<51-1) | (1 << 53)
	default:
		fl = flNormal
		exp = int((d.bits>>(63-10))&(1<<10-1)) - expOffset
		significand = d.bits & (1<<53 - 1)
		if significand == 0 {
			exp = 0
		}
	}
	return
}
func expWholeFrac(exp int, significand uint64) (exp2 int, whole uint64, frac uint64) {
	if significand == 0 {
		return 0, 0, 0
	}
	if exp >= 0 {
		return exp, significand, 0
	}
	n := uint128T{significand, 0}
	exp += 16
	if exp > 0 {
		n = n.mul64(powersOf10[exp])
		exp = 0
	} else {
		for step := 3; step >= 0; step-- {
			expStep := 1 << uint(step)
			powerOf10 := powersOf10[expStep]
			for ; n.lo >= powerOf10 && exp <= -expStep; exp += expStep {
				quo := n.lo / powerOf10
				rem := n.lo - quo*powerOf10
				if rem > 0 {
					break
				}
				n.lo = quo
			}
		}
	}
	whole128 := n.div64(10 * decimal64Base)
	frac128 := n.sub(whole128.mul64(10 * decimal64Base))
	return exp, whole128.lo, frac128.lo
}
func (d Decimal64) Float64() float64 {
	flav, sign, exp, significand := d.parts()
	switch flav {
	case flNormal:
		if significand == 0 {
			return 0.0 * float64(1-2*sign)
		}
		if exp&1 == 1 {
			exp--
			significand *= 10
		}
		return float64(1-2*sign) * float64(significand) * math.Pow10(exp)
	case flInf:
		return math.Inf(1 - 2*sign)
	case flQNaN:
		return math.NaN()
	}
	signalNaN64()
	return 0
}
func (d Decimal64) Int64() int64 {
	flav, sign, exp, significand := d.parts()
	switch flav {
	case flInf:
		if sign == 0 {
			return math.MaxInt64
		}
		return math.MinInt64
	case flQNaN:
		return 0
	case flSNaN:
		signalNaN64()
		return 0
	}
	exp, whole, _ := expWholeFrac(exp, significand)
	for exp > 0 && whole < math.MaxInt64/10 {
		exp--
		whole *= 10
	}
	if exp > 0 {
		return math.MaxInt64
	}
	return int64(1-2*sign) * int64(whole)
}
func (d Decimal64) IsZero() bool {
	flav, _, _, significand := d.parts()
	return significand == 0 && flav == flNormal
}
func (d Decimal64) IsInf() bool {
	flav, _, _, _ := d.parts()
	return flav == flInf
}
func (d Decimal64) IsNaN() bool {
	flav, _, _, _ := d.parts()
	return flav == flQNaN || flav == flSNaN
}
func (d Decimal64) IsQNaN() bool {
	flav, _, _, _ := d.parts()
	return flav == flQNaN
}
func (d Decimal64) IsSNaN() bool {
	flav, _, _, _ := d.parts()
	return flav == flSNaN
}
func (d Decimal64) IsInt() bool {
	flav, _, exp, significand := d.parts()
	switch flav {
	case flNormal:
		_, _, frac := expWholeFrac(exp, significand)
		return frac == 0
	default:
		return false
	}
}