// parseFilesize converts strings of form 10GB to a size in bytes. Fractional // sizes are truncated at the byte size. func parseFilesize(strSize string) (string, error) { units := []struct { suffix string multiplier int64 }{ {"kb", 1e3}, {"mb", 1e6}, {"gb", 1e9}, {"tb", 1e12}, {"kib", 1 << 10}, {"mib", 1 << 20}, {"gib", 1 << 30}, {"tib", 1 << 40}, {"b", 1}, // must be after others else it'll match on them all {"", 1}, // no suffix is still a valid suffix } strSize = strings.ToLower(strSize) for _, unit := range units { if strings.HasSuffix(strSize, unit.suffix) { r, ok := new(big.Rat).SetString(strings.TrimSuffix(strSize, unit.suffix)) if !ok { return "", errUnableToParseSize } r.Mul(r, new(big.Rat).SetInt(big.NewInt(unit.multiplier))) if !r.IsInt() { f, _ := r.Float64() return fmt.Sprintf("%d", int64(f)), nil } return r.RatString(), nil } } return "", errUnableToParseSize }
func renderRat(img *image.RGBA) { var yminR, ymaxMinR, heightR big.Rat yminR.SetInt64(ymin) ymaxMinR.SetInt64(ymax - ymin) heightR.SetInt64(height) var xminR, xmaxMinR, widthR big.Rat xminR.SetInt64(xmin) xmaxMinR.SetInt64(xmax - xmin) widthR.SetInt64(width) var y, x big.Rat for py := int64(0); py < height; py++ { // y := float64(py)/height*(ymax-ymin) + ymin y.SetInt64(py) y.Quo(&y, &heightR) y.Mul(&y, &ymaxMinR) y.Add(&y, &yminR) for px := int64(0); px < width; px++ { // x := float64(px)/width*(xmax-xmin) + xmin x.SetInt64(px) x.Quo(&x, &widthR) x.Mul(&x, &xmaxMinR) x.Add(&x, &xminR) c := mandelbrotRat(&x, &y) if c == nil { c = color.Black } img.Set(int(px), int(py), c) } } }
func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} { var z big.Rat switch op { case token.ADD: return z.Add(x, y) case token.SUB: return z.Sub(x, y) case token.MUL: return z.Mul(x, y) case token.QUO: return z.Quo(x, y) case token.EQL: return x.Cmp(y) == 0 case token.NEQ: return x.Cmp(y) != 0 case token.LSS: return x.Cmp(y) < 0 case token.LEQ: return x.Cmp(y) <= 0 case token.GTR: return x.Cmp(y) > 0 case token.GEQ: return x.Cmp(y) >= 0 } panic("unreachable") }
// hostconfigcmd is the handler for the command `siac host config [setting] [value]`. // Modifies host settings. func hostconfigcmd(param, value string) { switch param { case "price": // convert price to hastings/byte/block p, ok := new(big.Rat).SetString(value) if !ok { die("Could not parse price") } p.Mul(p, big.NewRat(1e24/1e9, 4320)) value = new(big.Int).Div(p.Num(), p.Denom()).String() case "totalstorage": // parse sizes of form 10GB, 10TB, 1TiB etc var err error value, err = parseSize(value) if err != nil { die("Could not parse totalstorage:", err) } case "minduration", "maxduration", "windowsize", "acceptingcontracts": // Other valid settings. default: // Reject invalid host config commands. die("\"" + param + "\" is not a host setting") } err := post("/host", param+"="+value) if err != nil { die("Could not update host settings:", err) } fmt.Println("Host settings updated.") }
// coinUnits converts a siacoin amount to base units. func coinUnits(amount string) (string, error) { units := []string{"pS", "nS", "uS", "mS", "SC", "KS", "MS", "GS", "TS"} for i, unit := range units { if strings.HasSuffix(amount, unit) { // scan into big.Rat r, ok := new(big.Rat).SetString(strings.TrimSuffix(amount, unit)) if !ok { return "", errors.New("malformed amount") } // convert units exp := 24 + 3*(int64(i)-4) mag := new(big.Int).Exp(big.NewInt(10), big.NewInt(exp), nil) r.Mul(r, new(big.Rat).SetInt(mag)) // r must be an integer at this point if !r.IsInt() { return "", errors.New("non-integer number of hastings") } return r.RatString(), nil } } // check for hastings separately if strings.HasSuffix(amount, "H") { return strings.TrimSuffix(amount, "H"), nil } return "", errors.New("amount is missing units; run 'wallet --help' for a list of units") }
func hostconfigcmd(param, value string) { // convert price to hastings/byte/block if param == "price" { p, ok := new(big.Rat).SetString(value) if !ok { fmt.Println("could not parse price") return } p.Mul(p, big.NewRat(1e24/1e9, 4320)) value = new(big.Int).Div(p.Num(), p.Denom()).String() } // parse sizes of form 10GB, 10TB, 1TiB etc if param == "totalstorage" { var err error value, err = parseSize(value) if err != nil { fmt.Println("could not parse " + param) } } err := post("/host", param+"="+value) if err != nil { fmt.Println("Could not update host settings:", err) return } fmt.Println("Host settings updated.") }
func Mul(a, b string) string { ra := new(big.Rat) rb := new(big.Rat) ra.SetString(a) rb.SetString(b) return ra.Mul(ra, rb).FloatString(4) }
func GasPrice(bp, gl, ep *big.Int) *big.Int { BP := new(big.Rat).SetInt(bp) GL := new(big.Rat).SetInt(gl) EP := new(big.Rat).SetInt(ep) GP := new(big.Rat).Quo(BP, GL) GP = GP.Quo(GP, EP) return GP.Mul(GP, etherInWei).Num() }
func (me *StatisticalAccumulator) Mean() *big.Rat { mean := new(big.Rat) mean.Inv(me.n) mean.Mul(mean, me.sigmaXI) return mean }
func tans(m []mTerm) *big.Rat { if len(m) == 1 { return tanEval(m[0].a, big.NewRat(m[0].n, m[0].d)) } half := len(m) / 2 a := tans(m[:half]) b := tans(m[half:]) r := new(big.Rat) return r.Quo(new(big.Rat).Add(a, b), r.Sub(one, r.Mul(a, b))) }
func (v1 Vector) Dot(v2 Vector) *big.Rat { if len(v1) != len(v2) { log.Fatalf("Lengths differ: %d != %d", len(v1), len(v2)) } d := new(big.Rat) c := new(big.Rat) for i, e := range v1 { d.Add(d, c.Mul(e, v2[i])) } return d }
// ParseCPUs takes a string ratio and returns an integer value of nano cpus func ParseCPUs(value string) (int64, error) { cpu, ok := new(big.Rat).SetString(value) if !ok { return 0, fmt.Errorf("failed to parse %v as a rational number", value) } nano := cpu.Mul(cpu, big.NewRat(1e9, 1)) if !nano.IsInt() { return 0, fmt.Errorf("value is too precise") } return nano.Num().Int64(), nil }
// Returns the parsed duration in nanoseconds, support 'u', 's', 'm', // 'h', 'd', 'W', 'M', and 'Y' suffixes. func ParseTimeDuration(value string) (int64, error) { var constant time.Duration prefixSize := 1 switch value[len(value)-1] { case 'u': constant = time.Microsecond case 's': constant = time.Second case 'm': constant = time.Minute case 'h': constant = time.Hour case 'd': constant = 24 * time.Hour case 'w', 'W': constant = Week case 'M': constant = Month case 'y', 'Y': constant = Year default: prefixSize = 0 } if value[len(value)-2:] == "ms" { constant = time.Millisecond prefixSize = 2 } t := big.Rat{} timeString := value if prefixSize > 0 { timeString = value[:len(value)-prefixSize] } _, err := fmt.Sscan(timeString, &t) if err != nil { return 0, err } if prefixSize > 0 { c := big.Rat{} c.SetFrac64(int64(constant), 1) t.Mul(&t, &c) } if t.IsInt() { return t.Num().Int64(), nil } f, _ := t.Float64() return int64(f), nil }
func (me *StatisticalAccumulator) PutRat(x *big.Rat) { me.n.Add(me.n, me.one) me.sigmaXI.Add(me.sigmaXI, x) xSquared := new(big.Rat) xSquared.Mul(x, x) me.sigmaXISquared.Add(me.sigmaXISquared, xSquared) }
// floatString returns the string representation for a // numeric value v in normalized floating-point format. func floatString(v exact.Value) string { if exact.Sign(v) == 0 { return "0.0" } // x != 0 // convert |v| into a big.Rat x x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v))) // normalize x and determine exponent e // (This is not very efficient, but also not speed-critical.) var e int for x.Cmp(ten) >= 0 { x.Quo(x, ten) e++ } for x.Cmp(one) < 0 { x.Mul(x, ten) e-- } // TODO(gri) Values such as 1/2 are easier to read in form 0.5 // rather than 5.0e-1. Similarly, 1.0e1 is easier to read as // 10.0. Fine-tune best exponent range for readability. s := x.FloatString(100) // good-enough precision // trim trailing 0's i := len(s) for i > 0 && s[i-1] == '0' { i-- } s = s[:i] // add a 0 if the number ends in decimal point if len(s) > 0 && s[len(s)-1] == '.' { s += "0" } // add exponent and sign if e != 0 { s += fmt.Sprintf("e%+d", e) } if exact.Sign(v) < 0 { s = "-" + s } // TODO(gri) If v is a "small" fraction (i.e., numerator and denominator // are just a small number of decimal digits), add the exact fraction as // a comment. For instance: 3.3333...e-1 /* = 1/3 */ return s }
func (c *nanoCPUs) Set(value string) error { cpu, ok := new(big.Rat).SetString(value) if !ok { return fmt.Errorf("Failed to parse %v as a rational number", value) } nano := cpu.Mul(cpu, big.NewRat(1e9, 1)) if !nano.IsInt() { return fmt.Errorf("value is too precise") } *c = nanoCPUs(nano.Num().Int64()) return nil }
func abs(x *complexRat) *big.Rat { r := new(big.Rat) i := new(big.Rat) r.Set(x.r) i.Set(x.i) r.Mul(r, x.r) // r^2 i.Mul(i, x.i) // i^2 r.Add(r, i) // r^2 + i^2 return sqrtFloat(r) // sqrt(r^2 + i^2) }
// Returns hash if they intersect, otherwise nil func Intersect(P1, Q1, P2, Q2 Vec) ([20]byte, bool) { // Vectors with same length and direction as line segments v1 := Q1.Sub(P1) v2 := Q2.Sub(P2) // Parallel vectors never intersect det := v2.X*v1.Y - v1.X*v2.Y if det == 0 { return sha1nil, false } // Intersection is calculated using linear algebra var k1, k2 big.Rat Pdx, Pdy := P2.X-P1.X, P2.Y-P1.Y invDet := big.NewRat(1, det) k1.Mul(invDet, big.NewRat(-v2.Y*Pdx+v2.X*Pdy, 1)) k2.Mul(invDet, big.NewRat(-v1.Y*Pdx+v1.X*Pdy, 1)) // Check if intersection is inside both segments zero := big.NewRat(0, 1) one := big.NewRat(1, 1) k1valid := k1.Cmp(zero) == 1 && k1.Cmp(one) == -1 k2valid := k2.Cmp(zero) == 1 && k2.Cmp(one) == -1 // Return hash of intersection coordinate if it was if k1valid && k2valid { var Ix, Iy big.Rat Ix.Mul(big.NewRat(v1.X, 1), &k1).Add(&Ix, big.NewRat(P1.X, 1)) Iy.Mul(big.NewRat(v1.Y, 1), &k1).Add(&Iy, big.NewRat(P1.Y, 1)) return sha1.Sum([]byte(fmt.Sprintf("%v,%v", Ix.String(), Iy.String()))), true } else { return sha1nil, false } }
func mandelbrotRat(a, b *big.Rat) color.Color { var x, y, nx, ny, x2, y2, f2, f4, r2, tmp big.Rat f2.SetInt64(2) f4.SetInt64(4) x.SetInt64(0) y.SetInt64(0) defer func() { recover() }() for n := uint8(0); n < iterations; n++ { // Not update x2 and y2 // because they are already updated in the previous loop nx.Sub(&x2, &y2) nx.Add(&nx, a) tmp.Mul(&x, &y) ny.Mul(&f2, &tmp) ny.Add(&ny, b) x.Set(&nx) y.Set(&ny) x2.Mul(&x, &x) y2.Mul(&y, &y) r2.Add(&x2, &y2) if r2.Cmp(&f4) > 0 { return color.Gray{255 - contrast*n} } } return color.Black }
func tanEval(coef int64, f *big.Rat) *big.Rat { if coef == 1 { return f } if coef < 0 { r := tanEval(-coef, f) return r.Neg(r) } ca := coef / 2 cb := coef - ca a := tanEval(ca, f) b := tanEval(cb, f) r := new(big.Rat) return r.Quo(new(big.Rat).Add(a, b), r.Sub(one, r.Mul(a, b))) }
// Compute 4*(1 - 1/3 + 1/5 - 1/7 + 1/9 - ...) func main() { sum := big.NewRat(0, 1) var sumTimes4 big.Rat for i, sign := int64(1), int64(1); i < 10000000; i, sign = i+2, -sign { part := big.NewRat(sign, i) sum.Add(sum, part) if (i+1)%1000 == 0 { sumTimes4.Mul(big.NewRat(4, 1), sum) fmt.Printf("%v, %v\n", i+1, sumTimes4.FloatString(10)) } } }
// returns number of Nanoseconds func (t *milliSecsOf256th) MilliSecs(m Measure) uint { r := new(big.Rat) r.Mul(t.Rat, big.NewRat(int64(int(m)), 1)) f, _ := r.Float64() // fmt.Printf("Nanoseconds: %0.2f\n", f*1000000) return uint(f * 1000000) /* a := big.NewRat(64, 60) b := big.NewRat(1, int64(uint(t))) z := new(big.Rat) z = z.Mul(a, b) z = z.Mul(z, big.NewRat(int64(int(m)), 1)) f, _ := z.Float64() fmt.Printf("ticksPerMinute: %0.2f", f*1000) return uint(f * 1000) */ }
// Returns the parsed duration in nanoseconds, support 'u', 's', 'm', // 'h', 'd' and 'w' suffixes. func ParseTimeDuration(value string) (int64, error) { var constant time.Duration hasPrefix := true switch value[len(value)-1] { case 'u': constant = time.Microsecond case 's': constant = time.Second case 'm': constant = time.Minute case 'h': constant = time.Hour case 'd': constant = 24 * time.Hour case 'w': constant = 7 * 24 * time.Hour case 'y': constant = 365 * 24 * time.Hour default: hasPrefix = false } t := big.Rat{} timeString := value if hasPrefix { timeString = value[:len(value)-1] } _, err := fmt.Sscan(timeString, &t) if err != nil { return 0, err } if hasPrefix { c := big.Rat{} c.SetFrac64(int64(constant), 1) t.Mul(&t, &c) } if t.IsInt() { return t.Num().Int64(), nil } f, _ := t.Float64() return int64(f), nil }
// hostcmd is the handler for the command `siac host`. // Prints info about the host. func hostcmd() { hg := new(api.HostGET) err := getAPI("/host", &hg) if err != nil { die("Could not fetch host settings:", err) } // convert accepting bool accept := yesNo(hg.AcceptingContracts) // convert price to SC/GB/mo price := new(big.Rat).SetInt(hg.Price.Big()) price.Mul(price, big.NewRat(4320, 1e24/1e9)) fmt.Printf(`Host info: Storage: %v (%v used) Price: %v SC per GB per month Max Duration: %v Blocks Contracts: %v Accepting Contracts: %v Anticipated Revenue: %v Revenue: %v Lost Revenue: %v `, filesizeUnits(hg.TotalStorage), filesizeUnits(hg.TotalStorage-hg.StorageRemaining), price.FloatString(3), hg.MaxDuration, hg.NumContracts, accept, hg.AnticipatedRevenue, hg.Revenue, hg.LostRevenue) // display more info if verbose flag is set if !hostVerbose { return } fmt.Printf(` Net Address: %v Unlock Hash: %v (NOT a wallet address!) RPC Stats: Error Calls: %v Unrecognized Calls: %v Download Calls: %v Renew Calls: %v Revise Calls: %v Settings Calls: %v Upload Calls: %v `, hg.NetAddress, hg.UnlockHash, hg.RPCErrorCalls, hg.RPCUnrecognizedCalls, hg.RPCDownloadCalls, hg.RPCRenewCalls, hg.RPCReviseCalls, hg.RPCSettingsCalls, hg.RPCUploadCalls) }
func Parse(v string) (xdr.Int64, error) { var f, o, r big.Rat _, ok := f.SetString(v) if !ok { return xdr.Int64(0), fmt.Errorf("cannot parse amount: %s", v) } o.SetInt64(One) r.Mul(&f, &o) is := r.FloatString(0) i, err := strconv.ParseInt(is, 10, 64) if err != nil { return xdr.Int64(0), err } return xdr.Int64(i), nil }
func hostconfigcmd(param, value string) { // convert price to hastings/byte/block if param == "price" { p, ok := new(big.Rat).SetString(value) if !ok { fmt.Println("could not parse price") return } p.Mul(p, big.NewRat(1e24/1e9, 4320)) value = new(big.Int).Div(p.Num(), p.Denom()).String() } err := post("/host/configure", param+"="+value) if err != nil { fmt.Println("Could not update host settings:", err) return } fmt.Println("Host settings updated.") }
func sqrtFloat(x *big.Rat) *big.Rat { t1 := new(big.Rat) t2 := new(big.Rat) t1.Set(x) // Iterate. // x{n} = (x{n-1}+x{0}/x{n-1}) / 2 for i := 0; i <= 4; i++ { if t1.Cmp(zero) == 0 { return t1 } t2.Quo(x, t1) t2.Add(t2, t1) t1.Mul(half, t2) } return t1 }
func hoststatuscmd() { info := new(modules.HostInfo) err := getAPI("/host/status", info) if err != nil { fmt.Println("Could not fetch host settings:", err) return } // convert price to SC/GB/mo price := new(big.Rat).SetInt(info.Price.Big()) price.Mul(price, big.NewRat(4320, 1e24/1e9)) fmt.Printf(`Host settings: Storage: %v (%v used) Price: %v SC per GB per month Collateral: %v Max Filesize: %v Max Duration: %v Contracts: %v `, filesizeUnits(info.TotalStorage), filesizeUnits(info.TotalStorage-info.StorageRemaining), price.FloatString(3), info.Collateral, info.MaxFilesize, info.MaxDuration, info.NumContracts) }
// measure via string //func m_(s string) Measure { func m_(s string) float64 { r := new(big.Rat) _, ok := r.SetString(s) if !ok { panic("can't convert to measure") } x := new(big.Rat) // d := big.NewRat(1, 256) d := big.NewRat(256, 1) x.Mul(r, d) f, _ := x.Float64() //return Measure(int(f)) return f }
func mul(x, y *complexRat) *complexRat { t1 := new(big.Rat) t2 := new(big.Rat) z := newComplexRat() t1.Mul(x.r, y.r) t2.Mul(x.i, y.i) z.r.Sub(t1, t2) t1.Mul(x.r, y.i) t2.Mul(x.i, y.r) z.i.Add(t1, t2) return z }