Esempio n. 1
0
func renderFloat(img *image.RGBA) {
	var yminF, ymaxMinF, heightF big.Float
	yminF.SetInt64(ymin)
	ymaxMinF.SetInt64(ymax - ymin)
	heightF.SetInt64(height)

	var xminF, xmaxMinF, widthF big.Float
	xminF.SetInt64(xmin)
	xmaxMinF.SetInt64(xmax - xmin)
	widthF.SetInt64(width)

	var y, x big.Float
	for py := int64(0); py < height; py++ {
		// y := float64(py)/height*(ymax-ymin) + ymin
		y.SetInt64(py)
		y.Quo(&y, &heightF)
		y.Mul(&y, &ymaxMinF)
		y.Add(&y, &yminF)

		for px := int64(0); px < width; px++ {
			// x := float64(px)/width*(xmax-xmin) + xmin
			x.SetInt64(px)
			x.Quo(&x, &widthF)
			x.Mul(&x, &xmaxMinF)
			x.Add(&x, &xminF)

			c := mandelbrotFloat(&x, &y)
			if c == nil {
				c = color.Black
			}
			img.Set(int(px), int(py), c)
		}
	}
}
Esempio n. 2
0
// 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
}
Esempio n. 3
0
File: pslq.go Progetto: 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)
	}
}
Esempio n. 4
0
// Divide
func (a Scalar) Div_S(b S) S {
	var x, y big.Float
	x = big.Float(a)
	y = big.Float(b.(Scalar))
	z := x.Quo(&x, &y)
	return (Scalar)(*z)
}
func splitRangeString(start, end string, splits int) []string {
	results := []string{start}
	if start == end {
		return results
	}
	if end < start {
		tmp := start
		start = end
		end = tmp
	}

	// find longest common prefix between strings
	minLen := len(start)
	if len(end) < minLen {
		minLen = len(end)
	}
	prefix := ""
	for i := 0; i < minLen; i++ {
		if start[i] == end[i] {
			prefix = start[0 : i+1]
		} else {
			break
		}
	}

	// remove prefix from strings to split
	start = start[len(prefix):]
	end = end[len(prefix):]

	ordStart := stringToOrd(start)
	ordEnd := stringToOrd(end)

	tmp := new(big.Int)
	tmp.Sub(ordEnd, ordStart)

	stride := new(big.Float)
	stride.SetInt(tmp)
	stride.Quo(stride, big.NewFloat(float64(splits)))

	for i := 1; i <= splits; i++ {
		tmp := new(big.Float)
		tmp.Mul(stride, big.NewFloat(float64(i)))
		tmp.Add(tmp, new(big.Float).SetInt(ordStart))

		result, _ := tmp.Int(new(big.Int))

		value := prefix + ordToString(result, 0)

		if value != results[len(results)-1] {
			results = append(results, value)
		}
	}

	return results
}
Esempio n. 6
0
File: log.go Progetto: ghost-dog/ivy
// floatLog computes natural log(x) using the Maclaurin series for log(1-x).
func floatLog(c Context, 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
		x.Quo(floatOne, x)
	}

	// 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 := newFloat(c)
	exp2 := x.MantExp(mantissa)
	exp := newFloat(c).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 := newFloat(c).SetInt64(1)
	y.Sub(y, mantissa)

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

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

	// 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.

	for loop := newLoop(c.Config(), "log", x, 40); ; {
		term.Quo(yN, n.SetUint64(loop.i+1))
		z.Sub(z, term)
		if loop.done(z) {
			break
		}
		// Advance y**index (multiply by y).
		yN.Mul(yN, y)
	}

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

	return z
}
Esempio n. 7
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
}
Esempio n. 8
0
// 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())
}
Esempio n. 9
0
// hypot for big.Float
func hypot(p, q *big.Float) *big.Float {
	// special cases
	switch {
	case p.IsInf() || q.IsInf():
		return big.NewFloat(math.Inf(1))
	}
	p = p.Abs(p)
	q = q.Abs(q)
	if p.Cmp(p) < 0 {
		p, q = q, p
	}
	if p.Cmp(big.NewFloat(0)) == 0 {
		return big.NewFloat(0)
	}
	q = q.Quo(q, p)
	return sqrt(q.Mul(q, q).Add(q, big.NewFloat(1))).Mul(q, p)
}
Esempio n. 10
0
func sqrtFloat(x *big.Float) *big.Float {
	t1 := new(big.Float).SetPrec(prec)
	t2 := new(big.Float).SetPrec(prec)
	t1.Copy(x)

	// Iterate.
	// x{n} = (x{n-1}+x{0}/x{n-1}) / 2
	for i := 0; i <= steps; i++ {
		if t1.Cmp(zero) == 0 || t1.IsInf() {
			return t1
		}
		t2.Quo(x, t1)
		t2.Add(t2, t1)
		t1.Mul(half, t2)
	}

	return t1
}
Esempio n. 11
0
// 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
}
Esempio n. 12
0
// return: x^y
func Pow(x *big.Float, n int64) *big.Float {
	res := new(big.Float).Copy(x)
	if n < 0 {
		res = res.Quo(big.NewFloat(1), res)
		n = -n
	} else if n == 0 {
		return big.NewFloat(1)
	}
	y := big.NewFloat(1)
	for i := n; i > 1; {
		if i%2 == 0 {
			i /= 2
		} else {
			y = y.Mul(res, y)
			i = (i - 1) / 2
		}
		res = res.Mul(res, res)
	}
	return res.Mul(res, y)
}
Esempio n. 13
0
File: pow.go Progetto: ALTree/floats
// 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())

}
Esempio n. 14
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)
	}
}
Esempio n. 15
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)
	}
}
Esempio n. 16
0
File: log.go Progetto: ALTree/floats
// 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())
}
Esempio n. 17
0
func (f BigFloat) String() string {
	var mant big.Float
	exp := f.Float.MantExp(&mant)
	positive := 1
	if exp < 0 {
		positive = 0
		exp = -exp
	}
	verb, prec := byte('g'), 12
	format := conf.Format()
	if format != "" {
		v, p, ok := conf.FloatFormat()
		if ok {
			verb, prec = v, p
		}
	}
	// Printing huge floats can be very slow using
	// big.Float's native methods; see issue #11068.
	// For example 1e5000000 takes a minute of CPU time just
	// to print. The code below is instantaneous, by rescaling
	// first. It is however less feature-complete.
	// (Big ints are problematic too, but if you print 1e50000000
	// as an integer you probably won't be surprised it's slow.)

	if fastFloatPrint && exp > 10000 {
		// We always use %g to print the fraction, and it will
		// never have an exponent, but if the format is %E we
		// need to use a capital E.
		eChar := 'e'
		if verb == 'E' || verb == 'G' {
			eChar = 'E'
		}
		fexp := newF().SetInt64(int64(exp))
		fexp.Mul(fexp, floatLog2)
		fexp.Quo(fexp, floatLog10)
		// We now have a floating-point base 10 exponent.
		// Break into the integer part and the fractional part.
		// The integer part is what we will show.
		// The 10**(fractional part) will be multiplied back in.
		iexp, _ := fexp.Int(nil)
		fraction := fexp.Sub(fexp, newF().SetInt(iexp))
		// Now compute 10**(fractional part).
		// Fraction is in base 10. Move it to base e.
		fraction.Mul(fraction, floatLog10)
		scale := exponential(fraction)
		if positive > 0 {
			mant.Mul(&mant, scale)
		} else {
			mant.Quo(&mant, scale)
		}
		ten := newF().SetInt64(10)
		i64exp := iexp.Int64()
		// For numbers not too far from one, print without the E notation.
		// Shouldn't happen (exp must be large to get here) but just
		// in case, we keep this around.
		if -4 <= i64exp && i64exp <= 11 {
			if i64exp > 0 {
				for i := 0; i < int(i64exp); i++ {
					mant.Mul(&mant, ten)
				}
			} else {
				for i := 0; i < int(-i64exp); i++ {
					mant.Quo(&mant, ten)
				}
			}
			return fmt.Sprintf("%g\n", &mant)
		} else {
			sign := ""
			if mant.Sign() < 0 {
				sign = "-"
				mant.Neg(&mant)
			}
			// If it has a leading zero, rescale.
			digits := mant.Text('g', prec)
			for digits[0] == '0' {
				mant.Mul(&mant, ten)
				if positive > 0 {
					i64exp--
				} else {
					i64exp++
				}
				digits = mant.Text('g', prec)
			}
			return fmt.Sprintf("%s%s%c%c%d", sign, digits, eChar, "-+"[positive], i64exp)
		}
	}
	return f.Float.Text(verb, prec)
}
Esempio n. 18
0
func init() {
	unaryRoll = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				i := int64(v.(Int))
				if i <= 0 {
					Errorf("illegal roll value %v", v)
				}
				return Int(conf.Origin()) + Int(conf.Random().Int63n(i))
			},
			bigIntType: func(v Value) Value {
				if v.(BigInt).Sign() <= 0 {
					Errorf("illegal roll value %v", v)
				}
				return unaryBigIntOp(bigIntRand, v)
			},
		},
	}

	unaryPlus = &unaryOp{
		fn: [numType]unaryFn{
			intType:      self,
			bigIntType:   self,
			bigRatType:   self,
			bigFloatType: self,
			vectorType:   self,
			matrixType:   self,
		},
	}

	unaryMinus = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				return -v.(Int)
			},
			bigIntType: func(v Value) Value {
				return unaryBigIntOp((*big.Int).Neg, v)
			},
			bigRatType: func(v Value) Value {
				return unaryBigRatOp((*big.Rat).Neg, v)
			},
			bigFloatType: func(v Value) Value {
				return unaryBigFloatOp((*big.Float).Neg, v)
			},
		},
	}

	unaryRecip = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				i := int64(v.(Int))
				if i == 0 {
					Errorf("division by zero")
				}
				return BigRat{
					Rat: big.NewRat(0, 1).SetFrac64(1, i),
				}.shrink()
			},
			bigIntType: func(v Value) Value {
				// Zero division cannot happen for unary.
				return BigRat{
					Rat: big.NewRat(0, 1).SetFrac(bigOne.Int, v.(BigInt).Int),
				}.shrink()
			},
			bigRatType: func(v Value) Value {
				// Zero division cannot happen for unary.
				r := v.(BigRat)
				return BigRat{
					Rat: big.NewRat(0, 1).SetFrac(r.Denom(), r.Num()),
				}.shrink()
			},
			bigFloatType: func(v Value) Value {
				// Zero division cannot happen for unary.
				f := v.(BigFloat)
				one := new(big.Float).SetPrec(conf.FloatPrec()).SetInt64(1)
				return BigFloat{
					Float: one.Quo(one, f.Float),
				}.shrink()
			},
		},
	}

	unarySignum = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				i := int64(v.(Int))
				if i > 0 {
					return one
				}
				if i < 0 {
					return minusOne
				}
				return zero
			},
			bigIntType: func(v Value) Value {
				return Int(v.(BigInt).Sign())
			},
			bigRatType: func(v Value) Value {
				return Int(v.(BigRat).Sign())
			},
			bigFloatType: func(v Value) Value {
				return Int(v.(BigFloat).Sign())
			},
		},
	}

	unaryBitwiseNot = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				return ^v.(Int)
			},
			bigIntType: func(v Value) Value {
				// Lots of ways to do this, here's one.
				return BigInt{Int: bigInt64(0).Xor(v.(BigInt).Int, bigMinusOne.Int)}
			},
		},
	}

	unaryLogicalNot = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				if v.(Int) == 0 {
					return one
				}
				return zero
			},
			bigIntType: func(v Value) Value {
				if v.(BigInt).Sign() == 0 {
					return one
				}
				return zero
			},
			bigRatType: func(v Value) Value {
				if v.(BigRat).Sign() == 0 {
					return one
				}
				return zero
			},
			bigFloatType: func(v Value) Value {
				if v.(BigFloat).Sign() == 0 {
					return one
				}
				return zero
			},
		},
	}

	unaryAbs = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				i := v.(Int)
				if i < 0 {
					i = -i
				}
				return i
			},
			bigIntType: func(v Value) Value {
				return unaryBigIntOp((*big.Int).Abs, v)
			},
			bigRatType: func(v Value) Value {
				return unaryBigRatOp((*big.Rat).Abs, v)
			},
			bigFloatType: func(v Value) Value {
				return unaryBigFloatOp((*big.Float).Abs, v)
			},
		},
	}

	floor = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:    func(v Value) Value { return v },
			bigIntType: func(v Value) Value { return v },
			bigRatType: func(v Value) Value {
				i := v.(BigRat)
				if i.IsInt() {
					// It can't be an integer, which means we must move up or down.
					panic("min: is int")
				}
				positive := i.Sign() >= 0
				if !positive {
					j := bigRatInt64(0)
					j.Abs(i.Rat)
					i = j
				}
				z := bigInt64(0)
				z.Quo(i.Num(), i.Denom())
				if !positive {
					z.Add(z.Int, bigOne.Int)
					z.Neg(z.Int)
				}
				return z
			},
			bigFloatType: func(v Value) Value {
				f := v.(BigFloat)
				i, acc := f.Int(nil)
				switch acc {
				case big.Exact, big.Below:
					// Done.
				case big.Above:
					i.Sub(i, bigOne.Int)
				}
				return BigInt{i}.shrink()
			},
		},
	}

	ceil = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:    func(v Value) Value { return v },
			bigIntType: func(v Value) Value { return v },
			bigRatType: func(v Value) Value {
				i := v.(BigRat)
				if i.IsInt() {
					// It can't be an integer, which means we must move up or down.
					panic("max: is int")
				}
				positive := i.Sign() >= 0
				if !positive {
					j := bigRatInt64(0)
					j.Abs(i.Rat)
					i = j
				}
				z := bigInt64(0)
				z.Quo(i.Num(), i.Denom())
				if positive {
					z.Add(z.Int, bigOne.Int)
				} else {
					z.Neg(z.Int)
				}
				return z
			},
			bigFloatType: func(v Value) Value {
				f := v.(BigFloat)
				i, acc := f.Int(nil)
				switch acc {
				case big.Exact, big.Above:
					// Done
				case big.Below:
					i.Add(i, bigOne.Int)
				}
				return BigInt{i}.shrink()
			},
		},
	}

	unaryIota = &unaryOp{
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				i := v.(Int)
				if i < 0 || maxInt < i {
					Errorf("bad iota %d", i)
				}
				if i == 0 {
					return Vector{}
				}
				n := make([]Value, i)
				for k := range n {
					n[k] = Int(k + conf.Origin())
				}
				return NewVector(n)
			},
		},
	}

	unaryRho = &unaryOp{
		fn: [numType]unaryFn{
			intType: func(v Value) Value {
				return Vector{}
			},
			charType: func(v Value) Value {
				return Vector{}
			},
			bigIntType: func(v Value) Value {
				return Vector{}
			},
			bigRatType: func(v Value) Value {
				return Vector{}
			},
			bigFloatType: func(v Value) Value {
				return Vector{}
			},
			vectorType: func(v Value) Value {
				return Int(len(v.(Vector)))
			},
			matrixType: func(v Value) Value {
				return v.(Matrix).shape
			},
		},
	}

	unaryRavel = &unaryOp{
		fn: [numType]unaryFn{
			intType:      vectorSelf,
			charType:     vectorSelf,
			bigIntType:   vectorSelf,
			bigRatType:   vectorSelf,
			bigFloatType: vectorSelf,
			vectorType:   self,
			matrixType: func(v Value) Value {
				return v.(Matrix).data
			},
		},
	}

	gradeUp = &unaryOp{
		fn: [numType]unaryFn{
			intType:      self,
			charType:     self,
			bigIntType:   self,
			bigRatType:   self,
			bigFloatType: self,
			vectorType: func(v Value) Value {
				return v.(Vector).grade()
			},
		},
	}

	gradeDown = &unaryOp{
		fn: [numType]unaryFn{
			intType:      self,
			charType:     self,
			bigIntType:   self,
			bigRatType:   self,
			bigFloatType: self,
			vectorType: func(v Value) Value {
				x := v.(Vector).grade()
				for i, j := 0, len(x)-1; i < j; i, j = i+1, j-1 {
					x[i], x[j] = x[j], x[i]
				}
				return x
			},
		},
	}

	reverse = &unaryOp{
		fn: [numType]unaryFn{
			intType:      self,
			charType:     self,
			bigIntType:   self,
			bigRatType:   self,
			bigFloatType: self,
			vectorType: func(v Value) Value {
				x := v.(Vector)
				for i, j := 0, len(x)-1; i < j; i, j = i+1, j-1 {
					x[i], x[j] = x[j], x[i]
				}
				return x
			},
			matrixType: func(v Value) Value {
				m := v.(Matrix)
				if len(m.shape) == 0 {
					return m
				}
				if len(m.shape) == 1 {
					Errorf("rev: matrix is vector")
				}
				size := m.size()
				ncols := int(m.shape[len(m.shape)-1].(Int))
				x := m.data
				for index := 0; index <= size-ncols; index += ncols {
					for i, j := 0, ncols-1; i < j; i, j = i+1, j-1 {
						x[index+i], x[index+j] = x[index+j], x[index+i]
					}
				}
				return m
			},
		},
	}

	flip = &unaryOp{
		fn: [numType]unaryFn{
			intType:      self,
			charType:     self,
			bigIntType:   self,
			bigRatType:   self,
			bigFloatType: self,
			vectorType: func(v Value) Value {
				return Unary("rev", v)
			},
			matrixType: func(v Value) Value {
				m := v.(Matrix)
				if len(m.shape) == 0 {
					return m
				}
				if len(m.shape) == 1 {
					Errorf("flip: matrix is vector")
				}
				elemSize := m.elemSize()
				size := m.size()
				x := m.data
				lo := 0
				hi := size - elemSize
				for lo < hi {
					for i := 0; i < elemSize; i++ {
						x[lo+i], x[hi+i] = x[hi+i], x[lo+i]
					}
					lo += elemSize
					hi -= elemSize
				}
				return m
			},
		},
	}

	unaryCos = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return cos(v) },
			bigIntType:   func(v Value) Value { return cos(v) },
			bigRatType:   func(v Value) Value { return cos(v) },
			bigFloatType: func(v Value) Value { return cos(v) },
		},
	}

	unaryLog = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return logn(v) },
			bigIntType:   func(v Value) Value { return logn(v) },
			bigRatType:   func(v Value) Value { return logn(v) },
			bigFloatType: func(v Value) Value { return logn(v) },
		},
	}

	unarySin = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return sin(v) },
			bigIntType:   func(v Value) Value { return sin(v) },
			bigRatType:   func(v Value) Value { return sin(v) },
			bigFloatType: func(v Value) Value { return sin(v) },
		},
	}

	unaryTan = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return tan(v) },
			bigIntType:   func(v Value) Value { return tan(v) },
			bigRatType:   func(v Value) Value { return tan(v) },
			bigFloatType: func(v Value) Value { return tan(v) },
		},
	}

	unaryAsin = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return asin(v) },
			bigIntType:   func(v Value) Value { return asin(v) },
			bigRatType:   func(v Value) Value { return asin(v) },
			bigFloatType: func(v Value) Value { return asin(v) },
		},
	}

	unaryAcos = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return acos(v) },
			bigIntType:   func(v Value) Value { return acos(v) },
			bigRatType:   func(v Value) Value { return acos(v) },
			bigFloatType: func(v Value) Value { return acos(v) },
		},
	}

	unaryAtan = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return atan(v) },
			bigIntType:   func(v Value) Value { return atan(v) },
			bigRatType:   func(v Value) Value { return atan(v) },
			bigFloatType: func(v Value) Value { return atan(v) },
		},
	}

	unaryExp = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return exp(v) },
			bigIntType:   func(v Value) Value { return exp(v) },
			bigRatType:   func(v Value) Value { return exp(v) },
			bigFloatType: func(v Value) Value { return exp(v) },
		},
	}

	unarySqrt = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return sqrt(v) },
			bigIntType:   func(v Value) Value { return sqrt(v) },
			bigRatType:   func(v Value) Value { return sqrt(v) },
			bigFloatType: func(v Value) Value { return sqrt(v) },
		},
	}

	unaryChar = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType: func(v Value) Value { return Char(v.(Int)).validate() },
		},
	}

	unaryCode = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			charType: func(v Value) Value { return Int(v.(Char)) },
		},
	}

	unaryText = &unaryOp{
		fn: [numType]unaryFn{
			intType:      func(v Value) Value { return text(v) },
			bigIntType:   func(v Value) Value { return text(v) },
			bigRatType:   func(v Value) Value { return text(v) },
			bigFloatType: func(v Value) Value { return text(v) },
			vectorType:   func(v Value) Value { return text(v) },
			matrixType:   func(v Value) Value { return text(v) },
		},
	}

	unaryIvy = &unaryOp{
		fn: [numType]unaryFn{
			vectorType: func(v Value) Value {
				text := v.(Vector)
				if !text.allChars() {
					Errorf("ivy: value is not a vector of char")
				}
				return IvyEval(context, text.makeString(false))
			},
		},
	}

	unaryFloat = &unaryOp{
		elementwise: true,
		fn: [numType]unaryFn{
			intType:      floatSelf,
			bigIntType:   floatSelf,
			bigRatType:   floatSelf,
			bigFloatType: floatSelf,
		},
	}

	unaryOps = map[string]*unaryOp{
		"**":    unaryExp,
		"+":     unaryPlus,
		",":     unaryRavel,
		"-":     unaryMinus,
		"/":     unaryRecip,
		"?":     unaryRoll,
		"^":     unaryBitwiseNot,
		"abs":   unaryAbs,
		"acos":  unaryAcos,
		"asin":  unaryAsin,
		"atan":  unaryAtan,
		"ceil":  ceil,
		"char":  unaryChar,
		"code":  unaryCode,
		"cos":   unaryCos,
		"down":  gradeDown,
		"flip":  flip,
		"float": unaryFloat,
		"floor": floor,
		"iota":  unaryIota,
		"ivy":   unaryIvy,
		"log":   unaryLog,
		"rev":   reverse,
		"rho":   unaryRho,
		"sin":   unarySin,
		"sgn":   unarySignum,
		"sqrt":  unarySqrt,
		"tan":   unaryTan,
		"text":  unaryText,
		"up":    gradeUp,
		"~":     unaryLogicalNot,
	}
}
Esempio n. 19
0
File: pslq.go Progetto: ncw/pslq
// Given a vector of real numbers x = [x_0, x_1, ..., x_n], this
// uses the PSLQ algorithm to find a list of integers
// [c_0, c_1, ..., c_n] such that
//
//     |c_1 * x_1 + c_2 * x_2 + ... + c_n * x_n| < tolerance
//
// and such that max |c_k| < maxcoeff. If no such vector exists, Pslq
// returns one of the errors in this package depending on whether it
// has run out of iterations, precision or explored up to the
// maxcoeff. The tolerance defaults to 3/4 of the precision.
//
// This is a fairly direct translation of the pseudocode given by
// David Bailey, "The PSLQ Integer Relation Algorithm":
// http://www.cecm.sfu.ca/organics/papers/bailey/paper/html/node3.html
//
// If a result is returned, the first non-zero element will be positive
func (e *Pslq) Run(x []big.Float) ([]big.Int, error) {
	n := len(x)
	if n <= 1 {
		return nil, ErrorBadArguments
	}

	// At too low precision, the algorithm becomes meaningless
	if e.prec < 64 {
		return nil, ErrorPrecisionTooLow
	}

	if e.verbose && int(e.prec)/max(2, int(n)) < 5 {
		log.Printf("Warning: precision for PSLQ may be too low")
	}

	if e.verbose {
		log.Printf("PSLQ using prec %d and tol %g", e.prec, e.tol)
	}

	if e.tol.Sign() == 0 {
		return nil, ErrorToleranceRoundsToZero
	}

	// Temporary variables
	tmp0 := new(big.Float).SetPrec(e.prec)
	tmp1 := new(big.Float).SetPrec(e.prec)
	bigTmp := new(big.Int)

	// Convert to use 1-based indexing to allow us to be
	// consistent with Bailey's indexing.
	xNew := make([]big.Float, len(x)+1)
	minx := new(big.Float).SetPrec(e.prec)
	minxFirst := true
	for i, xk := range x {
		p := &xNew[i+1]
		p.Set(&xk)
		tmp0.Abs(p)
		if minxFirst || tmp0.Cmp(minx) < 0 {
			minxFirst = false
			minx.Set(tmp0)
		}
	}
	x = xNew
	if debug {
		printVector("x", x)
	}

	// Sanity check on magnitudes
	if minx.Sign() == 0 {
		return nil, ErrorZeroArguments
	}
	tmp1.SetInt64(128)
	tmp0.Quo(&e.tol, tmp1)
	if minx.Cmp(tmp0) < 0 { //  minx < tol/128
		return nil, ErrorArgumentTooSmall
	}

	tmp0.SetInt64(4)
	tmp1.SetInt64(3)
	tmp0.Quo(tmp0, tmp1)
	var γ big.Float
	e.Sqrt(tmp0, &γ) // sqrt(4<<prec)/3)
	if debug {
		fmt.Printf("γ = %f\n", &γ)
	}
	A := newBigIntMatrix(n+1, n+1)
	B := newBigIntMatrix(n+1, n+1)
	H := newMatrix(n+1, n+1)
	// Initialization Step 1
	//
	// Set the n×n matrices A and B to the identity.
	for i := 1; i <= n; i++ {
		for j := 1; j <= n; j++ {
			if i == j {
				A[i][j].SetInt64(1)
				B[i][j].SetInt64(1)
			} else {
				A[i][j].SetInt64(0)
				B[i][j].SetInt64(0)
			}
			H[i][j].SetInt64(0)
		}
	}
	if debug {
		printBigIntMatrix("A", A)
		printBigIntMatrix("B", B)
		printMatrix("H", H)
	}
	// Initialization Step 2
	//
	// For k := 1 to n
	//     compute s_k := sqrt( sum_j=k^n x_j^2 )
	// endfor.
	// Set t = 1/s1.
	// For k := 1 to n:
	//     y_k := t * x_k
	//     s_k := t * s_k
	// endfor.
	s := make([]big.Float, n+1)
	for i := 1; i <= n; i++ {
		s[i].SetInt64(0)
	}
	for k := 1; k <= n; k++ {
		var t big.Float
		t.SetInt64(0)
		for j := k; j <= n; j++ {
			tmp0.Mul(&x[j], &x[j])
			t.Add(&t, tmp0)
		}
		e.Sqrt(&t, &s[k])
	}
	if debug {
		fmt.Println("Init Step 2")
		printVector("s", s)
	}
	var t big.Float
	t.Set(&s[1])
	y := make([]big.Float, len(x))
	copy(y, x)
	for k := 1; k <= n; k++ {
		// y[k] = (x[k] << prec) / t
		y[k].Quo(&x[k], &t)
		// s[k] = (s[k] << prec) / t
		s[k].Quo(&s[k], &t)
	}
	if debug {
		printVector("y", y)
		printVector("s", s)
	}
	// Init Step 3
	//
	// Compute the n×(n−1) matrix H as follows:
	// For i := 1 to n:
	//     for j := i + 1 to n − 1:
	//         set Hij := 0
	//     endfor
	//     if i ≤ n − 1 then set Hii := s_(i+1)/s_i
	//     for j := 1 to i−1:
	//         set Hij := −y_i * y_j / (s_j * s_(j+1))
	//     endfor
	// endfor
	for i := 1; i <= n; i++ {
		for j := i + 1; j < n; j++ {
			H[i][j].SetInt64(0)
		}
		if i <= n-1 {
			if s[i].Sign() == 0 {
				// Precision probably exhausted
				return nil, ErrorPrecisionExhausted
			}
			// H[i][i] = (s[i+1] << prec) / s[i]
			H[i][i].Quo(&s[i+1], &s[i])
		}
		for j := 1; j < i; j++ {
			var sjj1 big.Float
			sjj1.Mul(&s[j], &s[j+1])
			if debug {
				fmt.Printf("sjj1 = %f\n", &sjj1)
			}
			if sjj1.Sign() == 0 {
				// Precision probably exhausted
				return nil, ErrorPrecisionExhausted
			}
			// H[i][j] = ((-y[i] * y[j]) << prec) / sjj1
			tmp0.Mul(&y[i], &y[j])
			tmp0.Neg(tmp0)
			H[i][j].Quo(tmp0, &sjj1)
		}
	}
	if debug {
		fmt.Println("Init Step 3")
		printMatrix("H", H)
	}
	// Init Step 4
	//
	// Perform full reduction on H, simultaneously updating y, A and B:
	//
	// For i := 2 to n:
	//     for j := i−1 to 1 step−1:
	//         t := nint(Hij/Hjj)
	//         y_j := y_j + t * y_i
	//         for k := 1 to j:
	//             Hik := Hik − t * Hjk
	//         endfor
	//         for k := 1 to n:
	//             Aik := Aik − t * Ajk
	//             Bkj := Bkj + t * Bki
	//         endfor
	//     endfor
	// endfor
	for i := 2; i <= n; i++ {
		for j := i - 1; j > 0; j-- {
			//t = floor(H[i][j]/H[j,j] + 0.5)
			var t big.Int
			var tFloat big.Float
			if H[j][j].Sign() == 0 {
				// Precision probably exhausted
				return nil, ErrorPrecisionExhausted
			}
			tmp0.Quo(&H[i][j], &H[j][j])
			e.NearestInt(tmp0, &t)
			tFloat.SetInt(&t).SetPrec(e.prec)
			if debug {
				fmt.Printf("H[i][j]=%f\n", &H[i][j])
				fmt.Printf("H[j][j]=%f\n", &H[j][j])
				fmt.Printf("tmp=%f\n", tmp0)
				fmt.Printf("t=%d\n", &t)
			}
			// y[j] = y[j] + (t * y[i] >> prec)
			tmp0.Mul(&y[i], &tFloat)
			y[j].Add(&y[j], tmp0)
			for k := 1; k <= j; k++ {
				// H[i][k] = H[i][k] - (t * H[j][k] >> prec)
				tmp0.Mul(&H[j][k], &tFloat)
				H[i][k].Sub(&H[i][k], tmp0)
			}
			for k := 1; k <= n; k++ {
				bigTmp.Mul(&t, &A[j][k])
				A[i][k].Sub(&A[i][k], bigTmp)
				bigTmp.Mul(&t, &B[k][i])
				B[k][j].Add(&B[k][j], bigTmp)
			}
		}
	}
	if debug {
		fmt.Println("Init Step 4")
		printBigIntMatrix("A", A)
		printBigIntMatrix("B", B)
		printMatrix("H", H)
	}
	// Main algorithm
	var REP int
	var norm big.Int
	vec := make([]big.Int, n)
	for REP = 0; REP < e.maxsteps; REP++ {
		// Step 1
		//
		// Select m such that γ^i * |Hii| is maximal when i = m.
		m := -1
		var szmax big.Float
		szmax.SetInt64(-1)
		var γPower big.Float
		γPower.Set(&γ)
		for i := 1; i < n; i++ {
			var absH big.Float
			absH.Abs(&H[i][i])
			var sz big.Float
			sz.Mul(&γPower, &absH)
			// sz := (g**i * abs(h)) >> (prec * (i - 1))
			if sz.Cmp(&szmax) > 0 {
				m = i
				szmax.Set(&sz)
			}
			γPower.Mul(&γPower, &γ)
		}
		if debug {
			fmt.Println("Step 1")
			fmt.Printf("szmax=%f\n", &szmax)
			fmt.Printf("m=%d\n", m)
		}
		// Step 2
		//
		// Exchange entries m and m+1 of y, corresponding rows
		// of A and H, and corresponding columns of B.
		y[m], y[m+1] = y[m+1], y[m]
		for i := 1; i < n+1; i++ {
			H[m][i], H[m+1][i] = H[m+1][i], H[m][i]
		}
		for i := 1; i < n+1; i++ {
			A[m][i], A[m+1][i] = A[m+1][i], A[m][i]
		}
		for i := 1; i < n+1; i++ {
			B[i][m], B[i][m+1] = B[i][m+1], B[i][m]
		}
		if debug {
			fmt.Println("Step 2")
			printVector("y", y)
			printBigIntMatrix("A", A)
			printBigIntMatrix("B", B)
			printMatrix("H", H)
		}
		// Step 3
		//
		// If m ≤ n−2 then update H as follows:
		//
		// t0 := sqrt( Hmm^2 + H(m,m+1)^2 )
		// t1 := Hmm/t0
		// t2 := H(m,m+1)/t0.
		// for i := m to n:
		//     t3 := Him
		//     t4 := Hi,m+1
		//     Him := t1t3 +t2t4
		//     Hi,m+1 := −t2t3 +t1t4
		// endfor.
		if m <= n-2 {
			tmp0.Mul(&H[m][m], &H[m][m])
			tmp1.Mul(&H[m][m+1], &H[m][m+1])
			tmp0.Add(tmp0, tmp1)
			var t0 big.Float
			e.Sqrt(tmp0, &t0)
			// Precision probably exhausted
			if t0.Sign() == 0 {
				return nil, ErrorPrecisionExhausted
			}
			var t1, t2 big.Float
			t1.Quo(&H[m][m], &t0)
			t2.Quo(&H[m][m+1], &t0)
			for i := m; i <= n; i++ {
				var t3, t4 big.Float
				t3.Set(&H[i][m])
				t4.Set(&H[i][m+1])
				// H[i][m] = (t1*t3 + t2*t4) >> prec
				tmp0.Mul(&t1, &t3)
				tmp1.Mul(&t2, &t4)
				H[i][m].Add(tmp0, tmp1)
				// H[i][m+1] = (-t2*t3 + t1*t4) >> prec
				tmp0.Mul(&t2, &t3)
				tmp1.Mul(&t1, &t4)
				H[i][m+1].Sub(tmp1, tmp0)
			}
		}
		if debug {
			fmt.Println("Step 3")
			printMatrix("H", H)
		}
		// Step 4
		// Perform block reduction on H, simultaneously updating y, A and B:
		//
		// For i := m+1 to n:
		//     for j := min(i−1, m+1) to 1 step −1:
		//         t := nint(Hij/Hjj)
		//         yj := yj + t * yi
		//         for k := 1 to j:
		//             Hik := Hik − tHjk
		//         endfor
		//         for k := 1 to n:
		//             Aik := Aik −tAjk
		//             Bkj := Bkj +tBki
		//         endfor
		//     endfor
		// endfor.
		for i := m + 1; i <= n; i++ {
			var t big.Int
			var tFloat big.Float
			for j := min(i-1, m+1); j > 0; j-- {
				if H[j][j].Sign() == 0 {
					// Precision probably exhausted
					return nil, ErrorPrecisionExhausted
				}
				tmp0.Quo(&H[i][j], &H[j][j])
				e.NearestInt(tmp0, &t)
				tFloat.SetInt(&t).SetPrec(e.prec)
				// y[j] = y[j] + ((t * y[i]) >> prec)
				tmp0.Mul(&y[i], &tFloat)
				y[j].Add(&y[j], tmp0)
				for k := 1; k <= j; k++ {
					// H[i][k] = H[i][k] - (t * H[j][k] >> prec)
					tmp0.Mul(&H[j][k], &tFloat)
					H[i][k].Sub(&H[i][k], tmp0)
				}
				for k := 1; k <= n; k++ {
					bigTmp.Mul(&t, &A[j][k])
					A[i][k].Sub(&A[i][k], bigTmp)
					bigTmp.Mul(&t, &B[k][i])
					B[k][j].Add(&B[k][j], bigTmp)
				}
			}
		}
		if debug {
			fmt.Println("Step 4")
			printBigIntMatrix("A", A)
			printBigIntMatrix("B", B)
			printMatrix("H", H)
		}

		// Step 6
		//
		// Termination test: If the largest entry of A exceeds
		// the level of numeric precision used, then precision
		// is exhausted. If the smallest entry of the y vector
		// is less than the detection threshold, a relation
		// has been detected and is given in the corresponding
		// column of B.
		//
		// Until a relation is found, the error typically decreases
		// slowly (e.g. a factor 1-10) with each step TODO: we could
		// compare err from two successive iterations. If there is a
		// large drop (several orders of magnitude), that indicates a
		// "high quality" relation was detected. Reporting this to
		// the user somehow might be useful.

		maxAPrecision := 0
		for i := 1; i <= n; i++ {
			for j := 1; j <= n; j++ {
				precision := A[i][j].BitLen()
				if precision > maxAPrecision {
					maxAPrecision = precision
				}
			}
		}
		if debug {
			log.Printf("Max A precision = %d, precision = %d, tolerance %d, ratio = %.3f\n", maxAPrecision, e.prec, e.target, float64(maxAPrecision)/float64(e.target))
		}
		if float64(maxAPrecision)/float64(e.target) > 0.85 {
			if e.verbose {
				log.Printf("CANCELLING after step %d/%d.", REP, e.maxsteps)
			}
			return nil, ErrorPrecisionExhausted
		}

		var best_err big.Float
		best_err.Set(&e.maxcoeff_fp)
		for i := 1; i <= n; i++ {
			var err big.Float
			err.Abs(&y[i])
			// Maybe we are done?
			if err.Cmp(&e.tol) < 0 {
				// We are done if the coefficients are acceptable
				var maxc big.Int
				for j := 1; j <= n; j++ {
					if debug {
						fmt.Printf("vec[%d]=%d\n", j-1, &B[j][i])
					}
					t := B[j][i]
					if debug {
						fmt.Printf("vec[%d]=%d\n", j-1, t)
					}
					vec[j-1] = t
					if t.Sign() < 0 {
						t.Neg(&t)
					}
					if t.Cmp(&maxc) > 0 {
						maxc.Set(&t)
					}
				}
				if debug {
					fmt.Printf("maxc = %d, maxcoeff = %d\n", maxc, e.maxcoeff)
				}
				if maxc.Cmp(&e.maxcoeff) < 0 {
					if e.verbose {
						log.Printf("FOUND relation at iter %d/%d, error: %g", REP, e.maxsteps, &err)
					}
					// Find sign of first non zero item
					sign := 0
					for i := range vec {
						sign = vec[i].Sign()
						if sign != 0 {
							break
						}
					}
					// Normalise vec making first non-zero argument positive
					if sign < 0 {
						for i := range vec {
							vec[i].Neg(&vec[i])
						}
					}
					return vec, nil
				}
			}
			if err.Cmp(&best_err) < 0 {
				best_err = err
			}
		}
		// Step 5
		//
		// Norm bound: Compute M := 1/maxj |Hj|, where Hj
		// denotes the j-th row of H.
		//
		// Then there can exist no relation vector whose
		// Euclidean norm is less than M.
		//
		// Calculate a lower bound for the norm. We could do this
		// more exactly (using the Euclidean norm) but there is probably
		// no practical benefit.
		var recnorm big.Float
		recnorm.SetInt64(0)
		for i := 1; i <= n; i++ {
			for j := 1; j <= n; j++ {
				tmp0.Abs(&H[i][j])
				if tmp0.Cmp(&recnorm) > 0 {
					recnorm.Set(tmp0)
				}
			}
		}
		norm.Set(&e.maxcoeff)
		if recnorm.Sign() != 0 {
			// norm = ((1 << (2 * prec)) / recnorm) >> prec
			tmp0.Quo(&e.one, &recnorm)
			tmp0.Int(&norm)
		}
		if e.verbose {
			log.Printf("%2d/%2d:  Error: %g   Norm: %d", REP, e.maxsteps, &best_err, &norm)
		}
		if norm.Cmp(&e.maxcoeff) >= 0 {
			if e.verbose {
				log.Printf("CANCELLING after step %d/%d.", REP, e.maxsteps)
				log.Printf("Could not find an integer relation. Norm bound: %d", &norm)
			}
			return nil, ErrorNoRelationFound
		}
	}
	if e.verbose {
		log.Printf("CANCELLING after step %d/%d.", REP, e.maxsteps)
		log.Printf("Could not find an integer relation. Norm bound: %d", &norm)
	}
	return nil, ErrorIterationsExceeded
}