]> Cypherpunks repositories - gostls13.git/commitdiff
- documentation for bignum package
authorRobert Griesemer <gri@golang.org>
Tue, 21 Apr 2009 17:52:00 +0000 (10:52 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 21 Apr 2009 17:52:00 +0000 (10:52 -0700)
- removed some constants from public interface

R=r
DELTA=375  (238 added, 14 deleted, 123 changed)
OCL=27636
CL=27668

src/lib/bignum.go

index 078374ad7e51e9fb689234bd8e8aa5de8fa2f1c2..e122a2cace1af04e7684878322ed9bdc495c54e4 100755 (executable)
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package bignum
-
 // A package for arbitrary precision arithmethic.
 // It implements the following numeric types:
 //
-// - Natural   unsigned integer numbers
-// - Integer   signed integer numbers
+// - Natural   unsigned integers
+// - Integer   signed integers
 // - Rational  rational numbers
+//
+package bignum
 
 import "fmt"
 
@@ -21,13 +21,13 @@ import "fmt"
 //
 //   x = x[n-1]*B^(n-1) + x[n-2]*B^(n-2) + ... + x[1]*B + x[0]
 //
-// with 0 <= x[i] < B and 0 <= i < n is stored in an array of length n,
-// with the digits x[i] as the array elements.
+// with 0 <= x[i] < B and 0 <= i < n is stored in a slice of length n,
+// with the digits x[i] as the slice elements.
 //
-// A natural number is normalized if the array contains no leading 0 digits.
-// During arithmetic operations, denormalized values may occur which are
+// A natural number is normalized if the slice contains no leading 0 digits.
+// During arithmetic operations, denormalized values may occur but are
 // always normalized before returning the final result. The normalized
-// representation of 0 is the empty array (length = 0).
+// representation of 0 is the empty slice (length = 0).
 //
 // The operations for all other numeric types are implemented on top of
 // the operations for natural numbers.
@@ -42,7 +42,7 @@ import "fmt"
 //    arithmetic. This makes addition, subtraction, and conversion routines
 //    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
+//    type (digit) in which these operations are performed. Having this
 //    buffer also allows for trivial (single-bit) carry computation in
 //    addition and subtraction (optimization suggested by Ken Thompson).
 //
@@ -53,17 +53,16 @@ import "fmt"
 //    in bits must be even.
 
 type (
-       Digit  uint64;
-       Digit2 uint32;  // half-digits for division
+       digit  uint64;
+       digit2 uint32;  // half-digits for division
 )
 
 
-const _LogW = 64;
-const _LogH = 4;  // bits for a hex digit (= "small" number)
-const _LogB = _LogW - _LogH;  // largest bit-width available
-
-
 const (
+       _LogW = 64;
+       _LogH = 4;  // bits for a hex digit (= "small" number)
+       _LogB = _LogW - _LogH;  // largest bit-width available
+
        // half-digits
        _W2 = _LogB / 2;  // width
        _B2 = 1 << _W2;   // base
@@ -86,12 +85,13 @@ func assert(p bool) {
 }
 
 
-func isSmall(x Digit) bool {
+func isSmall(x digit) bool {
        return x < 1<<_LogH;
 }
 
 
-func Dump(x []Digit) {
+// For debugging.
+func dump(x []digit) {
        print("[", len(x), "]");
        for i := len(x) - 1; i >= 0; i-- {
                print(" ", x[i]);
@@ -102,16 +102,10 @@ func Dump(x []Digit) {
 
 // ----------------------------------------------------------------------------
 // Natural numbers
-//
-// Naming conventions
-//
-// c      carry
-// x, y   operands
-// z      result
-// n, m   len(x), len(y)
 
-
-type Natural []Digit;
+// Natural represents an unsigned integer value of arbitrary precision.
+//
+type Natural []digit;
 
 var (
        natZero Natural = Natural{};
@@ -121,8 +115,10 @@ var (
 )
 
 
-// Creation
-
+// Nat creates a "small" natural number with value x.
+// Implementation restriction: At the moment, only values
+// x < (1<<60) are supported.
+//
 func Nat(x uint) Natural {
        switch x {
        case 0: return natZero;
@@ -130,24 +126,40 @@ func Nat(x uint) Natural {
        case 2: return natTwo;
        case 10: return natTen;
        }
-       assert(Digit(x) < _B);
-       return Natural{Digit(x)};
+       assert(digit(x) < _B);
+       return Natural{digit(x)};
 }
 
 
-// Predicates
+// IsEven returns true iff x is divisible by 2.
+//
+func (x Natural) IsEven() bool {
+       return len(x) == 0 || x[0]&1 == 0;
+}
+
 
+// IsOdd returns true iff x is not divisible by 2.
+//
 func (x Natural) IsOdd() bool {
        return len(x) > 0 && x[0]&1 != 0;
 }
 
 
+// IsZero returns true iff x == 0.
+//
 func (x Natural) IsZero() bool {
        return len(x) == 0;
 }
 
 
 // Operations
+//
+// Naming conventions
+//
+// c      carry
+// x, y   operands
+// z      result
+// n, m   len(x), len(y)
 
 func normalize(x Natural) Natural {
        n := len(x);
@@ -159,6 +171,8 @@ func normalize(x Natural) Natural {
 }
 
 
+// Add returns the sum x + y.
+//
 func (x Natural) Add(y Natural) Natural {
        n := len(x);
        m := len(y);
@@ -166,7 +180,7 @@ func (x Natural) Add(y Natural) Natural {
                return y.Add(x);
        }
 
-       c := Digit(0);
+       c := digit(0);
        z := make(Natural, n + 1);
        i := 0;
        for i < m {
@@ -188,6 +202,9 @@ func (x Natural) Add(y Natural) Natural {
 }
 
 
+// Sub returns the difference x - y for x >= y.
+// If x < y, an underflow run-time error occurs (use Cmp to test if x >= y).
+//
 func (x Natural) Sub(y Natural) Natural {
        n := len(x);
        m := len(y);
@@ -195,17 +212,17 @@ func (x Natural) Sub(y Natural) Natural {
                panic("underflow")
        }
 
-       c := Digit(0);
+       c := digit(0);
        z := make(Natural, n);
        i := 0;
        for i < m {
                t := c + x[i] - y[i];
-               c, z[i] = Digit(int64(t)>>_W), t&_M;  // requires arithmetic shift!
+               c, z[i] = digit(int64(t)>>_W), t&_M;  // requires arithmetic shift!
                i++;
        }
        for i < n {
                t := c + x[i];
-               c, z[i] = Digit(int64(t)>>_W), t&_M;  // requires arithmetic shift!
+               c, z[i] = digit(int64(t)>>_W), t&_M;  // requires arithmetic shift!
                i++;
        }
        for i > 0 && z[i - 1] == 0 {  // normalize
@@ -217,7 +234,8 @@ func (x Natural) Sub(y Natural) Natural {
 
 
 // Returns c = x*y div B, z = x*y mod B.
-func mul11(x, y Digit) (Digit, Digit) {
+//
+func mul11(x, y digit) (digit, digit) {
        // Split x and y into 2 sub-digits each,
        // multiply the digits separately while avoiding overflow,
        // and return the product as two separate digits.
@@ -250,6 +268,8 @@ func mul11(x, y Digit) (Digit, Digit) {
 }
 
 
+// Mul returns the product x * y.
+//
 func (x Natural) Mul(y Natural) Natural {
        n := len(x);
        m := len(y);
@@ -258,7 +278,7 @@ func (x Natural) Mul(y Natural) Natural {
        for j := 0; j < m; j++ {
                d := y[j];
                if d != 0 {
-                       c := Digit(0);
+                       c := digit(0);
                        for i := 0; i < n; i++ {
                                // z[i+j] += c + x[i]*d;
                                z1, z0 := mul11(x[i], d);
@@ -274,18 +294,18 @@ func (x Natural) Mul(y Natural) Natural {
 }
 
 
-// DivMod needs multi-precision division which is not available if Digit
+// DivMod needs multi-precision division, which is not available if digit
 // is already using the largest uint size. Instead, unpack each operand
-// into operands with twice as many digits of half the size (Digit2), do
+// into operands with twice as many digits of half the size (digit2), do
 // DivMod, and then pack the results again.
 
-func unpack(x Natural) []Digit2 {
+func unpack(x Natural) []digit2 {
        n := len(x);
-       z := make([]Digit2, n*2 + 1);  // add space for extra digit (used by DivMod)
+       z := make([]digit2, n*2 + 1);  // add space for extra digit (used by DivMod)
        for i := 0; i < n; i++ {
                t := x[i];
-               z[i*2] = Digit2(t & _M2);
-               z[i*2 + 1] = Digit2(t >> _W2 & _M2);
+               z[i*2] = digit2(t & _M2);
+               z[i*2 + 1] = digit2(t >> _W2 & _M2);
        }
 
        // normalize result
@@ -295,42 +315,42 @@ func unpack(x Natural) []Digit2 {
 }
 
 
-func pack(x []Digit2) Natural {
+func pack(x []digit2) Natural {
        n := (len(x) + 1) / 2;
        z := make(Natural, n);
        if len(x) & 1 == 1 {
                // handle odd len(x)
                n--;
-               z[n] = Digit(x[n*2]);
+               z[n] = digit(x[n*2]);
        }
        for i := 0; i < n; i++ {
-               z[i] = Digit(x[i*2 + 1]) << _W2 | Digit(x[i*2]);
+               z[i] = digit(x[i*2 + 1]) << _W2 | digit(x[i*2]);
        }
        return normalize(z);
 }
 
 
-func mul1(z, x []Digit2, y Digit2) Digit2 {
+func mul1(z, x []digit2, y digit2) digit2 {
        n := len(x);
-       c := Digit(0);
-       f := Digit(y);
+       c := digit(0);
+       f := digit(y);
        for i := 0; i < n; i++ {
-               t := c + Digit(x[i])*f;
-               c, z[i] = t>>_W2, Digit2(t&_M2);
+               t := c + digit(x[i])*f;
+               c, z[i] = t>>_W2, digit2(t&_M2);
        }
-       return Digit2(c);
+       return digit2(c);
 }
 
 
-func div1(z, x []Digit2, y Digit2) Digit2 {
+func div1(z, x []digit2, y digit2) digit2 {
        n := len(x);
-       c := Digit(0);
-       d := Digit(y);
+       c := digit(0);
+       d := digit(y);
        for i := n-1; i >= 0; i-- {
-               t := c*_B2 + Digit(x[i]);
-               c, z[i] = t%d, Digit2(t/d);
+               t := c*_B2 + digit(x[i]);
+               c, z[i] = t%d, digit2(t/d);
        }
-       return Digit2(c);
+       return digit2(c);
 }
 
 
@@ -354,7 +374,7 @@ func div1(z, x []Digit2, y Digit2) Digit2 {
 //    minefield. "Software - Practice and Experience 24", (June 1994),
 //    579-601. John Wiley & Sons, Ltd.
 
-func divmod(x, y []Digit2) ([]Digit2, []Digit2) {
+func divmod(x, y []digit2) ([]digit2, []digit2) {
        n := len(x);
        m := len(y);
        if m == 0 {
@@ -382,21 +402,21 @@ func divmod(x, y []Digit2) ([]Digit2, []Digit2) {
                // TODO Instead of multiplying, it would be sufficient to
                //      shift y such that the normalization condition is
                //      satisfied (as done in "Hacker's Delight").
-               f := _B2 / (Digit(y[m-1]) + 1);
+               f := _B2 / (digit(y[m-1]) + 1);
                if f != 1 {
-                       mul1(x, x, Digit2(f));
-                       mul1(y, y, Digit2(f));
+                       mul1(x, x, digit2(f));
+                       mul1(y, y, digit2(f));
                }
                assert(_B2/2 <= y[m-1] && y[m-1] < _B2);  // incorrect scaling
 
-               y1, y2 := Digit(y[m-1]), Digit(y[m-2]);
-               d2 := Digit(y1)<<_W2 + Digit(y2);
+               y1, y2 := digit(y[m-1]), digit(y[m-2]);
+               d2 := digit(y1)<<_W2 + digit(y2);
                for i := n-m; i >= 0; i-- {
                        k := i+m;
 
                        // compute trial digit (Knuth)
-                       var q Digit;
-                       {       x0, x1, x2 := Digit(x[k]), Digit(x[k-1]), Digit(x[k-2]);
+                       var q digit;
+                       {       x0, x1, x2 := digit(x[k]), digit(x[k-1]), digit(x[k-2]);
                                if x0 != y1 {
                                        q = (x0<<_W2 + x1)/y1;
                                } else {
@@ -408,31 +428,31 @@ func divmod(x, y []Digit2) ([]Digit2, []Digit2) {
                        }
 
                        // subtract y*q
-                       c := Digit(0);
+                       c := digit(0);
                        for j := 0; j < m; j++ {
-                               t := c + Digit(x[i+j]) - Digit(y[j])*q;
-                               c, x[i+j] = Digit(int64(t) >> _W2), Digit2(t & _M2);  // requires arithmetic shift!
+                               t := c + digit(x[i+j]) - digit(y[j])*q;
+                               c, x[i+j] = digit(int64(t) >> _W2), digit2(t & _M2);  // requires arithmetic shift!
                        }
 
                        // correct if trial digit was too large
-                       if c + Digit(x[k]) != 0 {
+                       if c + digit(x[k]) != 0 {
                                // add y
-                               c := Digit(0);
+                               c := digit(0);
                                for j := 0; j < m; j++ {
-                                       t := c + Digit(x[i+j]) + Digit(y[j]);
-                                       c, x[i+j] = t >> _W2, Digit2(t & _M2)
+                                       t := c + digit(x[i+j]) + digit(y[j]);
+                                       c, x[i+j] = t >> _W2, digit2(t & _M2)
                                }
-                               assert(c + Digit(x[k]) == 0);
+                               assert(c + digit(x[k]) == 0);
                                // correct trial digit
                                q--;
                        }
 
-                       x[k] = Digit2(q);
+                       x[k] = digit2(q);
                }
 
                // undo normalization for remainder
                if f != 1 {
-                       c := div1(x[0 : m], x[0 : m], Digit2(f));
+                       c := div1(x[0 : m], x[0 : m], digit2(f));
                        assert(c == 0);
                }
        }
@@ -441,28 +461,39 @@ func divmod(x, y []Digit2) ([]Digit2, []Digit2) {
 }
 
 
+// Div returns the quotient q = x / y for y > 0,
+// with x = y*q + r and 0 <= r < y.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 func (x Natural) Div(y Natural) Natural {
        q, r := divmod(unpack(x), unpack(y));
        return pack(q);
 }
 
 
+// Mod returns the modulus r of the division x / y for y > 0,
+// with x = y*q + r and 0 <= r < y.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 func (x Natural) Mod(y Natural) Natural {
        q, r := divmod(unpack(x), unpack(y));
        return pack(r);
 }
 
 
+// DivMod returns the pair (x.Div(y), x.Mod(y)) for y > 0.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 func (x Natural) DivMod(y Natural) (Natural, Natural) {
        q, r := divmod(unpack(x), unpack(y));
        return pack(q), pack(r);
 }
 
 
-func shl(z, x []Digit, s uint) Digit {
+func shl(z, x []digit, s uint) digit {
        assert(s <= _W);
        n := len(x);
-       c := Digit(0);
+       c := digit(0);
        for i := 0; i < n; i++ {
                c, z[i] = x[i] >> (_W-s), x[i] << s & _M | c;
        }
@@ -470,6 +501,8 @@ func shl(z, x []Digit, s uint) Digit {
 }
 
 
+// Shl implements "shift left" x << s. It returns x * 2^s.
+//
 func (x Natural) Shl(s uint) Natural {
        n := uint(len(x));
        m := n + s/_W;
@@ -481,10 +514,10 @@ func (x Natural) Shl(s uint) Natural {
 }
 
 
-func shr(z, x []Digit, s uint) Digit {
+func shr(z, x []digit, s uint) digit {
        assert(s <= _W);
        n := len(x);
-       c := Digit(0);
+       c := digit(0);
        for i := n - 1; i >= 0; i-- {
                c, z[i] = x[i] << (_W-s) & _M, x[i] >> s | c;
        }
@@ -492,6 +525,8 @@ func shr(z, x []Digit, s uint) Digit {
 }
 
 
+// Shr implements "shift right" x >> s. It returns x / 2^s.
+//
 func (x Natural) Shr(s uint) Natural {
        n := uint(len(x));
        m := n - s/_W;
@@ -506,6 +541,8 @@ func (x Natural) Shr(s uint) Natural {
 }
 
 
+// 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);
        m := len(y);
@@ -523,13 +560,15 @@ func (x Natural) And(y Natural) Natural {
 }
 
 
-func copy(z, x []Digit) {
+func copy(z, x []digit) {
        for i, e := range x {
                z[i] = e
        }
 }
 
 
+// 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);
        m := len(y);
@@ -547,6 +586,8 @@ func (x Natural) Or(y Natural) Natural {
 }
 
 
+// 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);
        m := len(y);
@@ -564,6 +605,12 @@ func (x Natural) Xor(y Natural) Natural {
 }
 
 
+// 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 Natural) Cmp(y Natural) int {
        n := len(x);
        m := len(y);
@@ -585,7 +632,7 @@ func (x Natural) Cmp(y Natural) int {
 }
 
 
-func log2(x Digit) uint {
+func log2(x digit) uint {
        assert(x > 0);
        n := uint(0);
        for x > 0 {
@@ -596,6 +643,10 @@ func log2(x Digit) uint {
 }
 
 
+// Log2 computes the binary logarithm of x for x > 0.
+// The result is the integer n for which 2^n <= x < 2^(n+1).
+// If x == 0 a run-time error occurs.
+//
 func (x Natural) Log2() uint {
        n := len(x);
        if n > 0 {
@@ -607,10 +658,11 @@ func (x Natural) Log2() uint {
 
 // 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) {
+//
+func divmod1(x Natural, d digit) (Natural, digit) {
        assert(0 < d && isSmall(d - 1));
 
-       c := Digit(0);
+       c := digit(0);
        for i := len(x) - 1; i >= 0; i-- {
                t := c<<_W + x[i];
                c, x[i] = t%d, t/d;
@@ -620,6 +672,8 @@ func divmod1(x Natural, d Digit) (Natural, Digit) {
 }
 
 
+// ToString converts x to a string for a given base, with 2 <= base <= 16.
+//
 func (x Natural) ToString(base uint) string {
        if len(x) == 0 {
                return "0";
@@ -627,7 +681,7 @@ func (x Natural) ToString(base uint) string {
 
        // allocate buffer for conversion
        assert(2 <= base && base <= 16);
-       n := (x.Log2() + 1) / log2(Digit(base)) + 1;  // +1: round up
+       n := (x.Log2() + 1) / log2(digit(base)) + 1;  // +1: round up
        s := make([]byte, n);
 
        // don't destroy x
@@ -638,8 +692,8 @@ func (x Natural) ToString(base uint) string {
        i := n;
        for !t.IsZero() {
                i--;
-               var d Digit;
-               t, d = divmod1(t, Digit(base));
+               var d digit;
+               t, d = divmod1(t, digit(base));
                s[i] = "0123456789abcdef"[d];
        };
 
@@ -647,6 +701,9 @@ func (x Natural) ToString(base uint) string {
 }
 
 
+// String converts x to its decimal string representation.
+// (x.String is the same as x.ToString(10)).
+//
 func (x Natural) String() string {
        return x.ToString(10);
 }
@@ -662,6 +719,9 @@ func fmtbase(c int) uint {
 }
 
 
+// Format is a support routine for fmt.Formatter. It accepts
+// the formats 'b' (binary), 'o' (octal), and 'x' (hexadecimal).
+//
 func (x Natural) Format(h fmt.Formatter, c int) {
        fmt.Fprintf(h, "%s", x.ToString(fmtbase(c)));
 }
@@ -679,7 +739,8 @@ func hexvalue(ch byte) uint {
 
 
 // Computes x = x*d + c for "small" d's.
-func muladd1(x Natural, d, c Digit) Natural {
+//
+func muladd1(x Natural, d, c digit) Natural {
        assert(isSmall(d-1) && isSmall(c));
        n := len(x);
        z := make(Natural, n + 1);
@@ -694,8 +755,17 @@ func muladd1(x Natural, d, c Digit) Natural {
 }
 
 
-// Determines base (octal, decimal, hexadecimal) if base == 0.
-// Returns the number and base.
+// NatFromString returns the natural number corresponding to the
+// longest possible prefix of s representing a natural number in a
+// given conversion base.
+//
+// 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.
+//
 func NatFromString(s string, base uint, slen *int) (Natural, uint) {
        // determine base if necessary
        i, n := 0, len(s);
@@ -716,7 +786,7 @@ func NatFromString(s string, base uint, slen *int) (Natural, uint) {
        for ; i < n; i++ {
                d := hexvalue(s[i]);
                if d < base {
-                       x = muladd1(x, Digit(base), Digit(d));
+                       x = muladd1(x, digit(base), digit(d));
                } else {
                        break;
                }
@@ -733,7 +803,7 @@ func NatFromString(s string, base uint, slen *int) (Natural, uint) {
 
 // Natural number functions
 
-func pop1(x Digit) uint {
+func pop1(x digit) uint {
        n := uint(0);
        for x != 0 {
                x &= x-1;
@@ -743,6 +813,10 @@ func pop1(x Digit) uint {
 }
 
 
+// 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.
+//
 func (x Natural) Pop() uint {
        n := uint(0);
        for i := len(x) - 1; i >= 0; i-- {
@@ -752,6 +826,8 @@ func (x Natural) Pop() uint {
 }
 
 
+// Pow computes x to the power of n.
+//
 func (xp Natural) Pow(n uint) Natural {
        z := Nat(1);
        x := xp;
@@ -766,6 +842,9 @@ func (xp Natural) Pow(n uint) Natural {
 }
 
 
+// MulRange computes the product of all the unsigned integers
+// in the range [a, b] inclusively.
+//
 func MulRange(a, b uint) Natural {
        switch {
        case a > b: return Nat(1);
@@ -778,6 +857,8 @@ func MulRange(a, b uint) Natural {
 }
 
 
+// Fact computes the factorial of n (Fact(n) == MulRange(2, n)).
+//
 func Fact(n uint) Natural {
        // Using MulRange() instead of the basic for-loop
        // lead to faster factorial computation.
@@ -785,18 +866,22 @@ func Fact(n uint) Natural {
 }
 
 
+// Binomial computes the binomial coefficient of (n, k).
+//
 func Binomial(n, k uint) Natural {
        return MulRange(n-k+1, n).Div(MulRange(1, k));
 }
 
 
-func (xp Natural) Gcd(y Natural) Natural {
+// Gcd computes the gcd of x and y.
+//
+func (x Natural) Gcd(y Natural) Natural {
        // Euclidean algorithm.
-       x := xp;
-       for !y.IsZero() {
-               x, y = y, x.Mod(y);
+       a, b := x, y;
+       for !b.IsZero() {
+               a, b = b, a.Mod(b);
        }
-       return x;
+       return a;
 }
 
 
@@ -806,14 +891,18 @@ func (xp Natural) Gcd(y Natural) Natural {
 // Integers are normalized if the mantissa is normalized and the sign is
 // false for mant == 0. Use MakeInt to create normalized Integers.
 
+// Integer represents a signed integer value of arbitrary precision.
+//
 type Integer struct {
        sign bool;
        mant Natural;
 }
 
 
-// Creation
-
+// MakeInt makes an integer given a sign and a mantissa.
+// The number is positive (>= 0) if sign is false or the
+// mantissa is zero; it is negative otherwise.
+//
 func MakeInt(sign bool, mant Natural) *Integer {
        if mant.IsZero() {
                sign = false;  // normalize
@@ -822,6 +911,10 @@ func MakeInt(sign bool, mant Natural) *Integer {
 }
 
 
+// Int creates a "small" integer with value x.
+// Implementation restriction: At the moment, only values
+// with an absolute value |x| < (1<<60) are supported.
+//
 func Int(x int) *Integer {
        sign := false;
        var ux uint;
@@ -843,21 +936,36 @@ func Int(x int) *Integer {
 
 // Predicates
 
+// IsEven returns true iff x is divisible by 2.
+//
+func (x *Integer) IsEven() bool {
+       return x.mant.IsEven();
+}
+
+
+// IsOdd returns true iff x is not divisible by 2.
+//
 func (x *Integer) IsOdd() bool {
        return x.mant.IsOdd();
 }
 
 
+// IsZero returns true iff x == 0.
+//
 func (x *Integer) IsZero() bool {
        return x.mant.IsZero();
 }
 
 
+// IsNeg returns true iff x < 0.
+//
 func (x *Integer) IsNeg() bool {
        return x.sign && !x.mant.IsZero()
 }
 
 
+// IsPos returns true iff x >= 0.
+//
 func (x *Integer) IsPos() bool {
        return !x.sign && !x.mant.IsZero()
 }
@@ -865,11 +973,15 @@ func (x *Integer) IsPos() bool {
 
 // Operations
 
+// Neg returns the negated value of x.
+//
 func (x *Integer) Neg() *Integer {
        return MakeInt(!x.sign, x.mant);
 }
 
 
+// Add returns the sum x + y.
+//
 func (x *Integer) Add(y *Integer) *Integer {
        var z *Integer;
        if x.sign == y.sign {
@@ -892,6 +1004,8 @@ func (x *Integer) Add(y *Integer) *Integer {
 }
 
 
+// Sub returns the difference x - y.
+//
 func (x *Integer) Sub(y *Integer) *Integer {
        var z *Integer;
        if x.sign != y.sign {
@@ -914,6 +1028,8 @@ func (x *Integer) Sub(y *Integer) *Integer {
 }
 
 
+// Mul returns the product x * y.
+//
 func (x *Integer) Mul(y *Integer) *Integer {
        // x * y == x * y
        // x * (-y) == -(x * y)
@@ -923,6 +1039,8 @@ func (x *Integer) Mul(y *Integer) *Integer {
 }
 
 
+// MulNat returns the product x * y, where y is a (unsigned) natural number.
+//
 func (x *Integer) MulNat(y Natural) *Integer {
        // x * y == x * y
        // (-x) * y == -(x * y)
@@ -930,13 +1048,16 @@ func (x *Integer) MulNat(y Natural) *Integer {
 }
 
 
+// Quo returns the quotient q = x / y for y != 0.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 // Quo and Rem implement T-division and modulus (like C99):
 //
 //   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
        // x / (-y) == -(x / y)
@@ -946,6 +1067,11 @@ func (x *Integer) Quo(y *Integer) *Integer {
 }
 
 
+// Rem returns the remainder r of the division x / y for y != 0,
+// with r = x - y*x.Quo(y). Unless r is zero, its sign corresponds
+// to the sign of x.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 func (x *Integer) Rem(y *Integer) *Integer {
        // x % y == x % y
        // x % (-y) == x % y
@@ -955,23 +1081,28 @@ func (x *Integer) Rem(y *Integer) *Integer {
 }
 
 
+// QuoRem returns the pair (x.Quo(y), x.Rem(y)) for y != 0.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 func (x *Integer) QuoRem(y *Integer) (*Integer, *Integer) {
        q, r := x.mant.DivMod(y.mant);
        return MakeInt(x.sign != y.sign, q), MakeInt(x.sign, r);
 }
 
 
+// Div returns the quotient q = x / y for y != 0.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 // Div and Mod implement Euclidian division and modulus:
 //
-//   d = x.Div(y)
-//   m = x.Mod(y) with: 0 <= m < |d| and: y = x*d + m
+//   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.
+//  ACM press.)
 //
-// ( 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 {
        q, r := x.QuoRem(y);
        if r.IsNeg() {
@@ -985,6 +1116,10 @@ func (x *Integer) Div(y *Integer) *Integer {
 }
 
 
+// Mod returns the modulus r of the division x / y for y != 0,
+// with r = x - y*x.Div(y). r is always positive.
+// If y == 0, a division-by-zero run-time error occurs.
+//
 func (x *Integer) Mod(y *Integer) *Integer {
        r := x.Rem(y);
        if r.IsNeg() {
@@ -998,6 +1133,8 @@ func (x *Integer) Mod(y *Integer) *Integer {
 }
 
 
+// DivMod returns the pair (x.Div(y), x.Mod(y)).
+//
 func (x *Integer) DivMod(y *Integer) (*Integer, *Integer) {
        q, r := x.QuoRem(y);
        if r.IsNeg() {
@@ -1013,53 +1150,73 @@ func (x *Integer) DivMod(y *Integer) (*Integer, *Integer) {
 }
 
 
+// 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.
+// Implementation restriction: Shl is not yet implemented for negative x.
+//
 func (x *Integer) Shr(s uint) *Integer {
        z := MakeInt(x.sign, x.mant.Shr(s));
        if x.IsNeg() {
-               panic("UNIMPLEMENTED Integer.Shr() of negative values");
+               panic("UNIMPLEMENTED Integer.Shr of negative values");
        }
        return z;
 }
 
 
+// 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 {
        var z *Integer;
        if !x.sign && !y.sign {
                z = MakeInt(false, x.mant.And(y.mant));
        } else {
-               panic("UNIMPLEMENTED Integer.And() of negative values");
+               panic("UNIMPLEMENTED Integer.And of negative values");
        }
        return z;
 }
 
 
+// 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 {
        var z *Integer;
        if !x.sign && !y.sign {
                z = MakeInt(false, x.mant.Or(y.mant));
        } else {
-               panic("UNIMPLEMENTED Integer.Or() of negative values");
+               panic("UNIMPLEMENTED Integer.Or of negative values");
        }
        return z;
 }
 
 
+// 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 {
        var z *Integer;
        if !x.sign && !y.sign {
                z = MakeInt(false, x.mant.Xor(y.mant));
        } else {
-               panic("UNIMPLEMENTED Integer.Xor() of negative values");
+               panic("UNIMPLEMENTED Integer.Xor of negative values");
        }
        return z;
 }
 
 
+// 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 *Integer) Cmp(y *Integer) int {
        // x cmp y == x cmp y
        // x cmp (-y) == x
@@ -1079,6 +1236,8 @@ func (x *Integer) Cmp(y *Integer) int {
 }
 
 
+// ToString converts x to a string for a given base, with 2 <= base <= 16.
+//
 func (x *Integer) ToString(base uint) string {
        if x.mant.IsZero() {
                return "0";
@@ -1091,18 +1250,33 @@ func (x *Integer) ToString(base uint) string {
 }
 
 
+// String converts x to its decimal string representation.
+// (x.String is the same as x.ToString(10)).
+//
 func (x *Integer) 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 *Integer) Format(h fmt.Formatter, c int) {
        fmt.Fprintf(h, "%s", x.ToString(fmtbase(c)));
 }
 
 
-// Determines base (octal, decimal, hexadecimal) if base == 0.
-// Returns the number and base.
+// IntFromString returns the integer corresponding to the
+// longest possible prefix of s representing an integer in a
+// given conversion base.
+//
+// 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.
+//
 func IntFromString(s string, base uint, slen *int) (*Integer, uint) {
        // get sign, if any
        sign := false;
@@ -1126,14 +1300,16 @@ func IntFromString(s string, base uint, slen *int) (*Integer, uint) {
 // ----------------------------------------------------------------------------
 // Rational numbers
 
+// Rational represents a quotient a/b of arbitrary precision.
+//
 type Rational struct {
        a *Integer;  // numerator
        b Natural;  // denominator
 }
 
 
-// Creation
-
+// 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 {
@@ -1144,6 +1320,10 @@ func MakeRat(a *Integer, b Natural) *Rational {
 }
 
 
+// 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.
+//
 func Rat(a0 int, b0 int) *Rational {
        a, b := Int(a0), Int(b0);
        if b.sign {
@@ -1155,21 +1335,30 @@ func Rat(a0 int, b0 int) *Rational {
 
 // 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;
 }
@@ -1177,26 +1366,37 @@ func (x *Rational) IsInt() bool {
 
 // 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);
@@ -1207,11 +1407,20 @@ func (x *Rational) Quo(y *Rational) *Rational {
 }
 
 
+// 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 "numerator/denominator".
+//
 func (x *Rational) ToString(base uint) string {
        s := x.a.ToString(base);
        if !x.IsInt() {
@@ -1221,18 +1430,33 @@ func (x *Rational) ToString(base uint) string {
 }
 
 
+// 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.Formatter, c int) {
        fmt.Fprintf(h, "%s", x.ToString(fmtbase(c)));
 }
 
 
-// Determines base (octal, decimal, hexadecimal) if base == 0.
-// Returns the number and base of the nominator.
+// RatFromString returns the rational number corresponding to the
+// longest possible prefix of s representing a rational number in a
+// given conversion base.
+//
+// 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.
+//
 func RatFromString(s string, base uint, slen *int) (*Rational, uint) {
        // read nominator
        var alen, blen int;