mirror of
https://github.com/golang/go
synced 2024-11-13 18:50:24 -07:00
- gcd, exponentiation, population count
- more rational numbers stuff - more tests R=r OCL=18295 CL=18295
This commit is contained in:
parent
16fd356679
commit
db27d309d1
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user