Commit db27d309 authored by Robert Griesemer's avatar Robert Griesemer

- gcd, exponentiation, population count

- more rational numbers stuff
- more tests

R=r
OCL=18295
CL=18295
parent 16fd3566
......@@ -262,6 +262,38 @@ func (x *Natural) Mul(y *Natural) *Natural {
}
func Pop1(x Digit) uint {
n := uint(0);
for x != 0 {
x &= x-1;
n++;
}
return n;
}
func (x *Natural) Pop() uint {
n := uint(0);
for i := len(x) - 1; i >= 0; i-- {
n += Pop1(x[i]);
}
return n;
}
func (x *Natural) Pow(n uint) *Natural {
z := Nat(1);
for n > 0 {
// z * x^n == x^n0
if n&1 == 1 {
z = z.Mul(x);
}
x, n = x.Mul(x), n/2;
}
return z;
}
func Shl1(x, c Digit, s uint) (Digit, Digit) {
assert(s <= LogB);
return x >> (LogB - s), x << s & M | c
......@@ -490,7 +522,7 @@ func (x *Natural) Cmp(y *Natural) int {
func Log1(x Digit) int {
n := -1;
for x != 0 { x >>= 1; n++; }
for x != 0 { x = x >> 1; n++; } // BUG >>= broken for uint64
return n;
}
......@@ -624,6 +656,15 @@ export func Fact(n Digit) *Natural {
}
func (x *Natural) Gcd(y *Natural) *Natural {
// Euclidean algorithm.
for !y.IsZero() {
x, y = y, x.Mod(y);
}
return x;
}
func HexValue(ch byte) Digit {
d := Digit(1 << LogH);
switch {
......@@ -650,6 +691,23 @@ export func NatFromString(s string, base Digit) *Natural {
}
// ----------------------------------------------------------------------------
// Algorithms
export type T interface {
IsZero() bool;
Mod(y T) bool;
}
export func Gcd(x, y T) T {
// Euclidean algorithm.
for !y.IsZero() {
x, y = y, x.Mod(y);
}
return x;
}
// ----------------------------------------------------------------------------
// Integer numbers
......@@ -717,6 +775,18 @@ func (x *Integer) Mul(y *Integer) *Integer {
}
func (x *Integer) Quo(y *Integer) *Integer {
panic("UNIMPLEMENTED");
return nil;
}
func (x *Integer) Rem(y *Integer) *Integer {
panic("UNIMPLEMENTED");
return nil;
}
func (x *Integer) Div(y *Integer) *Integer {
panic("UNIMPLEMENTED");
return nil;
......@@ -765,29 +835,36 @@ export type Rational struct {
}
func NewRat(a, b *Integer) *Rational {
// TODO normalize the rational
return &Rational{a, b};
func (x *Rational) Normalize() *Rational {
f := x.a.mant.Gcd(x.b.mant);
x.a.mant = x.a.mant.Div(f);
x.b.mant = x.b.mant.Div(f);
return x;
}
func Rat(a, b *Integer) *Rational {
return (&Rational{a, b}).Normalize();
}
func (x *Rational) Add(y *Rational) *Rational {
return NewRat((x.a.Mul(y.b)).Add(x.b.Mul(y.a)), x.b.Mul(y.b));
return Rat((x.a.Mul(y.b)).Add(x.b.Mul(y.a)), x.b.Mul(y.b));
}
func (x *Rational) Sub(y *Rational) *Rational {
return NewRat((x.a.Mul(y.b)).Sub(x.b.Mul(y.a)), x.b.Mul(y.b));
return Rat((x.a.Mul(y.b)).Sub(x.b.Mul(y.a)), x.b.Mul(y.b));
}
func (x *Rational) Mul(y *Rational) *Rational {
return NewRat(x.a.Mul(y.a), x.b.Mul(y.b));
return Rat(x.a.Mul(y.a), x.b.Mul(y.b));
}
func (x *Rational) Div(y *Rational) *Rational {
return NewRat(x.a.Mul(y.b), x.b.Mul(y.a));
return Rat(x.a.Mul(y.b), x.b.Mul(y.a));
}
......
......@@ -129,11 +129,47 @@ func TestMod() {
}
func TestGcd() {
test_msg = "TestGcdA";
f := Big.Nat(99991);
TEST_EQ(0, b.Mul(f).Gcd(c.Mul(f)), Big.MulRange(1, 20).Mul(f));
}
func TestPow() {
test_msg = "TestPowA";
TEST_EQ(0, Big.Nat(2).Pow(0), Big.Nat(1));
test_msg = "TestPowB";
for i := uint(0); i < 100; i++ {
TEST_EQ(i, Big.Nat(2).Pow(i), Big.Nat(1).Shl(i));
}
}
func TestPop() {
test_msg = "TestPopA";
TEST(0, Big.Nat(0).Pop() == 0);
TEST(1, Big.Nat(1).Pop() == 1);
TEST(2, Big.Nat(10).Pop() == 2);
TEST(3, Big.Nat(30).Pop() == 4);
TEST(4, Big.Nat(0x1248f).Shl(33).Pop() == 8);
test_msg = "TestPopB";
for i := uint(0); i < 100; i++ {
TEST(i, Big.Nat(1).Shl(i).Sub(Big.Nat(1)).Pop() == i);
}
}
func main() {
TestConv();
TestShift();
TestMul();
TestDiv();
TestMod();
TestGcd();
TestPow();
TestPop();
print("PASSED\n");
}
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