// is chosen such that division and multiplication by 10 (for decimal
// string representation) can be done without using extended-precision
// arithmetic. This makes addition, subtraction, and conversion routines
-// twice as fast. It requires a "buffer" of 4 bits per operand digit.
+// twice as fast. It requires a ``buffer'' of 4 bits per operand digit.
// That is, the size of B must be 4 bits smaller then the size of the
// type (digit) in which these operations are performed. Having this
// buffer also allows for trivial (single-bit) carry computation in
//
// 2) Long division requires extended-precision (2-digit) division per digit.
// Instead of sacrificing the largest base type for all other operations,
-// for division the operands are unpacked into "half-digits", and the
+// for division the operands are unpacked into ``half-digits'', and the
// results are packed again. For faster unpacking/packing, the base size
// in bits must be even.
const (
_LogW = 64;
- _LogH = 4; // bits for a hex digit (= "small" number)
+ _LogH = 4; // bits for a hex digit (= small number)
_LogB = _LogW - _LogH; // largest bit-width available
// half-digits
)
-// Nat creates a "small" natural number with value x.
+// Nat creates a small natural number with value x.
// Implementation restriction: At the moment, only values
// x < (1<<60) are supported.
//
// it relies on tripple-precision arithmetic which is why Knuth's method is
// used here.
//
-// 1) D. Knuth, "The Art of Computer Programming. Volume 2. Seminumerical
+// 1) D. Knuth, The Art of Computer Programming. Volume 2. Seminumerical
// Algorithms." Addison-Wesley, Reading, 1969.
// (Algorithm D, Sec. 4.3.1)
//
-// 2) Henry S. Warren, Jr., "A Hacker's Delight". Addison-Wesley, 2003.
+// 2) Henry S. Warren, Jr., Hacker's Delight. Addison-Wesley, 2003.
// (9-2 Multiword Division, p.140ff)
//
-// 3) P. Brinch Hansen, Multiple-length division revisited: A tour of the
-// minefield. "Software - Practice and Experience 24", (June 1994),
+// 3) P. Brinch Hansen, ``Multiple-length division revisited: A tour of the
+// minefield''. Software - Practice and Experience 24, (June 1994),
// 579-601. John Wiley & Sons, Ltd.
func divmod(x, y []digit2) ([]digit2, []digit2) {
// normalize x and y
// TODO Instead of multiplying, it would be sufficient to
// shift y such that the normalization condition is
- // satisfied (as done in "Hacker's Delight").
+ // satisfied (as done in Hacker's Delight).
f := _B2 / (digit(y[m-1]) + 1);
if f != 1 {
mul1(x, x, digit2(f));
}
-// Shl implements "shift left" x << s. It returns x * 2^s.
+// Shl implements ``shift left'' x << s. It returns x * 2^s.
//
func (x Natural) Shl(s uint) Natural {
n := uint(len(x));
}
-// Shr implements "shift right" x >> s. It returns x / 2^s.
+// Shr implements ``shift right'' x >> s. It returns x / 2^s.
//
func (x Natural) Shr(s uint) Natural {
n := uint(len(x));
}
-// And returns the "bitwise and" x & y for the binary representation of x and y.
+// And returns the ``bitwise and'' x & y for the binary representation of x and y.
//
func (x Natural) And(y Natural) Natural {
n := len(x);
}
-// Or returns the "bitwise or" x | y for the binary representation of x and y.
+// Or returns the ``bitwise or'' x | y for the binary representation of x and y.
//
func (x Natural) Or(y Natural) Natural {
n := len(x);
}
-// Xor returns the "bitwise exclusive or" x ^ y for the binary representation of x and y.
+// Xor returns the ``bitwise exclusive or'' x ^ y for the binary representation of x and y.
//
func (x Natural) Xor(y Natural) Natural {
n := len(x);
}
-// Computes x = x div d in place (modifies x) for "small" d's.
+// Computes x = x div d in place (modifies x) for small d's.
// Returns updated x and x mod d.
//
func divmod1(x Natural, d digit) (Natural, digit) {
}
-// Computes x = x*d + c for "small" d's.
+// Computes x = x*d + c for small d's.
//
func muladd1(x Natural, d, c digit) Natural {
assert(isSmall(d-1) && isSmall(c));
// NatFromString returns the natural number corresponding to the
// longest possible prefix of s representing a natural number in a
-// given conversion base.
+// given conversion base, the actual conversion base used, and the
+// prefix length.
//
// If the base argument is 0, the string prefix determines the actual
-// conversion base. A prefix of "0x" or "0X" selects base 16; the "0"
-// prefix selects base 8. Otherwise the selected base is 10.
+// conversion base. A prefix of ``0x'' or ``0X'' selects base 16; the
+// ``0'' prefix selects base 8. Otherwise the selected base is 10.
//
-// If a non-nil slen argument is provided, *slen is set to the length
-// of the string prefix converted.
-//
-func NatFromString(s string, base uint, slen *int) (Natural, uint) {
+func NatFromString(s string, base uint) (Natural, uint, int) {
// determine base if necessary
i, n := 0, len(s);
if base == 0 {
}
}
- // provide number of string bytes consumed if necessary
- if slen != nil {
- *slen = i;
- }
-
- return x, base;
+ return x, base, i;
}
}
-// Pop computes the "population count" of x.
-// The result is the number of set bits (i.e., "1" digits)
-// in the binary representation of x.
+// Pop computes the ``population count'' of (the number of 1 bits in) x.
//
func (x Natural) Pop() uint {
n := uint(0);
}
-// Int creates a "small" integer with value x.
+// Int creates a small integer with value x.
// Implementation restriction: At the moment, only values
// with an absolute value |x| < (1<<60) are supported.
//
// q = x.Quo(y) = trunc(x/y) (truncation towards zero)
// r = x.Rem(y) = x - y*q
//
-// (Daan Leijen, "Division and Modulus for Computer Scientists".)
+// (Daan Leijen, ``Division and Modulus for Computer Scientists''.)
//
func (x *Integer) Quo(y *Integer) *Integer {
// x / y == x / y
// q = x.Div(y)
// r = x.Mod(y) with: 0 <= r < |q| and: y = x*q + r
//
-// (Raymond T. Boute, The Euclidian definition of the functions
-// div and mod. "ACM Transactions on Programming Languages and
-// Systems (TOPLAS)", 14(2):127-144, New York, NY, USA, 4/1992.
+// (Raymond T. Boute, ``The Euclidian definition of the functions
+// div and mod''. ACM Transactions on Programming Languages and
+// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
// ACM press.)
//
func (x *Integer) Div(y *Integer) *Integer {
}
-// Shl implements "shift left" x << s. It returns x * 2^s.
+// Shl implements ``shift left'' x << s. It returns x * 2^s.
//
func (x *Integer) Shl(s uint) *Integer {
return MakeInt(x.sign, x.mant.Shl(s));
}
-// Shr implements "shift right" x >> s. It returns x / 2^s.
+// Shr implements ``shift right'' x >> s. It returns x / 2^s.
// Implementation restriction: Shl is not yet implemented for negative x.
//
func (x *Integer) Shr(s uint) *Integer {
}
-// And returns the "bitwise and" x & y for the binary representation of x and y.
+// And returns the ``bitwise and'' x & y for the binary representation of x and y.
// Implementation restriction: And is not implemented for negative x.
//
func (x *Integer) And(y *Integer) *Integer {
}
-// Or returns the "bitwise or" x | y for the binary representation of x and y.
+// Or returns the ``bitwise or'' x | y for the binary representation of x and y.
// Implementation restriction: Or is not implemented for negative x.
//
func (x *Integer) Or(y *Integer) *Integer {
}
-// Xor returns the "bitwise xor" x | y for the binary representation of x and y.
+// Xor returns the ``bitwise xor'' x | y for the binary representation of x and y.
// Implementation restriction: Xor is not implemented for negative integers.
//
func (x *Integer) Xor(y *Integer) *Integer {
// IntFromString returns the integer corresponding to the
// longest possible prefix of s representing an integer in a
-// given conversion base.
+// given conversion base, the actual conversion base used, and
+// the prefix length.
//
// If the base argument is 0, the string prefix determines the actual
-// conversion base. A prefix of "0x" or "0X" selects base 16; the "0"
-// prefix selects base 8. Otherwise the selected base is 10.
+// conversion base. A prefix of ``0x'' or ``0X'' selects base 16; the
+// ``0'' prefix selects base 8. Otherwise the selected base is 10.
//
-// If a non-nil slen argument is provided, *slen is set to the length
-// of the string prefix converted.
-//
-func IntFromString(s string, base uint, slen *int) (*Integer, uint) {
- // get sign, if any
- sign := false;
+func IntFromString(s string, base uint) (*Integer, uint, int) {
+ // skip sign, if any
+ i0 := 0;
if len(s) > 0 && (s[0] == '-' || s[0] == '+') {
- sign = s[0] == '-';
- s = s[1 : len(s)];
+ i0 = 1;
}
- var mant Natural;
- mant, base = NatFromString(s, base, slen);
+ mant, base, slen := NatFromString(s[i0 : len(s)], base);
- // correct slen if necessary
- if slen != nil && sign {
- *slen++;
- }
-
- return MakeInt(sign, mant), base;
+ return MakeInt(i0 > 0 && s[0] == '-', mant), base, i0 + slen;
}
}
-// Rat creates a "small" rational number with value a0/b0.
+// Rat creates a small rational number with value a0/b0.
// Implementation restriction: At the moment, only values a0, b0
// with an absolute value |a0|, |b0| < (1<<60) are supported.
//
// ToString converts x to a string for a given base, with 2 <= base <= 16.
-// The string representation is of the form "numerator/denominator".
+// 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);
// RatFromString returns the rational number corresponding to the
// longest possible prefix of s representing a rational number in a
-// given conversion base.
+// given conversion base, the actual conversion base used, and the
+// prefix length.
//
// If the base argument is 0, the string prefix determines the actual
-// conversion base. A prefix of "0x" or "0X" selects base 16; the "0"
-// prefix selects base 8. Otherwise the selected base is 10.
-//
-// If a non-nil slen argument is provided, *slen is set to the length
-// of the string prefix converted.
+// conversion base. A prefix of ``0x'' or ``0X'' selects base 16; the
+// ``0'' prefix selects base 8. Otherwise the selected base is 10.
//
-func RatFromString(s string, base uint, slen *int) (*Rational, uint) {
+func RatFromString(s string, base uint) (*Rational, uint, int) {
// read nominator
- var alen, blen int;
- a, abase := IntFromString(s, base, &alen);
+ 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 = NatFromString(s[alen : len(s)], base, &blen);
+ b, base, blen = NatFromString(s[alen : len(s)], base);
} else if ch == '.' {
alen++;
- b, base = NatFromString(s[alen : len(s)], abase, &blen);
+ b, base, blen = NatFromString(s[alen : len(s)], abase);
assert(base == abase);
f := Nat(base).Pow(uint(blen));
a = MakeInt(a.sign, a.mant.Mul(f).Add(b));
}
}
- // provide number of string bytes consumed if necessary
- if slen != nil {
- *slen = alen + blen;
- }
-
- return MakeRat(a, b), abase;
+ return MakeRat(a, b), base, alen + blen;
}
)
func natFromString(s string, base uint, slen *int) bignum.Natural {
- x, dummy := bignum.NatFromString(s, base, slen);
+ x, _, len := bignum.NatFromString(s, base);
+ if slen != nil {
+ *slen = len;
+ }
return x;
}
func intFromString(s string, base uint, slen *int) *bignum.Integer {
- x, dummy := bignum.IntFromString(s, base, slen);
+ x, _, len := bignum.IntFromString(s, base);
+ if slen != nil {
+ *slen = len;
+ }
return x;
}
func ratFromString(s string, base uint, slen *int) *bignum.Rational {
- x, dummy := bignum.RatFromString(s, base, slen);
+ x, _, len := bignum.RatFromString(s, base);
+ if slen != nil {
+ *slen = len;
+ }
return x;
}
func int_eq(n uint, x, y *bignum.Integer) {
if x.Cmp(y) != 0 {
- tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, &x, &y);
+ tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, x, y);
}
}
func rat_eq(n uint, x, y *bignum.Rational) {
if x.Cmp(y) != 0 {
- tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, &x, &y);
+ tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, x, y);
}
}
test_msg = "NatConvD";
x := bignum.Nat(100);
- y, b := bignum.NatFromString(fmt.Sprintf("%b", &x), 2, nil);
+ y, b, _ := bignum.NatFromString(fmt.Sprintf("%b", &x), 2);
nat_eq(100, y, x);
}
int_eq(4, intFromString("077", 0, nil), bignum.Int(7*8 + 7));
int_eq(5, intFromString("-077", 0, nil), bignum.Int(-(7*8 + 7)));
int_eq(6, intFromString("0x1f", 0, nil), bignum.Int(1*16 + 15));
- int_eq(7, intFromString("-0x1f", 0, nil), bignum.Int(-(1*16 + 15)));
- int_eq(8, intFromString("0x1fg", 0, &slen), bignum.Int(1*16 + 15));
- int_eq(9, intFromString("-0x1fg", 0, &slen), bignum.Int(-(1*16 + 15)));
+ int_eq(7, intFromString("-0x1f", 0, &slen), bignum.Int(-(1*16 + 15)));
+ test(7, slen == 5);
+ int_eq(8, intFromString("+0x1f", 0, &slen), bignum.Int(+(1*16 + 15)));
+ test(8, slen == 5);
+ int_eq(9, intFromString("0x1fg", 0, &slen), bignum.Int(1*16 + 15));
+ test(9, slen == 4);
+ int_eq(10, intFromString("-0x1fg", 0, &slen), bignum.Int(-(1*16 + 15)));
test(10, slen == 5);
}