// Subtract func (a Scalar) Sub_S(b S) S { var x, y big.Float x = big.Float(a) y = big.Float(b.(Scalar)) z := x.Sub(&x, &y) return (Scalar)(*z) }
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()) } } }
// Sqrt returns the square root n. func Sqrt(n *big.Float) *big.Float { prec := n.Prec() x := new(big.Float).SetPrec(prec).SetInt64(1) z := new(big.Float).SetPrec(prec).SetInt64(1) half := new(big.Float).SetPrec(prec).SetFloat64(0.5) t := new(big.Float).SetPrec(prec) for { z.Copy(x) t.Mul(x, x) t.Sub(t, n) t.Quo(t, x) t.Mul(t, half) x.Sub(x, t) if x.Cmp(z) == 0 { break } } return x }
// sincos iterates a sin or cos Taylor series. func sincos(name string, index int, x, z, exponent, factorial *big.Float) *big.Float { plus := false term := newF().Set(floatOne) for j := 0; j < index; j++ { term.Mul(term, x) } xN := newF().Set(term) x2 := newF().Mul(x, x) loop := newLoop(name, x, 4) for { // Invariant: factorial holds exponent!. term.Quo(term, factorial) if plus { z.Add(z, term) } else { z.Sub(z, term) } plus = !plus if loop.terminate(z) { break } // Advance x**index (multiply by x²). term.Mul(xN, x2) xN.Set(term) // Advance exponent and factorial. exponent.Add(exponent, floatOne) factorial.Mul(factorial, exponent) exponent.Add(exponent, floatOne) factorial.Mul(factorial, exponent) } return z }
// twoPiReduce guarantees x < 2𝛑; x is known to be >= 0 coming in. func twoPiReduce(x *big.Float) { // TODO: Is there an easy better algorithm? twoPi := newF().Set(floatTwo) twoPi.Mul(twoPi, floatPi) // Do something clever(er) if it's large. if x.Cmp(newF().SetInt64(1000)) > 0 { multiples := make([]*big.Float, 0, 100) sixteen := newF().SetInt64(16) multiple := newF().Set(twoPi) for { multiple.Mul(multiple, sixteen) if x.Cmp(multiple) < 0 { break } multiples = append(multiples, newF().Set(multiple)) } // From the right, subtract big multiples. for i := len(multiples) - 1; i >= 0; i-- { multiple := multiples[i] for x.Cmp(multiple) >= 0 { x.Sub(x, multiple) } } } for x.Cmp(twoPi) >= 0 { x.Sub(x, twoPi) } }
func mandelbrotFloat(a, b *big.Float) color.Color { var x, y, nx, ny, x2, y2, f2, f4, r2, tmp big.Float 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 }
// 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) }
// 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) }
// compute √z using newton to solve // t² - z = 0 for t func sqrtDirect(z *big.Float) *big.Float { // f(t)/f'(t) = 0.5(t² - z)/t half := big.NewFloat(0.5) f := func(t *big.Float) *big.Float { x := new(big.Float).Mul(t, t) // x = t² x.Sub(x, z) // x = t² - z x.Mul(half, x) // x = 0.5(t² - z) return x.Quo(x, t) // return x = 0.5(t² - z)/t } // initial guess zf, _ := z.Float64() guess := big.NewFloat(math.Sqrt(zf)) return newton(f, guess, z.Prec()) }
// 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 }
// This example shows how to use big.Float to compute the square root of 2 with // a precision of 200 bits, and how to print the result as a decimal number. func Example_sqrt2() { // We'll do computations with 200 bits of precision in the mantissa. const prec = 200 // Compute the square root of 2 using Newton's Method. We start with // an initial estimate for sqrt(2), and then iterate: // x_{n+1} = 1/2 * ( x_n + (2.0 / x_n) ) // Since Newton's Method doubles the number of correct digits at each // iteration, we need at least log_2(prec) steps. steps := int(math.Log2(prec)) // Initialize values we need for the computation. two := new(big.Float).SetPrec(prec).SetInt64(2) half := new(big.Float).SetPrec(prec).SetFloat64(0.5) // Use 1 as the initial estimate. x := new(big.Float).SetPrec(prec).SetInt64(1) // 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. t := new(big.Float) // Iterate. for i := 0; i <= steps; i++ { t.Quo(two, x) // t = 2.0 / x_n t.Add(x, t) // t = x_n + (2.0 / x_n) x.Mul(half, t) // x_{n+1} = 0.5 * t } // We can use the usual fmt.Printf verbs since big.Float implements fmt.Formatter fmt.Printf("sqrt(2) = %.50f\n", x) // Print the error between 2 and x*x. t.Mul(x, x) // t = x*x fmt.Printf("error = %e\n", t.Sub(two, t)) // Output: // sqrt(2) = 1.41421356237309504880168872420969807856967187537695 // error = 0.000000e+00 }
// Estimates the Variance based on the data set // If the data set is relatively small (< 1000 examples), then remove 1 from the total func (ad *AnomalyDetection) estimateVariance() *big.Float { // this means that the mean was never calculated before, therefore do it now // the means is needed for the cimputation of the deviation if ad.mean.Cmp(zero) == 0 { ad.estimateMean() } // initialize the total to zero totalVariance := big.NewFloat(0) totalDeviation := big.NewFloat(0) var deviation big.Float var deviationCopy big.Float var singleVariance big.Float // Loop while a is smaller than 1e100. for _, element := range ad.dataSet { // first calculate the deviation for each element, by subtracting the mean, take the absolute value deviation.Sub(&element, &ad.mean).Abs(&deviation) // add it to the total totalDeviation.Add(totalDeviation, &deviation) // calculate the variance by squaring it singleVariance = *deviationCopy.Mul(&deviation, &deviation) // ^2 // the calculate the variance totalVariance.Add(totalVariance, &singleVariance) } // calculate the variance // assign the variance to the anomaly detection object ad.variance = *totalVariance.Quo(totalVariance, &ad.totalSamples) // calculate the deviation ad.deviation = *totalDeviation.Quo(totalDeviation, &ad.totalSamples) return &ad.variance }
// compute √z using newton to solve // 1/t² - z = 0 for x and then inverting. func sqrtInverse(z *big.Float) *big.Float { // f(t)/f'(t) = -0.5t(1 - zt²) nhalf := big.NewFloat(-0.5) one := big.NewFloat(1) f := func(t *big.Float) *big.Float { u := new(big.Float) u.Mul(t, t) // u = t² u.Mul(u, z) // u = zt² u.Sub(one, u) // u = 1 - zt² u.Mul(u, nhalf) // u = -0.5(1 - zt²) return new(big.Float).Mul(t, u) // x = -0.5t(1 - zt²) } // initial guess zf, _ := z.Float64() guess := big.NewFloat(1 / math.Sqrt(zf)) // There's another operation after newton, // so we need to force it to return at least // a few guard digits. Use 32. x := newton(f, guess, z.Prec()+32) return x.Mul(z, x).SetPrec(z.Prec()) }