Ejemplo n.º 1
0
Archivo: sqrt.go Proyecto: db47h/ivy
// floatSqrt computes the square root of x using Newton's method.
// TODO: Use a better algorithm such as the one from math/sqrt.go.
func floatSqrt(c Context, x *big.Float) *big.Float {
	switch x.Sign() {
	case -1:
		Errorf("square root of negative number")
	case 0:
		return newFloat(c)
	}

	// Each iteration computes
	// 	z = z - (z²-x)/2z
	// z holds the result so far. A good starting point is to halve the exponent.
	// Experiments show we converge in only a handful of iterations.
	z := newFloat(c)
	exp := x.MantExp(z)
	z.SetMantExp(z, exp/2)

	// Intermediates, allocated once.
	zSquared := newFloat(c)
	num := newFloat(c)
	den := newFloat(c)

	for loop := newLoop(c.Config(), "sqrt", x, 1); ; {
		zSquared.Mul(z, z)
		num.Sub(zSquared, x)
		den.Mul(floatTwo, z)
		num.Quo(num, den)
		z.Sub(z, num)
		if loop.done(z) {
			break
		}
	}
	return z
}
Ejemplo n.º 2
0
Archivo: value.go Proyecto: 2thetop/go
// smallRat reports whether x would lead to "reasonably"-sized fraction
// if converted to a *big.Rat.
func smallRat(x *big.Float) bool {
	if !x.IsInf() {
		e := x.MantExp(nil)
		return -maxExp < e && e < maxExp
	}
	return false
}
Ejemplo n.º 3
0
Archivo: value.go Proyecto: adityavs/go
// toRat returns the fraction corresponding to x, or nil
// if x cannot be represented as a fraction a/b because
// its components a or b are too large.
func toRat(x *big.Float) *big.Rat {
	m := newFloat()
	e := x.MantExp(m)

	// fail to convert if fraction components are too large
	if e <= maxExp || e >= maxExp {
		return nil
	}

	// convert mantissa to big.Int value by shifting by ecorr
	ecorr := int(m.MinPrec())
	a, _ := m.SetMantExp(m, ecorr).Int(nil)
	e -= ecorr // correct exponent

	// compute actual fraction
	b := big.NewInt(1)
	switch {
	case e < 0:
		b.Lsh(b, uint(-e))
	case e > 0:
		a.Lsh(a, uint(e))
	}

	return new(big.Rat).SetFrac(a, b)
}
Ejemplo n.º 4
0
// floatLog computes natural log(x) using the Maclaurin series for log(1-x).
func floatLog(x *big.Float) *big.Float {
	if x.Sign() <= 0 {
		Errorf("log of non-positive value")
	}
	// The series wants x < 1, and log 1/x == -log x, so exploit that.
	invert := false
	if x.Cmp(floatOne) > 0 {
		invert = true
		xx := newF()
		xx.Quo(floatOne, x)
		x = xx
	}

	// x = mantissa * 2**exp, and 0.5 <= mantissa < 1.
	// So log(x) is log(mantissa)+exp*log(2), and 1-x will be
	// between 0 and 0.5, so the series for 1-x will converge well.
	// (The series converges slowly in general.)
	mantissa := newF()
	exp2 := x.MantExp(mantissa)
	exp := newF().SetInt64(int64(exp2))
	exp.Mul(exp, floatLog2)
	if invert {
		exp.Neg(exp)
	}

	// y = 1-x (whereupon x = 1-y and we use that in the series).
	y := newF().SetInt64(1)
	y.Sub(y, mantissa)

	// The Maclaurin series for log(1-y) == log(x) is: -y - y²/2 - y³/3 ...

	yN := newF().Set(y)
	term := newF()
	n := newF().Set(floatOne)
	z := newF()

	// This is the slowest-converging series, so we add a factor of ten to the cutoff.
	// Only necessary when FloatPrec is at or beyond constPrecisionInBits.
	loop := newLoop("log", y, 40)
	for {
		term.Set(yN)
		term.Quo(term, n)
		z.Sub(z, term)
		if loop.terminate(z) {
			break
		}
		// Advance y**index (multiply by y).
		yN.Mul(yN, y)
		n.Add(n, floatOne)
	}

	if invert {
		z.Neg(z)
	}
	z.Add(z, exp)

	return z
}
Ejemplo n.º 5
0
func (bed BinaryEncoderDecoder) Encode(w io.Writer, n *big.Float) error {
	exponent := n.MantExp(bed.tmp)
	f, _ := bed.tmp.Float64()

	if err := binary.Write(w, binary.BigEndian, f); err != nil {
		return err
	}
	return binary.Write(w, binary.BigEndian, int32(exponent))
}
Ejemplo n.º 6
0
// Sqrt returns a big.Float representation of the square root of
// z. Precision is the same as the one of the argument. The function
// panics if z is negative, returns ±0 when z = ±0, and +Inf when z =
// +Inf.
func Sqrt(z *big.Float) *big.Float {

	// panic on negative z
	if z.Sign() == -1 {
		panic("Sqrt: argument is negative")
	}

	// √±0 = ±0
	if z.Sign() == 0 {
		return big.NewFloat(float64(z.Sign()))
	}

	// √+Inf  = +Inf
	if z.IsInf() {
		return big.NewFloat(math.Inf(+1))
	}

	// Compute √(a·2**b) as
	//   √(a)·2**b/2       if b is even
	//   √(2a)·2**b/2      if b > 0 is odd
	//   √(0.5a)·2**b/2    if b < 0 is odd
	//
	// The difference in the odd exponent case is due to the fact that
	// exp/2 is rounded in different directions when exp is negative.
	mant := new(big.Float)
	exp := z.MantExp(mant)
	switch exp % 2 {
	case 1:
		mant.Mul(big.NewFloat(2), mant)
	case -1:
		mant.Mul(big.NewFloat(0.5), mant)
	}

	// Solving x² - z = 0 directly requires a Quo call, but it's
	// faster for small precisions.
	//
	// Solving 1/x² - z = 0 avoids the Quo call and is much faster for
	// high precisions.
	//
	// Use sqrtDirect for prec <= 128 and sqrtInverse for prec > 128.
	var x *big.Float
	if z.Prec() <= 128 {
		x = sqrtDirect(mant)
	} else {
		x = sqrtInverse(mant)
	}

	// re-attach the exponent and return
	return x.SetMantExp(x, exp/2)

}
Ejemplo n.º 7
0
func (p *exporter) float(x constant.Value) {
	if x.Kind() != constant.Float {
		log.Fatalf("gcimporter: unexpected constant %v, want float", x)
	}
	// extract sign (there is no -0)
	sign := constant.Sign(x)
	if sign == 0 {
		// x == 0
		p.int(0)
		return
	}
	// x != 0

	var f big.Float
	if v, exact := constant.Float64Val(x); exact {
		// float64
		f.SetFloat64(v)
	} else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {
		// TODO(gri): add big.Rat accessor to constant.Value.
		r := valueToRat(num)
		f.SetRat(r.Quo(r, valueToRat(denom)))
	} else {
		// Value too large to represent as a fraction => inaccessible.
		// TODO(gri): add big.Float accessor to constant.Value.
		f.SetFloat64(math.MaxFloat64) // FIXME
	}

	// extract exponent such that 0.5 <= m < 1.0
	var m big.Float
	exp := f.MantExp(&m)

	// extract mantissa as *big.Int
	// - set exponent large enough so mant satisfies mant.IsInt()
	// - get *big.Int from mant
	m.SetMantExp(&m, int(m.MinPrec()))
	mant, acc := m.Int(nil)
	if acc != big.Exact {
		log.Fatalf("gcimporter: internal error")
	}

	p.int(sign)
	p.int(exp)
	p.string(string(mant.Bytes()))
}
Ejemplo n.º 8
0
func (bed BinaryIntEncoderDecoder) Encode(w io.Writer, n *big.Float) error {
	if n.IsInt() {
		x, _ := n.Int64()
		// TODO - if accuracy is not Exact, then use the other path
		if err := binary.Write(w, binary.BigEndian, int8(0)); err != nil {
			return err
		}
		return binary.Write(w, binary.BigEndian, x)
	} else {
		if err := binary.Write(w, binary.BigEndian, int8(1)); err != nil {
			return err
		}

		exponent := n.MantExp(bed.tmp)
		f, _ := bed.tmp.Float64()
		if err := binary.Write(w, binary.BigEndian, f); err != nil {
			return err
		}
		return binary.Write(w, binary.BigEndian, int32(exponent))
	}
}
Ejemplo n.º 9
0
// floatSqrt computes the square root of x using Newton's method.
// TODO: Use a better algorithm such as the one from math/sqrt.go.
func floatSqrt(x *big.Float) *big.Float {
	switch x.Sign() {
	case -1:
		Errorf("square root of negative number")
	case 0:
		return newF()
	}

	// Each iteration computes
	// 	z = z - (z²-x)/2z
	// delta holds the difference between the result
	// this iteration and the previous. The loop stops
	// when it hits zero.

	// z holds the result so far. A good starting point is to halve the exponent.
	// Experiments show we converge in only a handful of iterations.
	z := newF()
	exp := x.MantExp(z)
	z.SetMantExp(z, exp/2)

	// Intermediates, allocated once.
	zSquared := newF()
	num := newF()
	den := newF()

	loop := newLoop("sqrt", x, 1)
	for {
		zSquared.Mul(z, z)
		num.Sub(zSquared, x)
		den.Mul(floatTwo, z)
		num.Quo(num, den)
		z.Sub(z, num)
		if loop.terminate(z) {
			break
		}
	}
	return z
}
Ejemplo n.º 10
0
Archivo: pow.go Proyecto: ALTree/floats
// fast path for z**w when w is an integer
func powInt(z *big.Float, w int) *big.Float {

	// get mantissa and exponent of z
	mant := new(big.Float)
	exp := z.MantExp(mant)

	// result's exponent
	exp = exp * w

	// result's mantissa
	x := big.NewFloat(1).SetPrec(z.Prec())

	// Classic right-to-left binary exponentiation
	for w > 0 {
		if w%2 == 1 {
			x.Mul(x, mant)
		}
		w >>= 1
		mant.Mul(mant, mant)
	}

	return new(big.Float).SetMantExp(x, exp)
}
Ejemplo n.º 11
0
func (bed BinaryVarintEncoderDecoder) Encode(w io.Writer, n *big.Float) error {
	if n.IsInt() {
		x, _ := n.Int64()
		// TODO - if accuracy is not Exact, then use the other path
		buf := make([]byte, binary.MaxVarintLen64)
		nBytes := binary.PutVarint(buf, x)
		if _, err := w.Write([]byte{byte(0)}); err != nil {
			return err
		}
		_, err := w.Write(buf[0:nBytes])
		return err
	} else {
		if err := binary.Write(w, binary.BigEndian, int8(1)); err != nil {
			return err
		}

		exponent := n.MantExp(bed.tmp)
		f, _ := bed.tmp.Float64()
		if err := binary.Write(w, binary.BigEndian, f); err != nil {
			return err
		}
		return binary.Write(w, binary.BigEndian, int32(exponent))
	}
}