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 { ...@@ -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) { func Shl1(x, c Digit, s uint) (Digit, Digit) {
assert(s <= LogB); assert(s <= LogB);
return x >> (LogB - s), x << s & M | c return x >> (LogB - s), x << s & M | c
...@@ -490,7 +522,7 @@ func (x *Natural) Cmp(y *Natural) int { ...@@ -490,7 +522,7 @@ func (x *Natural) Cmp(y *Natural) int {
func Log1(x Digit) int { func Log1(x Digit) int {
n := -1; n := -1;
for x != 0 { x >>= 1; n++; } for x != 0 { x = x >> 1; n++; } // BUG >>= broken for uint64
return n; return n;
} }
...@@ -624,6 +656,15 @@ export func Fact(n Digit) *Natural { ...@@ -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 { func HexValue(ch byte) Digit {
d := Digit(1 << LogH); d := Digit(1 << LogH);
switch { switch {
...@@ -650,6 +691,23 @@ export func NatFromString(s string, base Digit) *Natural { ...@@ -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 // Integer numbers
...@@ -717,6 +775,18 @@ func (x *Integer) Mul(y *Integer) *Integer { ...@@ -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 { func (x *Integer) Div(y *Integer) *Integer {
panic("UNIMPLEMENTED"); panic("UNIMPLEMENTED");
return nil; return nil;
...@@ -765,29 +835,36 @@ export type Rational struct { ...@@ -765,29 +835,36 @@ export type Rational struct {
} }
func NewRat(a, b *Integer) *Rational { func (x *Rational) Normalize() *Rational {
// TODO normalize the rational f := x.a.mant.Gcd(x.b.mant);
return &Rational{a, b}; 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 { 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 { 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 { 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 { 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() { ...@@ -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() { func main() {
TestConv(); TestConv();
TestShift(); TestShift();
TestMul(); TestMul();
TestDiv(); TestDiv();
TestMod(); TestMod();
TestGcd();
TestPow();
TestPop();
print("PASSED\n"); 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