Source File
nat.go
Belonging Package
math/big
package big
import (
)
return [:0]
return .set()
return [:0]
return .set()
= .make()
:= subVV([0:], , )
if > {
= subVW([:], [:], )
}
if != 0 {
panic("underflow")
}
return .norm()
}
func ( nat) ( nat) ( int) {
:= len()
:= len()
if != || == 0 {
switch {
case < :
= -1
case > :
= 1
}
return
}
:= - 1
for > 0 && [] == [] {
--
}
switch {
case [] < []:
= -1
case [] > []:
= 1
}
return
}
func ( nat) ( nat, , Word) nat {
:= len()
if == 0 || == 0 {
return .setWord() // result is r
if len() != || len() != || len() != {
panic("math/big: mismatched montgomery number lengths")
}
= .make( * 2)
.clear()
var Word
for := 0; < ; ++ {
:= []
:= addMulVVW([:+], , )
:= [] *
:= addMulVVW([:+], , )
:= +
:= +
[+] =
if < || < {
= 1
} else {
= 0
}
}
if != 0 {
subVV([:], [:], )
} else {
copy([:], [:])
}
return [:]
}
var karatsubaThreshold = 40 // computed by calibrate_test.go
if &1 != 0 || < karatsubaThreshold || < 2 {
basicMul(, , )
return
:= >> 1 // n2 >= 1
, := [:], [0:] // x = x1*b + y0
, := [:], [0:] // y = y1*b + y0
(, , ) // z0 = x0*y0
([:], , ) // z2 = x1*y1
:= [*3:]
(, , )
:= [*4:]
copy(, [:*2])
karatsubaAdd([:], , )
karatsubaAdd([:], [:], )
if > 0 {
karatsubaAdd([:], , )
} else {
karatsubaSub([:], , )
}
}
if < karatsubaThreshold {
= .make( + )
basicMul(, , )
return .norm()
if < || != {
:= getNat(3 * )
:= *
func (, nat) {
:= len()
if &1 != 0 || < karatsubaSqrThreshold || < 2 {
basicSqr([:2*], )
return
}
:= >> 1
, := [:], [0:]
(, )
([:], )
:= [2* : 2*+]
if subVV(, , ) != 0 {
subVV(, , )
}
:= [*3:]
(, )
:= [*4:]
copy(, [:*2])
karatsubaAdd([:], , )
karatsubaAdd([:], [:], )
karatsubaSub([:], , ) // s == -1 for p != 0; s == 1 for p == 0
}
var basicSqrThreshold = 20 // computed by calibrate_test.go
var karatsubaSqrThreshold = 260 // computed by calibrate_test.go
func ( nat) ( nat) nat {
:= len()
switch {
case == 0:
return [:0]
case == 1:
:= [0]
= .make(2)
[1], [0] = mulWW(, )
return .norm()
}
if alias(, ) {
= nil // z is an alias for x - cannot reuse
}
if < basicSqrThreshold {
= .make(2 * )
basicMul(, , )
return .norm()
}
if < karatsubaSqrThreshold {
= .make(2 * )
basicSqr(, )
return .norm()
}
:= karatsubaLen(, karatsubaSqrThreshold)
:= [0:]
= .make(max(6*, 2*))
karatsubaSqr(, ) // z = x0^2
= [0 : 2*]
[2*:].clear()
if < {
:= getNat(2 * )
:= *
:= .norm()
:= [:]
= .mul(, )
addAt(, , )
addAt(, , ) // z = 2*x1*x0*b + x0^2
= .()
addAt(, , 2*) // z = x1^2*b^2 + 2*x1*x0*b + x0^2
putNat()
}
return .norm()
}
if alias(, ) {
= nil // z is an alias for u - cannot reuse
}
= .make( + 1)
if < divRecursiveThreshold {
.divBasic(, )
} else {
.divRecursive(, )
}
putNat()
= .norm()
shrVU(, , )
= .norm()
return ,
}
:= [-1]
:= reciprocalWord()
:= [-2]
:= [+-2]
for greaterThan(, , , ) {
--
:=
if < {
break
}
, = mulWW(, )
}
}
if < {
[+] +=
}
--
}
if == && == len() && == 0 {
continue
}
[] =
}
putNat()
}
const divRecursiveThreshold = 100
:= / 2
:= [-:]
:= *[]
.clear()
.([:+], [:], +1, , )
:= .make(3 * )
.clear()
= .mul(, [:])
for := 0; < 2; ++ {
:= .cmp(.norm())
if <= 0 {
break
}
subVW(, , 1)
:= subVV([:], [:], [:])
if len() > {
subVW([:], [:], )
}
addAt([:], [:], 0)
}
if .cmp(.norm()) > 0 {
panic("impossible")
}
:= subVV([:len()], [:len()], )
if > 0 {
subVW([len():], [len():], )
}
addAt(, , -)
-=
}
return
}
panic("set bit is not 0 or 1")
}
func ( nat) ( *rand.Rand, nat, int) nat {
if alias(, ) {
= nil // z is an alias for limit - cannot reuse
}
= .make(len())
:= uint( % _W)
if == 0 {
= _W
}
:= Word((1 << ) - 1)
for {
switch _W {
case 32:
for := range {
[] = Word(.Uint32())
}
case 64:
for := range {
[] = Word(.Uint32()) | Word(.Uint32())<<32
}
default:
panic("unknown word size")
}
[len()-1] &=
if .cmp() < 0 {
break
}
}
return .norm()
}
= nil
}
if .cmp(natOne) > 0 && len() > 1 && len() > 0 {
if [0]&1 == 1 {
return .expNNMontgomery(, , )
}
return .expNNWindowed(, , )
}
:= [len()-1] // v > 0 because y is normalized and y > 0
:= nlz() + 1
<<=
var nat
const = 1 << (_W - 1)
var , nat
for := 0; < ; ++ {
= .sqr()
, = ,
if & != 0 {
= .mul(, )
, = ,
}
if len() != 0 {
, = .div(, , )
, , , = , , ,
}
<<= 1
}
for := len() - 2; >= 0; -- {
= []
for := 0; < _W; ++ {
= .sqr()
, = ,
if & != 0 {
= .mul(, )
, = ,
}
if len() != 0 {
, = .div(, , )
, , , = , , ,
}
<<= 1
}
}
return .norm()
}
var , nat
if len() > {
:= 2 - [0]
:= [0] - 1
for := 1; < _W; <<= 1 {
*=
*= ( + 1)
}
= -
var [1 << ]nat
[0] = [0].montgomery(, , , , )
[1] = [1].montgomery(, , , , )
for := 2; < 1<<; ++ {
[] = [].montgomery([-1], [1], , , )
}
for := len() - 1; >= 0; -- {
:= []
for := 0; < _W; += {
if != len()-1 || != 0 {
= .montgomery(, , , , )
= .montgomery(, , , , )
= .montgomery(, , , , )
= .montgomery(, , , , )
}
= .montgomery(, [>>(_W-)], , , )
, = ,
<<=
}
= .montgomery(, , , , )
if &1 == 0 {
return
}
return .set()
}
, = ,
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |