Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
364a8520
Commit
364a8520
authored
Jan 15, 2009
by
Robert Griesemer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- lowercase non-exported functions in bignum
R=r DELTA=117 (1 added, 0 deleted, 116 changed) OCL=22764 CL=22863
parent
aa126447
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
97 additions
and
96 deletions
+97
-96
src/lib/bignum.go
src/lib/bignum.go
+97
-96
No files found.
src/lib/bignum.go
View file @
364a8520
...
@@ -11,7 +11,8 @@ package bignum
...
@@ -11,7 +11,8 @@ package bignum
// - Integer signed integer numbers
// - Integer signed integer numbers
// - Rational rational numbers
// - Rational rational numbers
import
Fmt
"fmt"
import
"fmt"
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Internal representation
// Internal representation
...
@@ -51,27 +52,27 @@ import Fmt "fmt"
...
@@ -51,27 +52,27 @@ import Fmt "fmt"
// results are packed again. For faster unpacking/packing, the base size
// results are packed again. For faster unpacking/packing, the base size
// in bits must be even.
// in bits must be even.
type
(
export
type
(
Digit
uint64
;
Digit
uint64
;
Digit2
uint32
;
// half-digits for division
Digit2
uint32
;
// half-digits for division
)
)
const
LogW
=
64
;
const
_
LogW
=
64
;
const
LogH
=
4
;
// bits for a hex digit (= "small" number)
const
_
LogH
=
4
;
// bits for a hex digit (= "small" number)
const
LogB
=
LogW
-
LogH
;
// largest bit-width available
const
_LogB
=
_LogW
-
_
LogH
;
// largest bit-width available
const
(
const
(
// half-digits
// half-digits
W2
=
LogB
/
2
;
// width
_W2
=
_
LogB
/
2
;
// width
B2
=
1
<<
W2
;
// base
_B2
=
1
<<
_
W2
;
// base
M2
=
B2
-
1
;
// mask
_M2
=
_
B2
-
1
;
// mask
// full digits
// full digits
W
=
W2
*
2
;
// width
_W
=
_
W2
*
2
;
// width
B
=
1
<<
W
;
// base
_B
=
1
<<
_
W
;
// base
M
=
B
-
1
;
// mask
_M
=
_
B
-
1
;
// mask
)
)
...
@@ -86,7 +87,7 @@ func assert(p bool) {
...
@@ -86,7 +87,7 @@ func assert(p bool) {
func
IsSmall
(
x
Digit
)
bool
{
func
IsSmall
(
x
Digit
)
bool
{
return
x
<
1
<<
LogH
;
return
x
<
1
<<
_
LogH
;
}
}
...
@@ -129,7 +130,7 @@ export func Nat(x uint) Natural {
...
@@ -129,7 +130,7 @@ export func Nat(x uint) Natural {
case
2
:
return
NatTwo
;
case
2
:
return
NatTwo
;
case
10
:
return
NatTen
;
case
10
:
return
NatTen
;
}
}
assert
(
Digit
(
x
)
<
B
);
assert
(
Digit
(
x
)
<
_
B
);
return
Natural
{
Digit
(
x
)};
return
Natural
{
Digit
(
x
)};
}
}
...
@@ -148,7 +149,7 @@ func (x Natural) IsZero() bool {
...
@@ -148,7 +149,7 @@ func (x Natural) IsZero() bool {
// Operations
// Operations
func
N
ormalize
(
x
Natural
)
Natural
{
func
n
ormalize
(
x
Natural
)
Natural
{
n
:=
len
(
x
);
n
:=
len
(
x
);
for
n
>
0
&&
x
[
n
-
1
]
==
0
{
n
--
}
for
n
>
0
&&
x
[
n
-
1
]
==
0
{
n
--
}
if
n
<
len
(
x
)
{
if
n
<
len
(
x
)
{
...
@@ -170,12 +171,12 @@ func (x Natural) Add(y Natural) Natural {
...
@@ -170,12 +171,12 @@ func (x Natural) Add(y Natural) Natural {
i
:=
0
;
i
:=
0
;
for
i
<
m
{
for
i
<
m
{
t
:=
c
+
x
[
i
]
+
y
[
i
];
t
:=
c
+
x
[
i
]
+
y
[
i
];
c
,
z
[
i
]
=
t
>>
W
,
t
&
M
;
c
,
z
[
i
]
=
t
>>
_W
,
t
&
_
M
;
i
++
;
i
++
;
}
}
for
i
<
n
{
for
i
<
n
{
t
:=
c
+
x
[
i
];
t
:=
c
+
x
[
i
];
c
,
z
[
i
]
=
t
>>
W
,
t
&
M
;
c
,
z
[
i
]
=
t
>>
_W
,
t
&
_
M
;
i
++
;
i
++
;
}
}
if
c
!=
0
{
if
c
!=
0
{
...
@@ -199,12 +200,12 @@ func (x Natural) Sub(y Natural) Natural {
...
@@ -199,12 +200,12 @@ func (x Natural) Sub(y Natural) Natural {
i
:=
0
;
i
:=
0
;
for
i
<
m
{
for
i
<
m
{
t
:=
c
+
x
[
i
]
-
y
[
i
];
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
++
;
i
++
;
}
}
for
i
<
n
{
for
i
<
n
{
t
:=
c
+
x
[
i
];
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
++
;
i
++
;
}
}
for
i
>
0
&&
z
[
i
-
1
]
==
0
{
// normalize
for
i
>
0
&&
z
[
i
-
1
]
==
0
{
// normalize
...
@@ -216,7 +217,7 @@ func (x Natural) Sub(y Natural) Natural {
...
@@ -216,7 +217,7 @@ func (x Natural) Sub(y Natural) Natural {
// Returns c = x*y div B, z = x*y mod B.
// Returns c = x*y div B, z = x*y mod B.
func
M
ul11
(
x
,
y
Digit
)
(
Digit
,
Digit
)
{
func
m
ul11
(
x
,
y
Digit
)
(
Digit
,
Digit
)
{
// Split x and y into 2 sub-digits each,
// Split x and y into 2 sub-digits each,
// multiply the digits separately while avoiding overflow,
// multiply the digits separately while avoiding overflow,
// and return the product as two separate digits.
// and return the product as two separate digits.
...
@@ -224,10 +225,10 @@ func Mul11(x, y Digit) (Digit, Digit) {
...
@@ -224,10 +225,10 @@ func Mul11(x, y Digit) (Digit, Digit) {
// This code also works for non-even bit widths W
// This code also works for non-even bit widths W
// which is why there are separate constants below
// which is why there are separate constants below
// for half-digits.
// for half-digits.
const
W2
=
(
W
+
1
)
/
2
;
const
W2
=
(
_
W
+
1
)
/
2
;
const
DW
=
W2
*
2
-
W
;
// 0 or 1
const
DW
=
W2
*
2
-
_
W
;
// 0 or 1
const
B2
=
1
<<
W2
;
const
B2
=
1
<<
W2
;
const
M2
=
B2
-
1
;
const
M2
=
_
B2
-
1
;
// split x and y into sub-digits
// split x and y into sub-digits
// x = (x1*B2 + x0)
// x = (x1*B2 + x0)
...
@@ -242,8 +243,8 @@ func Mul11(x, y Digit) (Digit, Digit) {
...
@@ -242,8 +243,8 @@ func Mul11(x, y Digit) (Digit, Digit) {
// compute the result digits but avoid overflow
// compute the result digits but avoid overflow
// z = z1*B + z0 = x*y
// z = z1*B + z0 = x*y
z0
:=
(
t1
<<
W2
+
t0
)
&
M
;
z0
:=
(
t1
<<
W2
+
t0
)
&
_
M
;
z1
:=
t2
<<
DW
+
(
t1
+
t0
>>
W2
)
>>
(
W
-
W2
);
z1
:=
t2
<<
DW
+
(
t1
+
t0
>>
W2
)
>>
(
_
W
-
W2
);
return
z1
,
z0
;
return
z1
,
z0
;
}
}
...
@@ -260,16 +261,16 @@ func (x Natural) Mul(y Natural) Natural {
...
@@ -260,16 +261,16 @@ func (x Natural) Mul(y Natural) Natural {
c
:=
Digit
(
0
);
c
:=
Digit
(
0
);
for
i
:=
0
;
i
<
n
;
i
++
{
for
i
:=
0
;
i
<
n
;
i
++
{
// z[i+j] += c + x[i]*d;
// z[i+j] += c + x[i]*d;
z1
,
z0
:=
M
ul11
(
x
[
i
],
d
);
z1
,
z0
:=
m
ul11
(
x
[
i
],
d
);
t
:=
c
+
z
[
i
+
j
]
+
z0
;
t
:=
c
+
z
[
i
+
j
]
+
z0
;
c
,
z
[
i
+
j
]
=
t
>>
W
,
t
&
M
;
c
,
z
[
i
+
j
]
=
t
>>
_W
,
t
&
_
M
;
c
+=
z1
;
c
+=
z1
;
}
}
z
[
n
+
j
]
=
c
;
z
[
n
+
j
]
=
c
;
}
}
}
}
return
N
ormalize
(
z
);
return
n
ormalize
(
z
);
}
}
...
@@ -278,13 +279,13 @@ func (x Natural) Mul(y Natural) Natural {
...
@@ -278,13 +279,13 @@ func (x Natural) Mul(y Natural) Natural {
// 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.
// DivMod, and then pack the results again.
func
U
npack
(
x
Natural
)
[]
Digit2
{
func
u
npack
(
x
Natural
)
[]
Digit2
{
n
:=
len
(
x
);
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
++
{
for
i
:=
0
;
i
<
n
;
i
++
{
t
:=
x
[
i
];
t
:=
x
[
i
];
z
[
i
*
2
]
=
Digit2
(
t
&
M2
);
z
[
i
*
2
]
=
Digit2
(
t
&
_
M2
);
z
[
i
*
2
+
1
]
=
Digit2
(
t
>>
W2
&
M2
);
z
[
i
*
2
+
1
]
=
Digit2
(
t
>>
_W2
&
_
M2
);
}
}
// normalize result
// normalize result
...
@@ -294,7 +295,7 @@ func Unpack(x Natural) []Digit2 {
...
@@ -294,7 +295,7 @@ func Unpack(x Natural) []Digit2 {
}
}
func
P
ack
(
x
[]
Digit2
)
Natural
{
func
p
ack
(
x
[]
Digit2
)
Natural
{
n
:=
(
len
(
x
)
+
1
)
/
2
;
n
:=
(
len
(
x
)
+
1
)
/
2
;
z
:=
make
(
Natural
,
n
);
z
:=
make
(
Natural
,
n
);
if
len
(
x
)
&
1
==
1
{
if
len
(
x
)
&
1
==
1
{
...
@@ -303,37 +304,37 @@ func Pack(x []Digit2) Natural {
...
@@ -303,37 +304,37 @@ func Pack(x []Digit2) Natural {
z
[
n
]
=
Digit
(
x
[
n
*
2
]);
z
[
n
]
=
Digit
(
x
[
n
*
2
]);
}
}
for
i
:=
0
;
i
<
n
;
i
++
{
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
N
ormalize
(
z
);
return
n
ormalize
(
z
);
}
}
func
M
ul1
(
z
,
x
[]
Digit2
,
y
Digit2
)
Digit2
{
func
m
ul1
(
z
,
x
[]
Digit2
,
y
Digit2
)
Digit2
{
n
:=
len
(
x
);
n
:=
len
(
x
);
c
:=
Digit
(
0
);
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
;
c
,
z
[
i
]
=
t
>>
W2
,
Digit2
(
t
&
M2
);
c
,
z
[
i
]
=
t
>>
_W2
,
Digit2
(
t
&
_
M2
);
}
}
return
Digit2
(
c
);
return
Digit2
(
c
);
}
}
func
D
iv1
(
z
,
x
[]
Digit2
,
y
Digit2
)
Digit2
{
func
d
iv1
(
z
,
x
[]
Digit2
,
y
Digit2
)
Digit2
{
n
:=
len
(
x
);
n
:=
len
(
x
);
c
:=
Digit
(
0
);
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
]);
c
,
z
[
i
]
=
t
%
d
,
Digit2
(
t
/
d
);
c
,
z
[
i
]
=
t
%
d
,
Digit2
(
t
/
d
);
}
}
return
Digit2
(
c
);
return
Digit2
(
c
);
}
}
//
DivM
od returns q and r with x = y*q + r and 0 <= r < y.
//
divm
od returns q and r with x = y*q + r and 0 <= r < y.
// x and y are destroyed in the process.
// x and y are destroyed in the process.
//
//
// The algorithm used here is based on 1). 2) describes the same algorithm
// The algorithm used here is based on 1). 2) describes the same algorithm
...
@@ -353,7 +354,7 @@ func Div1(z, x []Digit2, y Digit2) Digit2 {
...
@@ -353,7 +354,7 @@ func Div1(z, x []Digit2, y Digit2) Digit2 {
// minefield. "Software - Practice and Experience 24", (June 1994),
// minefield. "Software - Practice and Experience 24", (June 1994),
// 579-601. John Wiley & Sons, Ltd.
// 579-601. John Wiley & Sons, Ltd.
func
DivM
od
(
x
,
y
[]
Digit2
)
([]
Digit2
,
[]
Digit2
)
{
func
divm
od
(
x
,
y
[]
Digit2
)
([]
Digit2
,
[]
Digit2
)
{
n
:=
len
(
x
);
n
:=
len
(
x
);
m
:=
len
(
y
);
m
:=
len
(
y
);
if
m
==
0
{
if
m
==
0
{
...
@@ -366,7 +367,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
...
@@ -366,7 +367,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
if
m
==
1
{
if
m
==
1
{
// division by single digit
// division by single digit
// result is shifted left by 1 in place!
// result is shifted left by 1 in place!
x
[
0
]
=
D
iv1
(
x
[
1
:
n
+
1
],
x
[
0
:
n
],
y
[
0
]);
x
[
0
]
=
d
iv1
(
x
[
1
:
n
+
1
],
x
[
0
:
n
],
y
[
0
]);
}
else
if
m
>
n
{
}
else
if
m
>
n
{
// y > x => quotient = 0, remainder = x
// y > x => quotient = 0, remainder = x
...
@@ -381,15 +382,15 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
...
@@ -381,15 +382,15 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
// TODO Instead of multiplying, it would be sufficient to
// TODO Instead of multiplying, it would be sufficient to
// shift y such that the normalization condition is
// shift y such that the normalization condition is
// satisfied (as done in "Hacker's Delight").
// satisfied (as done in "Hacker's Delight").
f
:=
B2
/
(
Digit
(
y
[
m
-
1
])
+
1
);
f
:=
_
B2
/
(
Digit
(
y
[
m
-
1
])
+
1
);
if
f
!=
1
{
if
f
!=
1
{
M
ul1
(
x
,
x
,
Digit2
(
f
));
m
ul1
(
x
,
x
,
Digit2
(
f
));
M
ul1
(
y
,
y
,
Digit2
(
f
));
m
ul1
(
y
,
y
,
Digit2
(
f
));
}
}
assert
(
B2
/
2
<=
y
[
m
-
1
]
&&
y
[
m
-
1
]
<
B2
);
// incorrect scaling
assert
(
_B2
/
2
<=
y
[
m
-
1
]
&&
y
[
m
-
1
]
<
_
B2
);
// incorrect scaling
y1
,
y2
:=
Digit
(
y
[
m
-
1
]),
Digit
(
y
[
m
-
2
]);
y1
,
y2
:=
Digit
(
y
[
m
-
1
]),
Digit
(
y
[
m
-
2
]);
d2
:=
Digit
(
y1
)
<<
W2
+
Digit
(
y2
);
d2
:=
Digit
(
y1
)
<<
_
W2
+
Digit
(
y2
);
for
i
:=
n
-
m
;
i
>=
0
;
i
--
{
for
i
:=
n
-
m
;
i
>=
0
;
i
--
{
k
:=
i
+
m
;
k
:=
i
+
m
;
...
@@ -397,11 +398,11 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
...
@@ -397,11 +398,11 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
var
q
Digit
;
var
q
Digit
;
{
x0
,
x1
,
x2
:=
Digit
(
x
[
k
]),
Digit
(
x
[
k
-
1
]),
Digit
(
x
[
k
-
2
]);
{
x0
,
x1
,
x2
:=
Digit
(
x
[
k
]),
Digit
(
x
[
k
-
1
]),
Digit
(
x
[
k
-
2
]);
if
x0
!=
y1
{
if
x0
!=
y1
{
q
=
(
x0
<<
W2
+
x1
)
/
y1
;
q
=
(
x0
<<
_
W2
+
x1
)
/
y1
;
}
else
{
}
else
{
q
=
B2
-
1
;
q
=
_
B2
-
1
;
}
}
for
y2
*
q
>
(
x0
<<
W2
+
x1
-
y1
*
q
)
<<
W2
+
x2
{
for
y2
*
q
>
(
x0
<<
_W2
+
x1
-
y1
*
q
)
<<
_
W2
+
x2
{
q
--
q
--
}
}
}
}
...
@@ -410,7 +411,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
...
@@ -410,7 +411,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
c
:=
Digit
(
0
);
c
:=
Digit
(
0
);
for
j
:=
0
;
j
<
m
;
j
++
{
for
j
:=
0
;
j
<
m
;
j
++
{
t
:=
c
+
Digit
(
x
[
i
+
j
])
-
Digit
(
y
[
j
])
*
q
;
t
:=
c
+
Digit
(
x
[
i
+
j
])
-
Digit
(
y
[
j
])
*
q
;
c
,
x
[
i
+
j
]
=
Digit
(
int64
(
t
)
>>
W2
),
Digit2
(
t
&
M2
);
// requires arithmetic shift!
c
,
x
[
i
+
j
]
=
Digit
(
int64
(
t
)
>>
_W2
),
Digit2
(
t
&
_
M2
);
// requires arithmetic shift!
}
}
// correct if trial digit was too large
// correct if trial digit was too large
...
@@ -419,7 +420,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
...
@@ -419,7 +420,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
c
:=
Digit
(
0
);
c
:=
Digit
(
0
);
for
j
:=
0
;
j
<
m
;
j
++
{
for
j
:=
0
;
j
<
m
;
j
++
{
t
:=
c
+
Digit
(
x
[
i
+
j
])
+
Digit
(
y
[
j
]);
t
:=
c
+
Digit
(
x
[
i
+
j
])
+
Digit
(
y
[
j
]);
c
,
x
[
i
+
j
]
=
t
>>
W2
,
Digit2
(
t
&
M2
)
c
,
x
[
i
+
j
]
=
t
>>
_W2
,
Digit2
(
t
&
_
M2
)
}
}
assert
(
c
+
Digit
(
x
[
k
])
==
0
);
assert
(
c
+
Digit
(
x
[
k
])
==
0
);
// correct trial digit
// correct trial digit
...
@@ -431,7 +432,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
...
@@ -431,7 +432,7 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
// undo normalization for remainder
// undo normalization for remainder
if
f
!=
1
{
if
f
!=
1
{
c
:=
D
iv1
(
x
[
0
:
m
],
x
[
0
:
m
],
Digit2
(
f
));
c
:=
d
iv1
(
x
[
0
:
m
],
x
[
0
:
m
],
Digit2
(
f
));
assert
(
c
==
0
);
assert
(
c
==
0
);
}
}
}
}
...
@@ -441,29 +442,29 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
...
@@ -441,29 +442,29 @@ func DivMod(x, y []Digit2) ([]Digit2, []Digit2) {
func
(
x
Natural
)
Div
(
y
Natural
)
Natural
{
func
(
x
Natural
)
Div
(
y
Natural
)
Natural
{
q
,
r
:=
DivMod
(
Unpack
(
x
),
U
npack
(
y
));
q
,
r
:=
divmod
(
unpack
(
x
),
u
npack
(
y
));
return
P
ack
(
q
);
return
p
ack
(
q
);
}
}
func
(
x
Natural
)
Mod
(
y
Natural
)
Natural
{
func
(
x
Natural
)
Mod
(
y
Natural
)
Natural
{
q
,
r
:=
DivMod
(
Unpack
(
x
),
U
npack
(
y
));
q
,
r
:=
divmod
(
unpack
(
x
),
u
npack
(
y
));
return
P
ack
(
r
);
return
p
ack
(
r
);
}
}
func
(
x
Natural
)
DivMod
(
y
Natural
)
(
Natural
,
Natural
)
{
func
(
x
Natural
)
DivMod
(
y
Natural
)
(
Natural
,
Natural
)
{
q
,
r
:=
DivMod
(
Unpack
(
x
),
U
npack
(
y
));
q
,
r
:=
divmod
(
unpack
(
x
),
u
npack
(
y
));
return
Pack
(
q
),
P
ack
(
r
);
return
pack
(
q
),
p
ack
(
r
);
}
}
func
S
hl
(
z
,
x
[]
Digit
,
s
uint
)
Digit
{
func
s
hl
(
z
,
x
[]
Digit
,
s
uint
)
Digit
{
assert
(
s
<=
W
);
assert
(
s
<=
_
W
);
n
:=
len
(
x
);
n
:=
len
(
x
);
c
:=
Digit
(
0
);
c
:=
Digit
(
0
);
for
i
:=
0
;
i
<
n
;
i
++
{
for
i
:=
0
;
i
<
n
;
i
++
{
c
,
z
[
i
]
=
x
[
i
]
>>
(
W
-
s
),
x
[
i
]
<<
s
&
M
|
c
;
c
,
z
[
i
]
=
x
[
i
]
>>
(
_W
-
s
),
x
[
i
]
<<
s
&
_
M
|
c
;
}
}
return
c
;
return
c
;
}
}
...
@@ -471,21 +472,21 @@ func Shl(z, x []Digit, s uint) Digit {
...
@@ -471,21 +472,21 @@ func Shl(z, x []Digit, s uint) Digit {
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
;
z
:=
make
(
Natural
,
m
+
1
);
z
:=
make
(
Natural
,
m
+
1
);
z
[
m
]
=
Shl
(
z
[
m
-
n
:
m
],
x
,
s
%
W
);
z
[
m
]
=
shl
(
z
[
m
-
n
:
m
],
x
,
s
%
_
W
);
return
N
ormalize
(
z
);
return
n
ormalize
(
z
);
}
}
func
S
hr
(
z
,
x
[]
Digit
,
s
uint
)
Digit
{
func
s
hr
(
z
,
x
[]
Digit
,
s
uint
)
Digit
{
assert
(
s
<=
W
);
assert
(
s
<=
_
W
);
n
:=
len
(
x
);
n
:=
len
(
x
);
c
:=
Digit
(
0
);
c
:=
Digit
(
0
);
for
i
:=
n
-
1
;
i
>=
0
;
i
--
{
for
i
:=
n
-
1
;
i
>=
0
;
i
--
{
c
,
z
[
i
]
=
x
[
i
]
<<
(
W
-
s
)
&
M
,
x
[
i
]
>>
s
|
c
;
c
,
z
[
i
]
=
x
[
i
]
<<
(
_W
-
s
)
&
_
M
,
x
[
i
]
>>
s
|
c
;
}
}
return
c
;
return
c
;
}
}
...
@@ -493,15 +494,15 @@ func Shr(z, x []Digit, s uint) Digit {
...
@@ -493,15 +494,15 @@ func Shr(z, x []Digit, s uint) Digit {
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
;
if
m
>
n
{
// check for underflow
if
m
>
n
{
// check for underflow
m
=
0
;
m
=
0
;
}
}
z
:=
make
(
Natural
,
m
);
z
:=
make
(
Natural
,
m
);
Shr
(
z
,
x
[
n
-
m
:
n
],
s
%
W
);
shr
(
z
,
x
[
n
-
m
:
n
],
s
%
_
W
);
return
N
ormalize
(
z
);
return
n
ormalize
(
z
);
}
}
...
@@ -518,11 +519,11 @@ func (x Natural) And(y Natural) Natural {
...
@@ -518,11 +519,11 @@ func (x Natural) And(y Natural) Natural {
}
}
// upper bits are 0
// upper bits are 0
return
N
ormalize
(
z
);
return
n
ormalize
(
z
);
}
}
func
C
opy
(
z
,
x
[]
Digit
)
{
func
c
opy
(
z
,
x
[]
Digit
)
{
for
i
,
e
:=
range
x
{
for
i
,
e
:=
range
x
{
z
[
i
]
=
e
z
[
i
]
=
e
}
}
...
@@ -540,7 +541,7 @@ func (x Natural) Or(y Natural) Natural {
...
@@ -540,7 +541,7 @@ func (x Natural) Or(y Natural) Natural {
for
i
:=
0
;
i
<
m
;
i
++
{
for
i
:=
0
;
i
<
m
;
i
++
{
z
[
i
]
=
x
[
i
]
|
y
[
i
];
z
[
i
]
=
x
[
i
]
|
y
[
i
];
}
}
C
opy
(
z
[
m
:
n
],
x
[
m
:
n
]);
c
opy
(
z
[
m
:
n
],
x
[
m
:
n
]);
return
z
;
return
z
;
}
}
...
@@ -557,9 +558,9 @@ func (x Natural) Xor(y Natural) Natural {
...
@@ -557,9 +558,9 @@ func (x Natural) Xor(y Natural) Natural {
for
i
:=
0
;
i
<
m
;
i
++
{
for
i
:=
0
;
i
<
m
;
i
++
{
z
[
i
]
=
x
[
i
]
^
y
[
i
];
z
[
i
]
=
x
[
i
]
^
y
[
i
];
}
}
C
opy
(
z
[
m
:
n
],
x
[
m
:
n
]);
c
opy
(
z
[
m
:
n
],
x
[
m
:
n
]);
return
N
ormalize
(
z
);
return
n
ormalize
(
z
);
}
}
...
@@ -584,7 +585,7 @@ func (x Natural) Cmp(y Natural) int {
...
@@ -584,7 +585,7 @@ func (x Natural) Cmp(y Natural) int {
}
}
func
L
og2
(
x
Digit
)
uint
{
func
l
og2
(
x
Digit
)
uint
{
assert
(
x
>
0
);
assert
(
x
>
0
);
n
:=
uint
(
0
);
n
:=
uint
(
0
);
for
x
>
0
{
for
x
>
0
{
...
@@ -598,7 +599,7 @@ func Log2(x Digit) uint {
...
@@ -598,7 +599,7 @@ func Log2(x Digit) uint {
func
(
x
Natural
)
Log2
()
uint
{
func
(
x
Natural
)
Log2
()
uint
{
n
:=
len
(
x
);
n
:=
len
(
x
);
if
n
>
0
{
if
n
>
0
{
return
(
uint
(
n
)
-
1
)
*
W
+
L
og2
(
x
[
n
-
1
]);
return
(
uint
(
n
)
-
1
)
*
_W
+
l
og2
(
x
[
n
-
1
]);
}
}
panic
(
"Log2(0)"
);
panic
(
"Log2(0)"
);
}
}
...
@@ -606,16 +607,16 @@ func (x Natural) Log2() uint {
...
@@ -606,16 +607,16 @@ func (x Natural) Log2() uint {
// Computes x = x div d in place (modifies x) for "small" d's.
// Computes x = x div d in place (modifies x) for "small" d's.
// Returns updated x and x mod d.
// Returns updated x and x mod d.
func
DivM
od1
(
x
Natural
,
d
Digit
)
(
Natural
,
Digit
)
{
func
divm
od1
(
x
Natural
,
d
Digit
)
(
Natural
,
Digit
)
{
assert
(
0
<
d
&&
IsSmall
(
d
-
1
));
assert
(
0
<
d
&&
IsSmall
(
d
-
1
));
c
:=
Digit
(
0
);
c
:=
Digit
(
0
);
for
i
:=
len
(
x
)
-
1
;
i
>=
0
;
i
--
{
for
i
:=
len
(
x
)
-
1
;
i
>=
0
;
i
--
{
t
:=
c
<<
W
+
x
[
i
];
t
:=
c
<<
_
W
+
x
[
i
];
c
,
x
[
i
]
=
t
%
d
,
t
/
d
;
c
,
x
[
i
]
=
t
%
d
,
t
/
d
;
}
}
return
N
ormalize
(
x
),
c
;
return
n
ormalize
(
x
),
c
;
}
}
...
@@ -626,19 +627,19 @@ func (x Natural) ToString(base uint) string {
...
@@ -626,19 +627,19 @@ func (x Natural) ToString(base uint) string {
// allocate buffer for conversion
// allocate buffer for conversion
assert
(
2
<=
base
&&
base
<=
16
);
assert
(
2
<=
base
&&
base
<=
16
);
n
:=
(
x
.
Log2
()
+
1
)
/
L
og2
(
Digit
(
base
))
+
1
;
// +1: round up
n
:=
(
x
.
Log2
()
+
1
)
/
l
og2
(
Digit
(
base
))
+
1
;
// +1: round up
s
:=
make
([]
byte
,
n
);
s
:=
make
([]
byte
,
n
);
// don't destroy x
// don't destroy x
t
:=
make
(
Natural
,
len
(
x
));
t
:=
make
(
Natural
,
len
(
x
));
C
opy
(
t
,
x
);
c
opy
(
t
,
x
);
// convert
// convert
i
:=
n
;
i
:=
n
;
for
!
t
.
IsZero
()
{
for
!
t
.
IsZero
()
{
i
--
;
i
--
;
var
d
Digit
;
var
d
Digit
;
t
,
d
=
DivM
od1
(
t
,
Digit
(
base
));
t
,
d
=
divm
od1
(
t
,
Digit
(
base
));
s
[
i
]
=
"0123456789abcdef"
[
d
];
s
[
i
]
=
"0123456789abcdef"
[
d
];
};
};
...
@@ -651,7 +652,7 @@ func (x Natural) String() string {
...
@@ -651,7 +652,7 @@ func (x Natural) String() string {
}
}
func
FmtB
ase
(
c
int
)
uint
{
func
fmtb
ase
(
c
int
)
uint
{
switch
c
{
switch
c
{
case
'b'
:
return
2
;
case
'b'
:
return
2
;
case
'o'
:
return
8
;
case
'o'
:
return
8
;
...
@@ -661,13 +662,13 @@ func FmtBase(c int) uint {
...
@@ -661,13 +662,13 @@ func FmtBase(c int) uint {
}
}
func
(
x
Natural
)
Format
(
h
F
mt
.
Formatter
,
c
int
)
{
func
(
x
Natural
)
Format
(
h
f
mt
.
Formatter
,
c
int
)
{
Fmt
.
Fprintf
(
h
,
"%s"
,
x
.
ToString
(
FmtB
ase
(
c
)));
fmt
.
Fprintf
(
h
,
"%s"
,
x
.
ToString
(
fmtb
ase
(
c
)));
}
}
func
HexV
alue
(
ch
byte
)
uint
{
func
hexv
alue
(
ch
byte
)
uint
{
d
:=
uint
(
1
<<
LogH
);
d
:=
uint
(
1
<<
_
LogH
);
switch
{
switch
{
case
'0'
<=
ch
&&
ch
<=
'9'
:
d
=
uint
(
ch
-
'0'
);
case
'0'
<=
ch
&&
ch
<=
'9'
:
d
=
uint
(
ch
-
'0'
);
case
'a'
<=
ch
&&
ch
<=
'f'
:
d
=
uint
(
ch
-
'a'
)
+
10
;
case
'a'
<=
ch
&&
ch
<=
'f'
:
d
=
uint
(
ch
-
'a'
)
+
10
;
...
@@ -685,11 +686,11 @@ func MulAdd1(x Natural, d, c Digit) Natural {
...
@@ -685,11 +686,11 @@ func MulAdd1(x Natural, d, c Digit) Natural {
for
i
:=
0
;
i
<
n
;
i
++
{
for
i
:=
0
;
i
<
n
;
i
++
{
t
:=
c
+
x
[
i
]
*
d
;
t
:=
c
+
x
[
i
]
*
d
;
c
,
z
[
i
]
=
t
>>
W
,
t
&
M
;
c
,
z
[
i
]
=
t
>>
_W
,
t
&
_
M
;
}
}
z
[
n
]
=
c
;
z
[
n
]
=
c
;
return
N
ormalize
(
z
);
return
n
ormalize
(
z
);
}
}
...
@@ -713,7 +714,7 @@ export func NatFromString(s string, base uint, slen *int) (Natural, uint) {
...
@@ -713,7 +714,7 @@ export func NatFromString(s string, base uint, slen *int) (Natural, uint) {
assert
(
2
<=
base
&&
base
<=
16
);
assert
(
2
<=
base
&&
base
<=
16
);
x
:=
Nat
(
0
);
x
:=
Nat
(
0
);
for
;
i
<
n
;
i
++
{
for
;
i
<
n
;
i
++
{
d
:=
HexV
alue
(
s
[
i
]);
d
:=
hexv
alue
(
s
[
i
]);
if
d
<
base
{
if
d
<
base
{
x
=
MulAdd1
(
x
,
Digit
(
base
),
Digit
(
d
));
x
=
MulAdd1
(
x
,
Digit
(
base
),
Digit
(
d
));
}
else
{
}
else
{
...
@@ -732,7 +733,7 @@ export func NatFromString(s string, base uint, slen *int) (Natural, uint) {
...
@@ -732,7 +733,7 @@ export func NatFromString(s string, base uint, slen *int) (Natural, uint) {
// Natural number functions
// Natural number functions
func
P
op1
(
x
Digit
)
uint
{
func
p
op1
(
x
Digit
)
uint
{
n
:=
uint
(
0
);
n
:=
uint
(
0
);
for
x
!=
0
{
for
x
!=
0
{
x
&=
x
-
1
;
x
&=
x
-
1
;
...
@@ -745,7 +746,7 @@ func Pop1(x Digit) uint {
...
@@ -745,7 +746,7 @@ func Pop1(x Digit) uint {
func
(
x
Natural
)
Pop
()
uint
{
func
(
x
Natural
)
Pop
()
uint
{
n
:=
uint
(
0
);
n
:=
uint
(
0
);
for
i
:=
len
(
x
)
-
1
;
i
>=
0
;
i
--
{
for
i
:=
len
(
x
)
-
1
;
i
>=
0
;
i
--
{
n
+=
P
op1
(
x
[
i
]);
n
+=
p
op1
(
x
[
i
]);
}
}
return
n
;
return
n
;
}
}
...
@@ -1095,8 +1096,8 @@ func (x *Integer) String() string {
...
@@ -1095,8 +1096,8 @@ func (x *Integer) String() string {
}
}
func
(
x
*
Integer
)
Format
(
h
F
mt
.
Formatter
,
c
int
)
{
func
(
x
*
Integer
)
Format
(
h
f
mt
.
Formatter
,
c
int
)
{
Fmt
.
Fprintf
(
h
,
"%s"
,
x
.
ToString
(
FmtB
ase
(
c
)));
fmt
.
Fprintf
(
h
,
"%s"
,
x
.
ToString
(
fmtb
ase
(
c
)));
}
}
...
@@ -1225,8 +1226,8 @@ func (x *Rational) String() string {
...
@@ -1225,8 +1226,8 @@ func (x *Rational) String() string {
}
}
func
(
x
*
Rational
)
Format
(
h
F
mt
.
Formatter
,
c
int
)
{
func
(
x
*
Rational
)
Format
(
h
f
mt
.
Formatter
,
c
int
)
{
Fmt
.
Fprintf
(
h
,
"%s"
,
x
.
ToString
(
FmtB
ase
(
c
)));
fmt
.
Fprintf
(
h
,
"%s"
,
x
.
ToString
(
fmtb
ase
(
c
)));
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment