// Compute the square root of n using Newton's Method. We start with // an initial estimate for sqrt(n), and then iterate // x_{i+1} = 1/2 * ( x_i + (n / x_i) ) // Result is returned in x func (e *Pslq) Sqrt(n, x *big.Float) { if n == x { panic("need distinct input and output") } if n.Sign() == 0 { x.Set(n) return } else if n.Sign() < 0 { panic("Sqrt of negative number") } prec := n.Prec() // Use the floating point square root as initial estimate nFloat64, _ := n.Float64() x.SetPrec(prec).SetFloat64(math.Sqrt(nFloat64)) // We use t as a temporary variable. There's no need to set its precision // since big.Float values with unset (== 0) precision automatically assume // the largest precision of the arguments when used as the result (receiver) // of a big.Float operation. var t big.Float // Iterate. for { t.Quo(n, x) // t = n / x_i t.Add(x, &t) // t = x_i + (n / x_i) t.Mul(&e.half, &t) // x_{i+1} = 0.5 * t if x.Cmp(&t) == 0 { // Exit loop if no change to result break } x.Set(&t) } }
func (bed BinaryVarintEncoderDecoder) Decode(r io.Reader, n *big.Float) error { var isInteger int8 var f float64 var exponent int32 n.SetUint64(0) if err := binary.Read(r, binary.BigEndian, &isInteger); err != nil { return err } if isInteger <= 0 { var x int64 var err error if x, err = binary.ReadVarint(miniByteReader{r}); err != nil { return err } n.SetInt64(x) n.SetPrec(ENCODER_DECODER_PREC) return nil } else { if err := binary.Read(r, binary.BigEndian, &f); err != nil { return err } if err := binary.Read(r, binary.BigEndian, &exponent); err != nil { return err } bed.tmp.SetFloat64(f) bed.tmp.SetPrec(ENCODER_DECODER_PREC) n.SetMantExp(bed.tmp, int(exponent)) return nil } }
func TestSqrt(t *testing.T) { tests := []struct { prec uint in float64 }{ {16, 0}, {16, 1}, {16, 4}, {16, 10000}, {16, 2}, {64, 2}, {256, 2}, {1024, 1.5}, } for _, test := range tests { x := new(big.Float).SetPrec(test.prec) x.SetFloat64(test.in) var got, got2, diff big.Float pslq := New(test.prec) pslq.Sqrt(x, &got) got2.SetPrec(test.prec).Mul(&got, &got) diff.Sub(&got2, x) if diff.MinPrec() > 1 { t.Errorf("sqrt(%f) prec %d wrong got %.20f square %.20f expecting %f diff %g minprec %d", test.in, test.prec, &got, &got2, x, &diff, diff.MinPrec()) } } }
func (a *Mpint) SetFloat(b *Mpflt) int { // avoid converting huge floating-point numbers to integers // (2*Mpprec is large enough to permit all tests to pass) if b.Val.MantExp(nil) > 2*Mpprec { return -1 } if _, acc := b.Val.Int(&a.Val); acc == big.Exact { return 0 } const delta = 16 // a reasonably small number of bits > 0 var t big.Float t.SetPrec(Mpprec - delta) // try rounding down a little t.SetMode(big.ToZero) t.Set(&b.Val) if _, acc := t.Int(&a.Val); acc == big.Exact { return 0 } // try rounding up a little t.SetMode(big.AwayFromZero) t.Set(&b.Val) if _, acc := t.Int(&a.Val); acc == big.Exact { return 0 } return -1 }
func (sed StringEncoderDecoder) Decode(r io.Reader, n *big.Float) error { n.SetFloat64(0) n.SetPrec(ENCODER_DECODER_PREC) buf := make([]byte, 256) if _, err := r.Read(buf); err != nil { return err } _, _, err := n.Parse(string(buf), 10) return err }
// NearestInt set res to the nearest integer to x func (e *Pslq) NearestInt(x *big.Float, res *big.Int) { prec := x.Prec() var tmp big.Float tmp.SetPrec(prec) if x.Sign() >= 0 { tmp.Add(x, &e.half) } else { tmp.Sub(x, &e.half) } tmp.Int(res) }
// ToInt converts x to an Int value if x is representable as an Int. // Otherwise it returns an Unknown. func ToInt(x Value) Value { switch x := x.(type) { case int64Val, intVal: return x case ratVal: if x.val.IsInt() { return makeInt(x.val.Num()) } case floatVal: // avoid creation of huge integers // (Existing tests require permitting exponents of at least 1024; // allow any value that would also be permissible as a fraction.) if smallRat(x.val) { i := newInt() if _, acc := x.val.Int(i); acc == big.Exact { return makeInt(i) } // If we can get an integer by rounding up or down, // assume x is not an integer because of rounding // errors in prior computations. const delta = 4 // a small number of bits > 0 var t big.Float t.SetPrec(prec - delta) // try rounding down a little t.SetMode(big.ToZero) t.Set(x.val) if _, acc := t.Int(i); acc == big.Exact { return makeInt(i) } // try rounding up a little t.SetMode(big.AwayFromZero) t.Set(x.val) if _, acc := t.Int(i); acc == big.Exact { return makeInt(i) } } case complexVal: if re := ToFloat(x); re.Kind() == Float { return ToInt(re) } } return unknownVal{} }
// sqrt for big.Float func sqrt(given *big.Float) *big.Float { const prec = 200 steps := int(math.Log2(prec)) given.SetPrec(prec) half := new(big.Float).SetPrec(prec).SetFloat64(0.5) x := new(big.Float).SetPrec(prec).SetInt64(1) t := new(big.Float) for i := 0; i <= steps; i++ { t.Quo(given, x) t.Add(x, t) t.Mul(half, t) } return x }
func ExampleFloat_Add() { // Operating on numbers of different precision. var x, y, z big.Float x.SetInt64(1000) // x is automatically set to 64bit precision y.SetFloat64(2.718281828) // y is automatically set to 53bit precision z.SetPrec(32) z.Add(&x, &y) fmt.Printf("x = %s (%s, prec = %d, acc = %s)\n", &x, x.Format('p', 0), x.Prec(), x.Acc()) fmt.Printf("y = %s (%s, prec = %d, acc = %s)\n", &y, y.Format('p', 0), y.Prec(), y.Acc()) fmt.Printf("z = %s (%s, prec = %d, acc = %s)\n", &z, z.Format('p', 0), z.Prec(), z.Acc()) // Output: // x = 1000 (0x.fap10, prec = 64, acc = Exact) // y = 2.718281828 (0x.adf85458248cd8p2, prec = 53, acc = Exact) // z = 1002.718282 (0x.faadf854p10, prec = 32, acc = Below) }
// Exp returns a big.Float representation of exp(z). Precision is // the same as the one of the argument. The function returns +Inf // when z = +Inf, and 0 when z = -Inf. func Exp(z *big.Float) *big.Float { // exp(0) == 1 if z.Sign() == 0 { return big.NewFloat(1).SetPrec(z.Prec()) } // Exp(+Inf) = +Inf if z.IsInf() && z.Sign() > 0 { return big.NewFloat(math.Inf(+1)).SetPrec(z.Prec()) } // Exp(-Inf) = 0 if z.IsInf() && z.Sign() < 0 { return big.NewFloat(0).SetPrec(z.Prec()) } guess := new(big.Float) // try to get initial estimate using IEEE-754 math zf, _ := z.Float64() if zfs := math.Exp(zf); zfs == math.Inf(+1) || zfs == 0 { // too big or too small for IEEE-754 math, // perform argument reduction using // e^{2z} = (e^z)² halfZ := new(big.Float).Mul(z, big.NewFloat(0.5)) halfExp := Exp(halfZ.SetPrec(z.Prec() + 64)) return new(big.Float).Mul(halfExp, halfExp).SetPrec(z.Prec()) } else { // we got a nice IEEE-754 estimate guess.SetFloat64(zfs) } // f(t)/f'(t) = t*(log(t) - z) f := func(t *big.Float) *big.Float { x := new(big.Float) x.Sub(Log(t), z) return x.Mul(x, t) } x := newton(f, guess, z.Prec()) return x }
// Read lines from in as big.Float func read(in io.Reader, xs []big.Float) []big.Float { scanner := bufio.NewScanner(in) for scanner.Scan() { var x big.Float x.SetPrec(*prec) text := strings.TrimSpace(scanner.Text()) if len(text) == 0 || text[0] == '#' { continue } _, ok := x.SetString(text) if !ok { log.Fatalf("Failed to parse line %q", text) } xs = append(xs, x) } if err := scanner.Err(); err != nil { log.Fatalf("Error reading input: %v", err) } return xs }
// Pow returns a big.Float representation of z**w. Precision is the same as the one // of the first argument. The function panics when z is negative. func Pow(z *big.Float, w *big.Float) *big.Float { if z.Sign() < 0 { panic("Pow: negative base") } // Pow(z, 0) = 1.0 if w.Sign() == 0 { return big.NewFloat(1).SetPrec(z.Prec()) } // Pow(z, 1) = z // Pow(+Inf, n) = +Inf if w.Cmp(big.NewFloat(1)) == 0 || z.IsInf() { return new(big.Float).Copy(z) } // Pow(z, -w) = 1 / Pow(z, w) if w.Sign() < 0 { x := new(big.Float) zExt := new(big.Float).Copy(z).SetPrec(z.Prec() + 64) wNeg := new(big.Float).Neg(w) return x.Quo(big.NewFloat(1), Pow(zExt, wNeg)).SetPrec(z.Prec()) } // w integer fast path if w.IsInt() { wi, _ := w.Int64() return powInt(z, int(wi)) } // compute w**z as exp(z log(w)) x := new(big.Float).SetPrec(z.Prec() + 64) logZ := Log(new(big.Float).Copy(z).SetPrec(z.Prec() + 64)) x.Mul(w, logZ) x = Exp(x) return x.SetPrec(z.Prec()) }
// Returns pi using Machin's formula func pi(prec uint, result *big.Float) { var tmp, _4 big.Float _4.SetPrec(prec).SetInt64(4) acot(prec, 5, &tmp) tmp.SetPrec(prec).Mul(&tmp, &_4) acot(prec, 239, result) result.Sub(&tmp, result) result.SetPrec(prec).Mul(result, &_4) }
// Returns acot(x) in result func acot(prec uint, x int64, result *big.Float) { var term, power, _x, _kp, x2, oldresult big.Float _x.SetPrec(prec).SetInt64(x) power.SetPrec(prec).SetInt64(1) power.Quo(&power, &_x) // 1/x x2.Mul(&_x, &_x) result.SetPrec(prec).SetInt64(0) positive := true for k := int64(1); ; k += 2 { oldresult.Set(result) kp := k if !positive { kp = -k } positive = !positive _kp.SetPrec(prec).SetInt64(kp) term.Quo(&power, &_kp) result.Add(result, &term) if oldresult.Cmp(result) == 0 { break } power.Quo(&power, &x2) } }
// Log returns a big.Float representation of the natural logarithm of // z. Precision is the same as the one of the argument. The function // panics if z is negative, returns -Inf when z = 0, and +Inf when z = // +Inf func Log(z *big.Float) *big.Float { // panic on negative z if z.Sign() == -1 { panic("Log: argument is negative") } // Log(0) = -Inf if z.Sign() == 0 { return big.NewFloat(math.Inf(-1)).SetPrec(z.Prec()) } prec := z.Prec() + 64 // guard digits one := big.NewFloat(1).SetPrec(prec) two := big.NewFloat(2).SetPrec(prec) four := big.NewFloat(4).SetPrec(prec) // Log(1) = 0 if z.Cmp(one) == 0 { return big.NewFloat(0).SetPrec(z.Prec()) } // Log(+Inf) = +Inf if z.IsInf() { return big.NewFloat(math.Inf(+1)).SetPrec(z.Prec()) } x := new(big.Float).SetPrec(prec) // if 0 < z < 1 we compute log(z) as -log(1/z) var neg bool if z.Cmp(one) < 0 { x.Quo(one, z) neg = true } else { x.Set(z) } // We scale up x until x >= 2**(prec/2), and then we'll be allowed // to use the AGM formula for Log(x). // // Double x until the condition is met, and keep track of the // number of doubling we did (needed to scale back later). lim := new(big.Float) lim.SetMantExp(two, int(prec/2)) k := 0 for x.Cmp(lim) < 0 { x.Mul(x, x) k++ } // Compute the natural log of x using the fact that // log(x) = π / (2 * AGM(1, 4/x)) // if // x >= 2**(prec/2), // where prec is the desired precision (in bits) pi := pi(prec) agm := agm(one, x.Quo(four, x)) // agm = AGM(1, 4/x) x.Quo(pi, x.Mul(two, agm)) // reuse x, we don't need it if neg { x.Neg(x) } // scale the result back multiplying by 2**-k // reuse lim to reduce allocations. x.Mul(x, lim.SetMantExp(one, -k)) return x.SetPrec(z.Prec()) }
// used to ensure all of the big.Floats end up with the same precision func newBigFloat(n uint64) *big.Float { tmp := new(big.Float).SetUint64(n) tmp.SetPrec(ENCODER_DECODER_PREC) return tmp }
// Evaluates a BBP term // // sum(k=0->inf)(1/base**k * (1/a*k + b)) func bbp(prec uint, base, a, b int64, result *big.Float) { var term, power, aFp, bFp, _1, k, _base, oldresult big.Float power.SetPrec(prec).SetInt64(1) result.SetPrec(prec).SetInt64(0) aFp.SetPrec(prec).SetInt64(a) bFp.SetPrec(prec).SetInt64(b) _1.SetPrec(prec).SetInt64(1) k.SetPrec(prec).SetInt64(0) _base.SetPrec(prec).SetInt64(base) for { oldresult.Set(result) term.Mul(&aFp, &k) term.Add(&term, &bFp) term.Quo(&_1, &term) term.Mul(&term, &power) result.Add(result, &term) if oldresult.Cmp(result) == 0 { break } power.Quo(&power, &_base) k.Add(&k, &_1) } }