Beispiel #1
0
Datei: rat.go Projekt: ncw/gmp
// SetNum sets the numerator of z returning z
//
// NB this isn't part of math/big which uses Num().Set() for this
// purpose. In gmp Num() returns a copy hence the need for a SetNum()
// method.
func (z *Rat) SetNum(a *Int) *Rat {
	z.doinit()
	a.doinit()
	C.mpq_set_num(&z.i[0], &a.i[0])
	C.mpq_canonicalize(&z.i[0])
	return z
}
Beispiel #2
0
// IsInt returns true if the denominator of x is 1.
func (q *Rat) IsInt() bool {
	q.doinit()
	C.mpq_canonicalize(&q.i[0])
	if q.Denom().Cmp(intOne) == 0 {
		return true
	}
	return false
}
Beispiel #3
0
Datei: rat.go Projekt: ncw/gmp
// SetFrac sets z to a/b and returns z.
func (z *Rat) SetFrac(a, b *Int) *Rat {
	z.doinit()
	a.doinit()
	b.doinit()
	// FIXME copying? or referencing?
	C.mpq_set_num(&z.i[0], &a.i[0])
	C.mpq_set_den(&z.i[0], &b.i[0])
	C.mpq_canonicalize(&z.i[0])
	return z
}
Beispiel #4
0
Datei: rat.go Projekt: ncw/gmp
// SetDenom sets the numerator of z returning z
//
// NB this isn't part of math/big which uses Num().Set() for this
// purpose. In gmp Num() returns a copy hence the need for a SetNum()
// method.
func (z *Rat) SetDenom(a *Int) *Rat {
	z.doinit()
	a.doinit()
	C.mpq_set_den(&z.i[0], &a.i[0])
	// If numerator is zero don't canonicalize
	if C._mpq_num_sgn(&z.i[0]) != 0 {
		C.mpq_canonicalize(&z.i[0])
	}
	return z
}
Beispiel #5
0
// SetFrac64 sets q to x/y and returns q.
func (q *Rat) SetFrac64(x int64, y int64) *Rat {
	q.doinit()

	// y has to be positive for mpq_set_si
	if y < 0 {
		x *= -1
		y *= -1
	}

	C.mpq_set_si(&q.i[0], C.long(x), C.ulong(y))
	C.mpq_canonicalize(&q.i[0])
	return q
}
Beispiel #6
0
// SetStringBase interprets s as a number in the given base
// and sets z to that value.  The base must be in the range [2,36].
// SetString returns an error if s cannot be parsed or the base is invalid.
func (q *Rat) SetStringBase(s string, base int) (*Rat, bool) {
	q.doinit()
	if base < 2 || base > 36 {
		return nil, false
	}
	p := C.CString(s)
	defer C.free(unsafe.Pointer(p))
	if C.mpq_set_str(&q.i[0], p, C.int(base)) < 0 {
		return nil, false
	}
	C.mpq_canonicalize(&q.i[0])
	return q, true
}
Beispiel #7
0
Datei: rat.go Projekt: ncw/gmp
// SetFrac64 sets z to a/b and returns z.
func (z *Rat) SetFrac64(a, b int64) *Rat {
	z.doinit()
	if b == 0 {
		panic("division by zero")
	}
	// Detect overflow if running on 32 bits
	if a == int64(C.long(a)) && b == int64(C.long(b)) {
		if b < 0 {
			a = -a
			b = -b
		}
		C.mpq_set_si(&z.i[0], C.long(a), C.ulong(b))
		C.mpq_canonicalize(&z.i[0])
		if b < 0 {
			// This only happens when b = 1<<63
			z.Neg(z)
		}
	} else {
		// Slow path but will work on 32 bit architectures
		z.SetFrac(NewInt(a), NewInt(b))
	}
	return z
}
Beispiel #8
0
// SetUint sets q to x/y and returns q.
func (q *Rat) SetUint(x, y uint) *Rat {
	q.doinit()
	C.mpq_set_ui(&q.i[0], C.ulong(x), C.ulong(y))
	C.mpq_canonicalize(&q.i[0])
	return q
}
Beispiel #9
0
Datei: rat.go Projekt: ncw/gmp
// SetString sets z to the value of s and returns z and a boolean indicating
// success. s can be given as a fraction "a/b" or as a floating-point number
// optionally followed by an exponent. If the operation failed, the value of
// z is undefined but the returned value is nil.
func (z *Rat) SetString(s string) (*Rat, bool) {
	if len(s) == 0 {
		return nil, false
	}
	z.doinit()
	a := new(Int)
	b := new(Int)

	// check for a quotient
	sep := strings.Index(s, "/")
	if sep >= 0 {
		// FIXME Num and Denom are bust
		// if _, ok := z.Num().SetString(s[0:sep], 10); !ok {
		// 	return nil, false
		// }
		// if _, ok := z.Denom().SetString(s[sep+1:], 10); !ok {
		// 	return nil, false
		// }
		if _, ok := a.SetString(s[0:sep], 10); !ok {
			return nil, false
		}
		if _, ok := b.SetString(s[sep+1:], 10); !ok {
			return nil, false
		}
		z.SetFrac(a, b)
		C.mpq_canonicalize(&z.i[0])
		return z, true
	}

	// check for a decimal point
	sep = strings.Index(s, ".")
	// check for an exponent
	e := strings.IndexAny(s, "eE")
	exp := new(Int)
	if e >= 0 {
		if e < sep {
			// The E must come after the decimal point.
			return nil, false
		}
		if _, ok := exp.SetString(s[e+1:], 10); !ok {
			return nil, false
		}
		s = s[0:e]
	}
	if sep >= 0 {
		s = s[0:sep] + s[sep+1:]
		exp.Sub(exp, NewInt(int64(len(s)-sep)))
	}

	if _, ok := a.SetString(s, 10); !ok {
		return nil, false
	}
	absExp := new(Int).Abs(exp)
	powTen := new(Int).Exp(_Int10, absExp, nil)
	if exp.Sign() < 0 {
		b = powTen
	} else {
		a.Mul(a, powTen)
		b.SetInt64(1)
	}
	z.SetFrac(a, b)
	C.mpq_canonicalize(&z.i[0])

	return z, true
}