Beispiel #1
0
Datei: pslq.go Projekt: ncw/pslq
// 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
	}
}
Beispiel #3
0
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())
		}
	}
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
Datei: pslq.go Projekt: ncw/pslq
// 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)
}
Beispiel #7
0
// 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{}
}
Beispiel #8
0
// 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
}
Beispiel #9
0
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)
}
Beispiel #10
0
// 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
}
Beispiel #11
0
Datei: main.go Projekt: ncw/pslq
// 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
}
Beispiel #12
0
// 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())

}
Beispiel #13
0
// 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)
}
Beispiel #14
0
// 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)
	}
}
Beispiel #15
0
// 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())
}
Beispiel #16
0
// 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
}
Beispiel #17
0
// 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)
	}
}