mirror of
https://github.com/golang/go.git
synced 2025-05-30 03:41:33 +00:00
- fixed a bug in Natural.And()
- removed some non-beneficial factorization and reduced number of array slices per operations significantly - reduced line count - benchhil benchmark time reduced by ~2% R=r DELTA=313 (106 added, 163 deleted, 44 changed) OCL=21473 CL=21497
This commit is contained in:
parent
4d23030859
commit
ab0d2582b4
@ -100,7 +100,7 @@ export func Dump(x *[]Digit) {
|
|||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Raw operations on sequences of digits
|
// Natural numbers
|
||||||
//
|
//
|
||||||
// Naming conventions
|
// Naming conventions
|
||||||
//
|
//
|
||||||
@ -110,170 +110,6 @@ export func Dump(x *[]Digit) {
|
|||||||
// n, m len(x), len(y)
|
// n, m len(x), len(y)
|
||||||
|
|
||||||
|
|
||||||
func Add1(z, x *[]Digit, c Digit) Digit {
|
|
||||||
n := len(x);
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
t := c + x[i];
|
|
||||||
c, z[i] = t>>W, t&M
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Add(z, x, y *[]Digit) Digit {
|
|
||||||
var c Digit;
|
|
||||||
n := len(x);
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
t := c + x[i] + y[i];
|
|
||||||
c, z[i] = t>>W, t&M
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Sub1(z, x *[]Digit, c Digit) Digit {
|
|
||||||
n := len(x);
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
t := c + x[i];
|
|
||||||
c, z[i] = Digit(int64(t)>>W), t&M; // requires arithmetic shift!
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Sub(z, x, y *[]Digit) Digit {
|
|
||||||
var c Digit;
|
|
||||||
n := len(x);
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
t := c + x[i] - y[i];
|
|
||||||
c, z[i] = Digit(int64(t)>>W), t&M; // requires arithmetic shift!
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Returns c = x*y div B, z = x*y mod B.
|
|
||||||
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.
|
|
||||||
|
|
||||||
// This code also works for non-even bit widths W
|
|
||||||
// which is why there are separate constants below
|
|
||||||
// for half-digits.
|
|
||||||
const W2 = (W + 1)/2;
|
|
||||||
const DW = W2*2 - W; // 0 or 1
|
|
||||||
const B2 = 1<<W2;
|
|
||||||
const M2 = B2 - 1;
|
|
||||||
|
|
||||||
// split x and y into sub-digits
|
|
||||||
// x = (x1*B2 + x0)
|
|
||||||
// y = (y1*B2 + y0)
|
|
||||||
x1, x0 := x>>W2, x&M2;
|
|
||||||
y1, y0 := y>>W2, y&M2;
|
|
||||||
|
|
||||||
// x*y = t2*B2^2 + t1*B2 + t0
|
|
||||||
t0 := x0*y0;
|
|
||||||
t1 := x1*y0 + x0*y1;
|
|
||||||
t2 := x1*y1;
|
|
||||||
|
|
||||||
// compute the result digits but avoid overflow
|
|
||||||
// z = z1*B + z0 = x*y
|
|
||||||
z0 := (t1<<W2 + t0)&M;
|
|
||||||
z1 := t2<<DW + (t1 + t0>>W2)>>(W-W2);
|
|
||||||
|
|
||||||
return z1, z0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Mul(z, x, y *[]Digit) {
|
|
||||||
n := len(x);
|
|
||||||
m := len(y);
|
|
||||||
for j := 0; j < m; j++ {
|
|
||||||
d := y[j];
|
|
||||||
if d != 0 {
|
|
||||||
c := Digit(0);
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
// z[i+j] += c + x[i]*d;
|
|
||||||
z1, z0 := Mul11(x[i], d);
|
|
||||||
t := c + z[i+j] + z0;
|
|
||||||
c, z[i+j] = t>>W, t&M;
|
|
||||||
c += z1;
|
|
||||||
}
|
|
||||||
z[n+j] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Shl(z, x *[]Digit, s uint) Digit {
|
|
||||||
assert(s <= W);
|
|
||||||
n := len(x);
|
|
||||||
var c Digit;
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
c, z[i] = x[i] >> (W-s), x[i] << s & M | c;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Shr(z, x *[]Digit, s uint) Digit {
|
|
||||||
assert(s <= W);
|
|
||||||
n := len(x);
|
|
||||||
var c Digit;
|
|
||||||
for i := n - 1; i >= 0; i-- {
|
|
||||||
c, z[i] = x[i] << (W-s) & M, x[i] >> s | c;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func And1(z, x *[]Digit, y Digit) {
|
|
||||||
for i := len(x) - 1; i >= 0; i-- {
|
|
||||||
z[i] = x[i] & y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func And(z, x, y *[]Digit) {
|
|
||||||
for i := len(x) - 1; i >= 0; i-- {
|
|
||||||
z[i] = x[i] & y[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Or1(z, x *[]Digit, y Digit) {
|
|
||||||
for i := len(x) - 1; i >= 0; i-- {
|
|
||||||
z[i] = x[i] | y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Or(z, x, y *[]Digit) {
|
|
||||||
for i := len(x) - 1; i >= 0; i-- {
|
|
||||||
z[i] = x[i] | y[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Xor1(z, x *[]Digit, y Digit) {
|
|
||||||
for i := len(x) - 1; i >= 0; i-- {
|
|
||||||
z[i] = x[i] ^ y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Xor(z, x, y *[]Digit) {
|
|
||||||
for i := len(x) - 1; i >= 0; i-- {
|
|
||||||
z[i] = x[i] ^ y[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Natural numbers
|
|
||||||
|
|
||||||
|
|
||||||
export type Natural []Digit;
|
export type Natural []Digit;
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -328,12 +164,26 @@ func (x *Natural) Add(y *Natural) *Natural {
|
|||||||
if n < m {
|
if n < m {
|
||||||
return y.Add(x);
|
return y.Add(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c := Digit(0);
|
||||||
z := new(Natural, n + 1);
|
z := new(Natural, n + 1);
|
||||||
c := Add(z[0 : m], x[0 : m], y);
|
i := 0;
|
||||||
z[n] = Add1(z[m : n], x[m : n], c);
|
for i < m {
|
||||||
|
t := c + x[i] + y[i];
|
||||||
|
c, z[i] = t>>W, t&M;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
for i < n {
|
||||||
|
t := c + x[i];
|
||||||
|
c, z[i] = t>>W, t&M;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if c != 0 {
|
||||||
|
z[i] = c;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
return Normalize(z);
|
return z[0 : i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -343,14 +193,59 @@ func (x *Natural) Sub(y *Natural) *Natural {
|
|||||||
if n < m {
|
if n < m {
|
||||||
panic("underflow")
|
panic("underflow")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c := Digit(0);
|
||||||
z := new(Natural, n);
|
z := new(Natural, n);
|
||||||
c := Sub(z[0 : m], x[0 : m], y);
|
i := 0;
|
||||||
if Sub1(z[m : n], x[m : n], c) != 0 {
|
for i < m {
|
||||||
panic("underflow");
|
t := c + x[i] - y[i];
|
||||||
|
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!
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
for i > 0 && z[i - 1] == 0 { // normalize
|
||||||
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Normalize(z);
|
return z[0 : i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns c = x*y div B, z = x*y mod B.
|
||||||
|
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.
|
||||||
|
|
||||||
|
// This code also works for non-even bit widths W
|
||||||
|
// which is why there are separate constants below
|
||||||
|
// for half-digits.
|
||||||
|
const W2 = (W + 1)/2;
|
||||||
|
const DW = W2*2 - W; // 0 or 1
|
||||||
|
const B2 = 1<<W2;
|
||||||
|
const M2 = B2 - 1;
|
||||||
|
|
||||||
|
// split x and y into sub-digits
|
||||||
|
// x = (x1*B2 + x0)
|
||||||
|
// y = (y1*B2 + y0)
|
||||||
|
x1, x0 := x>>W2, x&M2;
|
||||||
|
y1, y0 := y>>W2, y&M2;
|
||||||
|
|
||||||
|
// x*y = t2*B2^2 + t1*B2 + t0
|
||||||
|
t0 := x0*y0;
|
||||||
|
t1 := x1*y0 + x0*y1;
|
||||||
|
t2 := x1*y1;
|
||||||
|
|
||||||
|
// compute the result digits but avoid overflow
|
||||||
|
// z = z1*B + z0 = x*y
|
||||||
|
z0 := (t1<<W2 + t0)&M;
|
||||||
|
z1 := t2<<DW + (t1 + t0>>W2)>>(W-W2);
|
||||||
|
|
||||||
|
return z1, z0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -359,7 +254,20 @@ func (x *Natural) Mul(y *Natural) *Natural {
|
|||||||
m := len(y);
|
m := len(y);
|
||||||
|
|
||||||
z := new(Natural, n + m);
|
z := new(Natural, n + m);
|
||||||
Mul(z, x, y);
|
for j := 0; j < m; j++ {
|
||||||
|
d := y[j];
|
||||||
|
if d != 0 {
|
||||||
|
c := Digit(0);
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
// z[i+j] += c + x[i]*d;
|
||||||
|
z1, z0 := Mul11(x[i], d);
|
||||||
|
t := c + z[i+j] + z0;
|
||||||
|
c, z[i+j] = t>>W, t&M;
|
||||||
|
c += z1;
|
||||||
|
}
|
||||||
|
z[n+j] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Normalize(z);
|
return Normalize(z);
|
||||||
}
|
}
|
||||||
@ -403,7 +311,7 @@ func Pack(x *[]Digit2) *Natural {
|
|||||||
|
|
||||||
func Mul1(z, x *[]Digit2, y Digit2) Digit2 {
|
func Mul1(z, x *[]Digit2, y Digit2) Digit2 {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
var c Digit;
|
c := Digit(0);
|
||||||
f := Digit(y);
|
f := Digit(y);
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
t := c + Digit(x[i])*f;
|
t := c + Digit(x[i])*f;
|
||||||
@ -415,7 +323,7 @@ func Mul1(z, x *[]Digit2, y Digit2) Digit2 {
|
|||||||
|
|
||||||
func Div1(z, x *[]Digit2, y Digit2) Digit2 {
|
func Div1(z, x *[]Digit2, y Digit2) Digit2 {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
var c Digit;
|
c := Digit(0);
|
||||||
d := Digit(y);
|
d := Digit(y);
|
||||||
for i := n-1; i >= 0; i-- {
|
for i := n-1; i >= 0; i-- {
|
||||||
t := c*B2 + Digit(x[i]);
|
t := c*B2 + Digit(x[i]);
|
||||||
@ -550,6 +458,17 @@ func (x *Natural) DivMod(y *Natural) (*Natural, *Natural) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func Shl(z, x *[]Digit, s uint) Digit {
|
||||||
|
assert(s <= W);
|
||||||
|
n := len(x);
|
||||||
|
c := Digit(0);
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
c, z[i] = x[i] >> (W-s), x[i] << s & M | c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (x *Natural) Shl(s uint) *Natural {
|
func (x *Natural) Shl(s uint) *Natural {
|
||||||
n := uint(len(x));
|
n := uint(len(x));
|
||||||
m := n + s/W;
|
m := n + s/W;
|
||||||
@ -561,6 +480,17 @@ func (x *Natural) Shl(s uint) *Natural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func Shr(z, x *[]Digit, s uint) Digit {
|
||||||
|
assert(s <= W);
|
||||||
|
n := len(x);
|
||||||
|
c := Digit(0);
|
||||||
|
for i := n - 1; i >= 0; i-- {
|
||||||
|
c, z[i] = x[i] << (W-s) & M, x[i] >> s | c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (x *Natural) Shr(s uint) *Natural {
|
func (x *Natural) Shr(s uint) *Natural {
|
||||||
n := uint(len(x));
|
n := uint(len(x));
|
||||||
m := n - s/W;
|
m := n - s/W;
|
||||||
@ -582,14 +512,23 @@ func (x *Natural) And(y *Natural) *Natural {
|
|||||||
return y.And(x);
|
return y.And(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
z := new(Natural, n);
|
z := new(Natural, m);
|
||||||
And(z[0 : m], x[0 : m], y);
|
for i := 0; i < m; i++ {
|
||||||
Or1(z[m : n], x[m : n], 0);
|
z[i] = x[i] & y[i];
|
||||||
|
}
|
||||||
|
// upper bits are 0
|
||||||
|
|
||||||
return Normalize(z);
|
return Normalize(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func Copy(z, x *[]Digit) {
|
||||||
|
for i, e := range x {
|
||||||
|
z[i] = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (x *Natural) Or(y *Natural) *Natural {
|
func (x *Natural) Or(y *Natural) *Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
@ -598,10 +537,12 @@ func (x *Natural) Or(y *Natural) *Natural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
z := new(Natural, n);
|
z := new(Natural, n);
|
||||||
Or(z[0 : m], x[0 : m], y);
|
for i := 0; i < m; i++ {
|
||||||
Or1(z[m : n], x[m : n], 0);
|
z[i] = x[i] | y[i];
|
||||||
|
}
|
||||||
|
Copy(z[m : n], x[m : n]);
|
||||||
|
|
||||||
return Normalize(z);
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -613,8 +554,10 @@ func (x *Natural) Xor(y *Natural) *Natural {
|
|||||||
}
|
}
|
||||||
|
|
||||||
z := new(Natural, n);
|
z := new(Natural, n);
|
||||||
Xor(z[0 : m], x[0 : m], y);
|
for i := 0; i < m; i++ {
|
||||||
Or1(z[m : n], x[m : n], 0);
|
z[i] = x[i] ^ y[i];
|
||||||
|
}
|
||||||
|
Copy(z[m : n], x[m : n]);
|
||||||
|
|
||||||
return Normalize(z);
|
return Normalize(z);
|
||||||
}
|
}
|
||||||
@ -688,7 +631,7 @@ func (x *Natural) ToString(base uint) string {
|
|||||||
|
|
||||||
// don't destroy x
|
// don't destroy x
|
||||||
t := new(Natural, len(x));
|
t := new(Natural, len(x));
|
||||||
Or1(t, x, 0); // copy
|
Copy(t, x);
|
||||||
|
|
||||||
// convert
|
// convert
|
||||||
i := n;
|
i := n;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user