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