Commit e62dd7bc authored by Robert Griesemer's avatar Robert Griesemer

- split bignum package into 3 files

- use array for common small values
- integer.go, rational.go don't contain changes besides the added file header

R=rsc
DELTA=1475  (748 added, 713 deleted, 14 changed)
OCL=31939
CL=31942
parent f0c00f7e
......@@ -2,8 +2,9 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# DO NOT EDIT. Automatically generated by gobuild.
# gobuild -m >Makefile
# gobuild -m bignum.go integer.go rational.go >Makefile
D=
......@@ -20,7 +21,7 @@ test: packages
coverage: packages
gotest
6cov -g `pwd` | grep -v '_test\.go:'
6cov -g $$(pwd) | grep -v '_test\.go:'
%.$O: %.go
$(GC) -I_obj $*.go
......@@ -34,14 +35,28 @@ coverage: packages
O1=\
bignum.$O\
O2=\
integer.$O\
O3=\
rational.$O\
phases: a1
phases: a1 a2 a3
_obj$D/bignum.a: phases
a1: $(O1)
$(AR) grc _obj$D/bignum.a bignum.$O
rm -f $(O1)
a2: $(O2)
$(AR) grc _obj$D/bignum.a integer.$O
rm -f $(O2)
a3: $(O3)
$(AR) grc _obj$D/bignum.a rational.$O
rm -f $(O3)
newpkg: clean
mkdir -p _obj$D
......@@ -49,6 +64,8 @@ newpkg: clean
$(O1): newpkg
$(O2): a1
$(O3): a2
$(O4): a3
nuke: clean
rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/bignum.a
......
This diff is collapsed.
......@@ -116,6 +116,11 @@ func TestNatConv(t *testing.T) {
test(200 + uint(i), natFromString(e.s, 0, nil).Value() == e.x);
}
test_msg = "NatConvB";
for i := uint(0); i < 100; i++ {
test(i, Nat(uint64(i)).String() == fmt.Sprintf("%d", i));
}
test_msg = "NatConvC";
z := uint64(7);
for i := uint(0); i <= 64; i++ {
......
This diff is collapsed.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Rational numbers
package bignum
import "bignum"
import "fmt"
// Rational represents a quotient a/b of arbitrary precision.
//
type Rational struct {
a *Integer; // numerator
b Natural; // denominator
}
// MakeRat makes a rational number given a numerator a and a denominator b.
//
func MakeRat(a *Integer, b Natural) *Rational {
f := a.mant.Gcd(b); // f > 0
if f.Cmp(nat[1]) != 0 {
a = MakeInt(a.sign, a.mant.Div(f));
b = b.Div(f);
}
return &Rational{a, b};
}
// Rat creates a small rational number with value a0/b0.
//
func Rat(a0 int64, b0 int64) *Rational {
a, b := Int(a0), Int(b0);
if b.sign {
a = a.Neg();
}
return MakeRat(a, b.mant);
}
// Value returns the numerator and denominator of x.
//
func (x *Rational) Value() (numerator *Integer, denominator Natural) {
return x.a, x.b;
}
// Predicates
// IsZero returns true iff x == 0.
//
func (x *Rational) IsZero() bool {
return x.a.IsZero();
}
// IsNeg returns true iff x < 0.
//
func (x *Rational) IsNeg() bool {
return x.a.IsNeg();
}
// IsPos returns true iff x > 0.
//
func (x *Rational) IsPos() bool {
return x.a.IsPos();
}
// IsInt returns true iff x can be written with a denominator 1
// in the form x == x'/1; i.e., if x is an integer value.
//
func (x *Rational) IsInt() bool {
return x.b.Cmp(nat[1]) == 0;
}
// Operations
// Neg returns the negated value of x.
//
func (x *Rational) Neg() *Rational {
return MakeRat(x.a.Neg(), x.b);
}
// Add returns the sum x + y.
//
func (x *Rational) Add(y *Rational) *Rational {
return MakeRat((x.a.MulNat(y.b)).Add(y.a.MulNat(x.b)), x.b.Mul(y.b));
}
// Sub returns the difference x - y.
//
func (x *Rational) Sub(y *Rational) *Rational {
return MakeRat((x.a.MulNat(y.b)).Sub(y.a.MulNat(x.b)), x.b.Mul(y.b));
}
// Mul returns the product x * y.
//
func (x *Rational) Mul(y *Rational) *Rational {
return MakeRat(x.a.Mul(y.a), x.b.Mul(y.b));
}
// Quo returns the quotient x / y for y != 0.
// If y == 0, a division-by-zero run-time error occurs.
//
func (x *Rational) Quo(y *Rational) *Rational {
a := x.a.MulNat(y.b);
b := y.a.MulNat(x.b);
if b.IsNeg() {
a = a.Neg();
}
return MakeRat(a, b.mant);
}
// Cmp compares x and y. The result is an int value
//
// < 0 if x < y
// == 0 if x == y
// > 0 if x > y
//
func (x *Rational) Cmp(y *Rational) int {
return (x.a.MulNat(y.b)).Cmp(y.a.MulNat(x.b));
}
// ToString converts x to a string for a given base, with 2 <= base <= 16.
// The string representation is of the form "n" if x is an integer; otherwise
// it is of form "n/d".
//
func (x *Rational) ToString(base uint) string {
s := x.a.ToString(base);
if !x.IsInt() {
s += "/" + x.b.ToString(base);
}
return s;
}
// String converts x to its decimal string representation.
// x.String() is the same as x.ToString(10).
//
func (x *Rational) String() string {
return x.ToString(10);
}
// Format is a support routine for fmt.Formatter. It accepts
// the formats 'b' (binary), 'o' (octal), and 'x' (hexadecimal).
//
func (x *Rational) Format(h fmt.State, c int) {
fmt.Fprintf(h, "%s", x.ToString(fmtbase(c)));
}
// RatFromString returns the rational number corresponding to the
// longest possible prefix of s representing a rational number in a
// given conversion base, the actual conversion base used, and the
// prefix length. The syntax of a rational number is:
//
// rational = mantissa [exponent] .
// mantissa = integer ('/' natural | '.' natural) .
// exponent = ('e'|'E') integer .
//
// If the base argument is 0, the string prefix determines the actual
// conversion base for the mantissa. A prefix of ``0x'' or ``0X'' selects
// base 16; the ``0'' prefix selects base 8. Otherwise the selected base is 10.
// If the mantissa is represented via a division, both the numerator and
// denominator may have different base prefixes; in that case the base of
// of the numerator is returned. If the mantissa contains a decimal point,
// the base for the fractional part is the same as for the part before the
// decimal point and the fractional part does not accept a base prefix.
// The base for the exponent is always 10.
//
func RatFromString(s string, base uint) (*Rational, uint, int) {
// read numerator
a, abase, alen := IntFromString(s, base);
b := nat[1];
// read denominator or fraction, if any
var blen int;
if alen < len(s) {
ch := s[alen];
if ch == '/' {
alen++;
b, base, blen = NatFromString(s[alen : len(s)], base);
} else if ch == '.' {
alen++;
b, base, blen = NatFromString(s[alen : len(s)], abase);
assert(base == abase);
f := Nat(uint64(base)).Pow(uint(blen));
a = MakeInt(a.sign, a.mant.Mul(f).Add(b));
b = f;
}
}
// read exponent, if any
rlen := alen + blen;
if rlen < len(s) {
ch := s[rlen];
if ch == 'e' || ch == 'E' {
rlen++;
e, _, elen := IntFromString(s[rlen : len(s)], 10);
rlen += elen;
m := nat[10].Pow(uint(e.mant.Value()));
if e.sign {
b = b.Mul(m);
} else {
a = a.MulNat(m);
}
}
}
return MakeRat(a, b), base, rlen;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment