Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
e2fe2f3f
Commit
e2fe2f3f
authored
Nov 04, 2008
by
Robert Griesemer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- better support for string conversions
- removed trailing tabs R=r OCL=18458 CL=18458
parent
d289e634
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
73 deletions
+107
-73
bignum.go
usr/gri/bignum/bignum.go
+45
-33
bignum_test.go
usr/gri/bignum/bignum_test.go
+62
-40
No files found.
usr/gri/bignum/bignum.go
View file @
e2fe2f3f
...
...
@@ -180,7 +180,7 @@ func Mul11(x, y Digit) (Digit, Digit) {
// z = z1*B + z0 = x*y
z0
:=
(
t1
<<
W2
+
t0
)
&
M
;
z1
:=
t2
<<
DW
+
(
t1
+
t0
>>
W2
)
>>
(
W
-
W2
);
return
z1
,
z0
;
}
...
...
@@ -453,17 +453,17 @@ func DivMod(x, y *[]Digit2) (*[]Digit2, *[]Digit2) {
assert
(
n
+
1
<=
cap
(
x
));
// space for one extra digit
x
=
x
[
0
:
n
+
1
];
assert
(
x
[
n
]
==
0
);
if
m
==
1
{
// division by single digit
// result is shifted left by 1 in place!
x
[
0
]
=
Div1
(
x
[
1
:
n
+
1
],
x
[
0
:
n
],
y
[
0
]);
}
else
if
m
>
n
{
// y > x => quotient = 0, remainder = x
// TODO in this case we shouldn't even unpack x and y
m
=
n
;
}
else
{
// general case
assert
(
2
<=
m
&&
m
<=
n
);
...
...
@@ -478,12 +478,12 @@ func DivMod(x, y *[]Digit2) (*[]Digit2, *[]Digit2) {
Mul1
(
y
,
y
,
Digit2
(
f
));
}
assert
(
B2
/
2
<=
y
[
m
-
1
]
&&
y
[
m
-
1
]
<
B2
);
// incorrect scaling
y1
,
y2
:=
Digit
(
y
[
m
-
1
]),
Digit
(
y
[
m
-
2
]);
d2
:=
Digit
(
y1
)
<<
W2
+
Digit
(
y2
);
for
i
:=
n
-
m
;
i
>=
0
;
i
--
{
k
:=
i
+
m
;
// compute trial digit (Knuth)
var
q
Digit
;
{
x0
,
x1
,
x2
:=
Digit
(
x
[
k
]),
Digit
(
x
[
k
-
1
]),
Digit
(
x
[
k
-
2
]);
...
...
@@ -496,14 +496,14 @@ func DivMod(x, y *[]Digit2) (*[]Digit2, *[]Digit2) {
q
--
}
}
// subtract y*q
c
:=
Digit
(
0
);
for
j
:=
0
;
j
<
m
;
j
++
{
t
:=
c
+
Digit
(
x
[
i
+
j
])
-
Digit
(
y
[
j
])
*
q
;
c
,
x
[
i
+
j
]
=
Digit
(
int64
(
t
)
>>
W2
),
Digit2
(
t
&
M2
);
// requires arithmetic shift!
}
// correct if trial digit was too large
if
c
+
Digit
(
x
[
k
])
!=
0
{
// add y
...
...
@@ -516,10 +516,10 @@ func DivMod(x, y *[]Digit2) (*[]Digit2, *[]Digit2) {
// correct trial digit
q
--
;
}
x
[
k
]
=
Digit2
(
q
);
}
// undo normalization for remainder
if
f
!=
1
{
c
:=
Div1
(
x
[
0
:
m
],
x
[
0
:
m
],
Digit2
(
f
));
...
...
@@ -553,9 +553,9 @@ func (x *Natural) Shl(s uint) *Natural {
n
:=
uint
(
len
(
x
));
m
:=
n
+
s
/
W
;
z
:=
new
(
Natural
,
m
+
1
);
z
[
m
]
=
Shl
(
z
[
m
-
n
:
m
],
x
,
s
%
W
);
return
Normalize
(
z
);
}
...
...
@@ -567,9 +567,9 @@ func (x *Natural) Shr(s uint) *Natural {
m
=
0
;
}
z
:=
new
(
Natural
,
m
);
Shr
(
z
,
x
[
n
-
m
:
n
],
s
%
W
);
return
Normalize
(
z
);
}
...
...
@@ -629,7 +629,7 @@ func (x *Natural) Cmp(y *Natural) int {
i
:=
n
-
1
;
for
i
>
0
&&
x
[
i
]
==
y
[
i
]
{
i
--
;
}
d
:=
0
;
switch
{
case
x
[
i
]
<
y
[
i
]
:
d
=
-
1
;
...
...
@@ -679,7 +679,7 @@ func (x *Natural) String(base uint) string {
if
len
(
x
)
==
0
{
return
"0"
;
}
// allocate buffer for conversion
assert
(
2
<=
base
&&
base
<=
16
);
n
:=
(
x
.
Log2
()
+
1
)
/
Log2
(
Digit
(
base
))
+
1
;
// +1: round up
...
...
@@ -688,7 +688,7 @@ func (x *Natural) String(base uint) string {
// don't destroy x
t
:=
new
(
Natural
,
len
(
x
));
Or1
(
t
,
x
,
0
);
// copy
// convert
i
:=
n
;
for
!
t
.
IsZero
()
{
...
...
@@ -730,7 +730,8 @@ func MulAdd1(x *Natural, d, c Digit) *Natural {
// Determines base (octal, decimal, hexadecimal) if base == 0.
export
func
NatFromString
(
s
string
,
base
uint
,
slen
*
int
)
*
Natural
{
// Returns the number and base.
export
func
NatFromString
(
s
string
,
base
uint
,
slen
*
int
)
(
*
Natural
,
uint
)
{
// determine base if necessary
i
,
n
:=
0
,
len
(
s
);
if
base
==
0
{
...
...
@@ -743,7 +744,7 @@ export func NatFromString(s string, base uint, slen *int) *Natural {
}
}
}
// convert string
assert
(
2
<=
base
&&
base
<=
16
);
x
:=
Nat
(
0
);
...
...
@@ -761,7 +762,7 @@ export func NatFromString(s string, base uint, slen *int) *Natural {
*
slen
=
i
;
}
return
x
;
return
x
,
base
;
}
...
...
@@ -1104,7 +1105,8 @@ func (x *Integer) String(base uint) string {
// Determines base (octal, decimal, hexadecimal) if base == 0.
export
func
IntFromString
(
s
string
,
base
uint
,
slen
*
int
)
*
Integer
{
// Returns the number and base.
export
func
IntFromString
(
s
string
,
base
uint
,
slen
*
int
)
(
*
Integer
,
uint
)
{
// get sign, if any
sign
:=
false
;
if
len
(
s
)
>
0
&&
(
s
[
0
]
==
'-'
||
s
[
0
]
==
'+'
)
{
...
...
@@ -1112,14 +1114,15 @@ export func IntFromString(s string, base uint, slen *int) *Integer {
s
=
s
[
1
:
len
(
s
)];
}
z
:=
MakeInt
(
sign
,
NatFromString
(
s
,
base
,
slen
));
var
mant
*
Natural
;
mant
,
base
=
NatFromString
(
s
,
base
,
slen
);
// correct slen if necessary
if
slen
!=
nil
&&
sign
{
*
slen
++
;
}
return
z
;
return
MakeInt
(
sign
,
mant
),
base
;
}
...
...
@@ -1222,24 +1225,33 @@ func (x *Rational) String(base uint) string {
// Determines base (octal, decimal, hexadecimal) if base == 0.
export
func
RatFromString
(
s
string
,
base
uint
,
slen
*
int
)
*
Rational
{
// Returns the number and base of the nominator.
export
func
RatFromString
(
s
string
,
base
uint
,
slen
*
int
)
(
*
Rational
,
uint
)
{
// read nominator
var
alen
,
blen
int
;
a
:=
IntFromString
(
s
,
base
,
&
alen
);
a
,
abase
:=
IntFromString
(
s
,
base
,
&
alen
);
b
:=
Nat
(
1
);
// read denominator, if any
if
alen
<
len
(
s
)
&&
s
[
alen
]
==
'/'
{
alen
++
;
if
alen
<
len
(
s
)
{
b
=
NatFromString
(
s
[
alen
:
len
(
s
)],
base
,
&
blen
);
// read denominator or fraction, if any
if
alen
<
len
(
s
)
{
ch
:=
s
[
alen
];
if
ch
==
'/'
{
alen
++
;
b
,
base
=
NatFromString
(
s
[
alen
:
len
(
s
)],
base
,
&
blen
);
}
else
if
ch
==
'.'
{
alen
++
;
b
,
base
=
NatFromString
(
s
[
alen
:
len
(
s
)],
abase
,
&
blen
);
assert
(
base
==
abase
);
f
:=
Nat
(
base
)
.
Pow
(
uint
(
blen
));
a
=
MakeInt
(
a
.
sign
,
a
.
mant
.
Mul
(
f
)
.
Add
(
b
));
b
=
f
;
}
}
// provide number of string bytes consumed if necessary
if
slen
!=
nil
{
*
slen
=
alen
+
blen
;
}
return
MakeRat
(
a
,
b
);
return
MakeRat
(
a
,
b
)
,
abase
;
}
usr/gri/bignum/bignum_test.go
View file @
e2fe2f3f
...
...
@@ -16,22 +16,40 @@ const (
)
func
NatFromString
(
s
string
,
base
uint
,
slen
*
int
)
*
Big
.
Natural
{
x
,
dummy
:=
Big
.
NatFromString
(
s
,
base
,
slen
);
return
x
;
}
func
IntFromString
(
s
string
,
base
uint
,
slen
*
int
)
*
Big
.
Integer
{
x
,
dummy
:=
Big
.
IntFromString
(
s
,
base
,
slen
);
return
x
;
}
func
RatFromString
(
s
string
,
base
uint
,
slen
*
int
)
*
Big
.
Rational
{
x
,
dummy
:=
Big
.
RatFromString
(
s
,
base
,
slen
);
return
x
;
}
var
(
nat_zero
=
Big
.
Nat
(
0
);
nat_one
=
Big
.
Nat
(
1
);
nat_two
=
Big
.
Nat
(
2
);
a
=
Big
.
NatFromString
(
sa
,
10
,
nil
);
b
=
Big
.
NatFromString
(
sb
,
10
,
nil
);
c
=
Big
.
NatFromString
(
sc
,
10
,
nil
);
p
=
Big
.
NatFromString
(
sp
,
10
,
nil
);
a
=
NatFromString
(
sa
,
10
,
nil
);
b
=
NatFromString
(
sb
,
10
,
nil
);
c
=
NatFromString
(
sc
,
10
,
nil
);
p
=
NatFromString
(
sp
,
10
,
nil
);
int_zero
=
Big
.
Int
(
0
);
int_one
=
Big
.
Int
(
1
);
int_two
=
Big
.
Int
(
2
);
ip
=
Big
.
IntFromString
(
sp
,
10
,
nil
);
ip
=
IntFromString
(
sp
,
10
,
nil
);
rat_zero
=
Big
.
Rat
(
0
,
1
);
rat_half
=
Big
.
Rat
(
1
,
2
);
rat_one
=
Big
.
Rat
(
1
,
1
);
...
...
@@ -89,17 +107,17 @@ func NatConv() {
test_msg
=
"NatConvB"
;
var
slen
int
;
NAT_EQ
(
0
,
Big
.
NatFromString
(
"0"
,
0
,
nil
),
nat_zero
);
NAT_EQ
(
1
,
Big
.
NatFromString
(
"123"
,
0
,
nil
),
Big
.
Nat
(
123
));
NAT_EQ
(
2
,
Big
.
NatFromString
(
"077"
,
0
,
nil
),
Big
.
Nat
(
7
*
8
+
7
));
NAT_EQ
(
3
,
Big
.
NatFromString
(
"0x1f"
,
0
,
nil
),
Big
.
Nat
(
1
*
16
+
15
));
NAT_EQ
(
4
,
Big
.
NatFromString
(
"0x1fg"
,
0
,
&
slen
),
Big
.
Nat
(
1
*
16
+
15
));
NAT_EQ
(
0
,
NatFromString
(
"0"
,
0
,
nil
),
nat_zero
);
NAT_EQ
(
1
,
NatFromString
(
"123"
,
0
,
nil
),
Big
.
Nat
(
123
));
NAT_EQ
(
2
,
NatFromString
(
"077"
,
0
,
nil
),
Big
.
Nat
(
7
*
8
+
7
));
NAT_EQ
(
3
,
NatFromString
(
"0x1f"
,
0
,
nil
),
Big
.
Nat
(
1
*
16
+
15
));
NAT_EQ
(
4
,
NatFromString
(
"0x1fg"
,
0
,
&
slen
),
Big
.
Nat
(
1
*
16
+
15
));
TEST
(
4
,
slen
==
4
);
test_msg
=
"NatConvC"
;
t
:=
c
.
Mul
(
c
);
for
base
:=
uint
(
2
);
base
<=
16
;
base
++
{
NAT_EQ
(
base
,
Big
.
NatFromString
(
t
.
String
(
base
),
base
,
nil
),
t
);
NAT_EQ
(
base
,
NatFromString
(
t
.
String
(
base
),
base
,
nil
),
t
);
}
}
...
...
@@ -107,16 +125,16 @@ func NatConv() {
func
IntConv
()
{
test_msg
=
"IntConv"
;
var
slen
int
;
INT_EQ
(
0
,
Big
.
IntFromString
(
"0"
,
0
,
nil
),
int_zero
);
INT_EQ
(
1
,
Big
.
IntFromString
(
"-0"
,
0
,
nil
),
int_zero
);
INT_EQ
(
2
,
Big
.
IntFromString
(
"123"
,
0
,
nil
),
Big
.
Int
(
123
));
INT_EQ
(
3
,
Big
.
IntFromString
(
"-123"
,
0
,
nil
),
Big
.
Int
(
-
123
));
INT_EQ
(
4
,
Big
.
IntFromString
(
"077"
,
0
,
nil
),
Big
.
Int
(
7
*
8
+
7
));
INT_EQ
(
5
,
Big
.
IntFromString
(
"-077"
,
0
,
nil
),
Big
.
Int
(
-
(
7
*
8
+
7
)));
INT_EQ
(
6
,
Big
.
IntFromString
(
"0x1f"
,
0
,
nil
),
Big
.
Int
(
1
*
16
+
15
));
INT_EQ
(
7
,
Big
.
IntFromString
(
"-0x1f"
,
0
,
nil
),
Big
.
Int
(
-
(
1
*
16
+
15
)));
INT_EQ
(
8
,
Big
.
IntFromString
(
"0x1fg"
,
0
,
&
slen
),
Big
.
Int
(
1
*
16
+
15
));
INT_EQ
(
9
,
Big
.
IntFromString
(
"-0x1fg"
,
0
,
&
slen
),
Big
.
Int
(
-
(
1
*
16
+
15
)));
INT_EQ
(
0
,
IntFromString
(
"0"
,
0
,
nil
),
int_zero
);
INT_EQ
(
1
,
IntFromString
(
"-0"
,
0
,
nil
),
int_zero
);
INT_EQ
(
2
,
IntFromString
(
"123"
,
0
,
nil
),
Big
.
Int
(
123
));
INT_EQ
(
3
,
IntFromString
(
"-123"
,
0
,
nil
),
Big
.
Int
(
-
123
));
INT_EQ
(
4
,
IntFromString
(
"077"
,
0
,
nil
),
Big
.
Int
(
7
*
8
+
7
));
INT_EQ
(
5
,
IntFromString
(
"-077"
,
0
,
nil
),
Big
.
Int
(
-
(
7
*
8
+
7
)));
INT_EQ
(
6
,
IntFromString
(
"0x1f"
,
0
,
nil
),
Big
.
Int
(
1
*
16
+
15
));
INT_EQ
(
7
,
IntFromString
(
"-0x1f"
,
0
,
nil
),
Big
.
Int
(
-
(
1
*
16
+
15
)));
INT_EQ
(
8
,
IntFromString
(
"0x1fg"
,
0
,
&
slen
),
Big
.
Int
(
1
*
16
+
15
));
INT_EQ
(
9
,
IntFromString
(
"-0x1fg"
,
0
,
&
slen
),
Big
.
Int
(
-
(
1
*
16
+
15
)));
TEST
(
10
,
slen
==
5
);
}
...
...
@@ -124,12 +142,16 @@ func IntConv() {
func
RatConv
()
{
test_msg
=
"RatConv"
;
var
slen
int
;
RAT_EQ
(
0
,
Big
.
RatFromString
(
"0"
,
0
,
nil
),
rat_zero
);
RAT_EQ
(
1
,
Big
.
RatFromString
(
"0/"
,
0
,
nil
),
rat_zero
);
RAT_EQ
(
2
,
Big
.
RatFromString
(
"0/1"
,
0
,
nil
),
rat_zero
);
RAT_EQ
(
3
,
Big
.
RatFromString
(
"010/8"
,
0
,
nil
),
rat_one
);
RAT_EQ
(
4
,
Big
.
RatFromString
(
"20/0xa"
,
0
,
&
slen
),
rat_two
);
TEST
(
5
,
slen
==
6
);
RAT_EQ
(
0
,
RatFromString
(
"0"
,
0
,
nil
),
rat_zero
);
RAT_EQ
(
1
,
RatFromString
(
"0/1"
,
0
,
nil
),
rat_zero
);
RAT_EQ
(
2
,
RatFromString
(
"0/01"
,
0
,
nil
),
rat_zero
);
RAT_EQ
(
3
,
RatFromString
(
"0x14/10"
,
0
,
&
slen
),
rat_two
);
TEST
(
4
,
slen
==
7
);
RAT_EQ
(
5
,
RatFromString
(
"0."
,
0
,
nil
),
rat_zero
);
RAT_EQ
(
6
,
RatFromString
(
"0.001f"
,
10
,
nil
),
Big
.
Rat
(
1
,
1000
));
RAT_EQ
(
7
,
RatFromString
(
"10101.0101"
,
2
,
nil
),
Big
.
Rat
(
0x155
,
1
<<
4
));
RAT_EQ
(
8
,
RatFromString
(
"-0003.145926"
,
10
,
&
slen
),
Big
.
Rat
(
-
3145926
,
1000000
));
TEST
(
9
,
slen
==
12
);
}
...
...
@@ -213,11 +235,11 @@ func NatMul() {
test_msg
=
"NatMulA"
;
NAT_EQ
(
0
,
Mul
(
c
,
nat_zero
),
nat_zero
);
NAT_EQ
(
1
,
Mul
(
c
,
nat_one
),
c
);
test_msg
=
"NatMulB"
;
NAT_EQ
(
0
,
b
.
Mul
(
Big
.
MulRange
(
0
,
100
)),
nat_zero
);
NAT_EQ
(
1
,
b
.
Mul
(
Big
.
MulRange
(
21
,
100
)),
c
);
test_msg
=
"NatMulC"
;
const
n
=
100
;
p
:=
b
.
Mul
(
c
)
.
Shl
(
n
);
...
...
@@ -234,7 +256,7 @@ func NatDiv() {
NAT_EQ
(
2
,
b
.
Div
(
c
),
nat_zero
);
NAT_EQ
(
4
,
nat_one
.
Shl
(
100
)
.
Div
(
nat_one
.
Shl
(
90
)),
nat_one
.
Shl
(
10
));
NAT_EQ
(
5
,
c
.
Div
(
b
),
Big
.
MulRange
(
21
,
100
));
test_msg
=
"NatDivB"
;
const
n
=
100
;
p
:=
Big
.
Fact
(
n
);
...
...
@@ -315,7 +337,7 @@ func NatShift() {
test_msg
=
"NatShift1L"
;
TEST
(
0
,
b
.
Shl
(
0
)
.
Cmp
(
b
)
==
0
);
TEST
(
1
,
c
.
Shl
(
1
)
.
Cmp
(
c
)
>
0
);
test_msg
=
"NatShift1R"
;
TEST
(
0
,
b
.
Shr
(
0
)
.
Cmp
(
b
)
==
0
);
TEST
(
1
,
c
.
Shr
(
1
)
.
Cmp
(
c
)
<
0
);
...
...
@@ -349,7 +371,7 @@ func IntShift() {
test_msg
=
"IntShift1L"
;
TEST
(
0
,
ip
.
Shl
(
0
)
.
Cmp
(
ip
)
==
0
);
TEST
(
1
,
ip
.
Shl
(
1
)
.
Cmp
(
ip
)
>
0
);
test_msg
=
"IntShift1R"
;
TEST
(
0
,
ip
.
Shr
(
0
)
.
Cmp
(
ip
)
==
0
);
TEST
(
1
,
ip
.
Shr
(
1
)
.
Cmp
(
ip
)
<
0
);
...
...
@@ -376,7 +398,7 @@ func IntShift() {
p
=
p
.
Shr
(
1
);
}
}
test_msg
=
"IntShift4R"
;
//INT_EQ(0, Big.Int(-43).Shr(1), Big.Int(-43 >> 1));
//INT_EQ(1, ip.Neg().Shr(10), ip.Neg().Div(Big.Int(1).Shl(10)));
...
...
@@ -456,17 +478,17 @@ func main() {
NatGcd
();
NatPow
();
NatPop
();
// Integers
// TODO add more tests
IntConv
();
IntQuoRem
();
IntDivMod
();
IntShift
();
// Rationals
// TODO add more tests
RatConv
();
print
(
"PASSED
\n
"
);
}
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