lotus/chain/types/bigint.go
Peter Rabbitson c2e5a837e6 Adjust various CLI display ratios to arbitrary precision
Originally the deviations from using float64 were insignificant, but at
exabyte scale they start to show up. Cleanup all displays, and clarify
the expectation text, adding an extra 99.9% probability calculator to
`lotus-miner info`
2021-05-25 14:09:01 +02:00

102 lines
2.1 KiB
Go

package types
import (
"fmt"
"math/big"
big2 "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/build"
)
const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
var TotalFilecoinInt = FromFil(build.FilBase)
var EmptyInt = BigInt{}
type BigInt = big2.Int
func NewInt(i uint64) BigInt {
return BigInt{Int: big.NewInt(0).SetUint64(i)}
}
func FromFil(i uint64) BigInt {
return BigMul(NewInt(i), NewInt(build.FilecoinPrecision))
}
func BigFromBytes(b []byte) BigInt {
i := big.NewInt(0).SetBytes(b)
return BigInt{Int: i}
}
func BigFromString(s string) (BigInt, error) {
v, ok := big.NewInt(0).SetString(s, 10)
if !ok {
return BigInt{}, fmt.Errorf("failed to parse string as a big int")
}
return BigInt{Int: v}, nil
}
func BigMul(a, b BigInt) BigInt {
return BigInt{Int: big.NewInt(0).Mul(a.Int, b.Int)}
}
func BigDiv(a, b BigInt) BigInt {
return BigInt{Int: big.NewInt(0).Div(a.Int, b.Int)}
}
func BigDivFloat(num, den BigInt) float64 {
res, _ := new(big.Rat).SetFrac(num.Int, den.Int).Float64()
return res
}
func BigMod(a, b BigInt) BigInt {
return BigInt{Int: big.NewInt(0).Mod(a.Int, b.Int)}
}
func BigAdd(a, b BigInt) BigInt {
return BigInt{Int: big.NewInt(0).Add(a.Int, b.Int)}
}
func BigSub(a, b BigInt) BigInt {
return BigInt{Int: big.NewInt(0).Sub(a.Int, b.Int)}
}
func BigCmp(a, b BigInt) int {
return a.Int.Cmp(b.Int)
}
var byteSizeUnits = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"}
func SizeStr(bi BigInt) string {
r := new(big.Rat).SetInt(bi.Int)
den := big.NewRat(1, 1024)
var i int
for f, _ := r.Float64(); f >= 1024 && i+1 < len(byteSizeUnits); f, _ = r.Float64() {
i++
r = r.Mul(r, den)
}
f, _ := r.Float64()
return fmt.Sprintf("%.4g %s", f, byteSizeUnits[i])
}
var deciUnits = []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"}
func DeciStr(bi BigInt) string {
r := new(big.Rat).SetInt(bi.Int)
den := big.NewRat(1, 1024)
var i int
for f, _ := r.Float64(); f >= 1024 && i+1 < len(deciUnits); f, _ = r.Float64() {
i++
r = r.Mul(r, den)
}
f, _ := r.Float64()
return fmt.Sprintf("%.3g %s", f, deciUnits[i])
}