forked from TrueCloudLab/frostfs-api-go
111 lines
2.8 KiB
Go
111 lines
2.8 KiB
Go
|
package decimal
|
||
|
|
||
|
import (
|
||
|
"math"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// GASPrecision contains precision for NEO Gas token.
|
||
|
const GASPrecision = 8
|
||
|
|
||
|
// Zero is empty Decimal value.
|
||
|
var Zero = &Decimal{}
|
||
|
|
||
|
// New returns new Decimal (in satoshi).
|
||
|
func New(v int64) *Decimal {
|
||
|
return NewWithPrecision(v, GASPrecision)
|
||
|
}
|
||
|
|
||
|
// NewGAS returns new Decimal * 1e8 (in GAS).
|
||
|
func NewGAS(v int64) *Decimal {
|
||
|
v *= int64(math.Pow10(GASPrecision))
|
||
|
return NewWithPrecision(v, GASPrecision)
|
||
|
}
|
||
|
|
||
|
// NewWithPrecision returns new Decimal with custom precision.
|
||
|
func NewWithPrecision(v int64, p uint32) *Decimal {
|
||
|
return &Decimal{Value: v, Precision: p}
|
||
|
}
|
||
|
|
||
|
// ParseFloat return new Decimal parsed from float64 * 1e8 (in GAS).
|
||
|
func ParseFloat(v float64) *Decimal {
|
||
|
return new(Decimal).Parse(v, GASPrecision)
|
||
|
}
|
||
|
|
||
|
// ParseFloatWithPrecision returns new Decimal parsed from float64 * 1^p.
|
||
|
func ParseFloatWithPrecision(v float64, p int) *Decimal {
|
||
|
return new(Decimal).Parse(v, p)
|
||
|
}
|
||
|
|
||
|
// Copy returns copy of current Decimal.
|
||
|
func (m *Decimal) Copy() *Decimal { return &Decimal{Value: m.Value, Precision: m.Precision} }
|
||
|
|
||
|
// Parse returns parsed Decimal from float64 * 1^p.
|
||
|
func (m *Decimal) Parse(v float64, p int) *Decimal {
|
||
|
m.Value = int64(v * math.Pow10(p))
|
||
|
m.Precision = uint32(p)
|
||
|
return m
|
||
|
}
|
||
|
|
||
|
// String returns string representation of Decimal.
|
||
|
func (m Decimal) String() string {
|
||
|
buf := new(strings.Builder)
|
||
|
val := m.Value
|
||
|
dec := int64(math.Pow10(int(m.Precision)))
|
||
|
if val < 0 {
|
||
|
buf.WriteRune('-')
|
||
|
val = -val
|
||
|
}
|
||
|
str := strconv.FormatInt(val/dec, 10)
|
||
|
buf.WriteString(str)
|
||
|
val %= dec
|
||
|
if val > 0 {
|
||
|
buf.WriteRune('.')
|
||
|
str = strconv.FormatInt(val, 10)
|
||
|
for i := len(str); i < int(m.Precision); i++ {
|
||
|
buf.WriteRune('0')
|
||
|
}
|
||
|
buf.WriteString(strings.TrimRight(str, "0"))
|
||
|
}
|
||
|
return buf.String()
|
||
|
}
|
||
|
|
||
|
// Add returns d + m.
|
||
|
func (m Decimal) Add(d *Decimal) *Decimal {
|
||
|
precision := m.Precision
|
||
|
if precision < d.Precision {
|
||
|
precision = d.Precision
|
||
|
}
|
||
|
return &Decimal{
|
||
|
Value: m.Value + d.Value,
|
||
|
Precision: precision,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Zero checks that Decimal is empty.
|
||
|
func (m Decimal) Zero() bool { return m.Value == 0 }
|
||
|
|
||
|
// Equal checks that current Decimal is equal to passed Decimal.
|
||
|
func (m Decimal) Equal(v *Decimal) bool { return m.Value == v.Value && m.Precision == v.Precision }
|
||
|
|
||
|
// GT checks that m > v.
|
||
|
func (m Decimal) GT(v *Decimal) bool { return m.Value > v.Value }
|
||
|
|
||
|
// GTE checks that m >= v.
|
||
|
func (m Decimal) GTE(v *Decimal) bool { return m.Value >= v.Value }
|
||
|
|
||
|
// LT checks that m < v.
|
||
|
func (m Decimal) LT(v *Decimal) bool { return m.Value < v.Value }
|
||
|
|
||
|
// LTE checks that m <= v.
|
||
|
func (m Decimal) LTE(v *Decimal) bool { return m.Value <= v.Value }
|
||
|
|
||
|
// Neg returns negative representation of current Decimal (m * -1).
|
||
|
func (m Decimal) Neg() *Decimal {
|
||
|
return &Decimal{
|
||
|
Value: m.Value * -1,
|
||
|
Precision: m.Precision,
|
||
|
}
|
||
|
}
|