// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// This file implements unsigned multi-precision integers (natural// numbers). They are the building blocks for the implementation// of signed integers, rationals, and floating-point numbers.//// Caution: This implementation relies on the function "alias"// which assumes that (nat) slice capacities are never// changed (no 3-operand slice expressions). If that// changes, alias needs to be updated for correctness.package bigimport ()// An unsigned integer x of the form//// x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0]//// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n,// with the digits x[i] as the slice elements.//// A number is normalized if the slice contains no leading 0 digits.// During arithmetic operations, denormalized values may occur but are// always normalized before returning the final result. The normalized// representation of 0 is the empty or nil slice (length = 0).//typenat []Wordvar (natOne = nat{1}natTwo = nat{2}natFive = nat{5}natTen = nat{10})func ( nat) () {for := range { [] = 0 }}func ( nat) () nat { := len()for > 0 && [-1] == 0 { -- }return [0:]}func ( nat) ( int) nat {if <= cap() {return [:] // reuse z }if == 1 {// Most nats start small and stay that way; don't over-allocate.returnmake(nat, 1) }// Choosing a good value for e has significant performance impact // because it increases the chance that a value can be reused.const = 4// extra capacityreturnmake(nat, , +)}func ( nat) ( Word) nat {if == 0 {return [:0] } = .make(1) [0] = return}func ( nat) ( uint64) nat {// single-word valueif := Word(); uint64() == {return .setWord() }// 2-word value = .make(2) [1] = Word( >> 32) [0] = Word()return}func ( nat) ( nat) nat { = .make(len())copy(, )return}func ( nat) (, nat) nat { := len() := len()switch {case < :return .(, )case == 0:// n == 0 because m >= n; result is 0return [:0]case == 0:// result is xreturn .set() }// m > 0 = .make( + 1) := addVV([0:], , )if > { = addVW([:], [:], ) } [] = return .norm()}func ( nat) (, nat) nat { := len() := len()switch {case < :panic("underflow")case == 0:// n == 0 because m >= n; result is 0return [:0]case == 0:// result is xreturn .set() }// m > 0 = .make() := subVV([0:], , )if > { = subVW([:], [:], ) }if != 0 {panic("underflow") }return .norm()}func ( nat) ( nat) ( int) { := len() := len()if != || == 0 {switch {case < : = -1case > : = 1 }return } := - 1for > 0 && [] == [] { -- }switch {case [] < []: = -1case [] > []: = 1 }return}func ( nat) ( nat, , Word) nat { := len()if == 0 || == 0 {return .setWord() // result is r }// m > 0 = .make( + 1) [] = mulAddVWW([0:], , , )return .norm()}// basicMul multiplies x and y and leaves the result in z.// The (non-normalized) result is placed in z[0 : len(x) + len(y)].func (, , nat) { [0 : len()+len()].clear() // initialize zfor , := range {if != 0 { [len()+] = addMulVVW([:+len()], , ) } }}// montgomery computes z mod m = x*y*2**(-n*_W) mod m,// assuming k = -1/m mod 2**_W.// z is used for storing the result which is returned;// z must not alias x, y or m.// See Gueron, "Efficient Software Implementations of Modular Exponentiation".// https://eprint.iacr.org/2011/239.pdf// In the terminology of that paper, this is an "Almost Montgomery Multiplication":// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m.func ( nat) (, , nat, Word, int) nat {// This code assumes x, y, m are all the same length, n. // (required by addMulVVW and the for loop). // It also assumes that x, y are already reduced mod m, // or else the result will not be properly reduced.iflen() != || len() != || len() != {panic("math/big: mismatched montgomery number lengths") } = .make( * 2) .clear()varWordfor := 0; < ; ++ { := [] := addMulVVW([:+], , ) := [] * := addMulVVW([:+], , ) := + := + [+] = if < || < { = 1 } else { = 0 } }if != 0 {subVV([:], [:], ) } else {copy([:], [:]) }return [:]}// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.// Factored out for readability - do not use outside karatsuba.func (, nat, int) {if := addVV([0:], , ); != 0 {addVW([:+>>1], [:], ) }}// Like karatsubaAdd, but does subtract.func (, nat, int) {if := subVV([0:], , ); != 0 {subVW([:+>>1], [:], ) }}// Operands that are shorter than karatsubaThreshold are multiplied using// "grade school" multiplication; for longer operands the Karatsuba algorithm// is used.varkaratsubaThreshold = 40// computed by calibrate_test.go// karatsuba multiplies x and y and leaves the result in z.// Both x and y must have the same length n and n must be a// power of 2. The result vector z must have len(z) >= 6*n.// The (non-normalized) result is placed in z[0 : 2*n].func (, , nat) { := len()// Switch to basic multiplication if numbers are odd or small. // (n is always even if karatsubaThreshold is even, but be // conservative)if &1 != 0 || < karatsubaThreshold || < 2 {basicMul(, , )return }// n&1 == 0 && n >= karatsubaThreshold && n >= 2// Karatsuba multiplication is based on the observation that // for two numbers x and y with: // // x = x1*b + x0 // y = y1*b + y0 // // the product x*y can be obtained with 3 products z2, z1, z0 // instead of 4: // // x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0 // = z2*b*b + z1*b + z0 // // with: // // xd = x1 - x0 // yd = y0 - y1 // // z1 = xd*yd + z2 + z0 // = (x1-x0)*(y0 - y1) + z2 + z0 // = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z2 + z0 // = x1*y0 - z2 - z0 + x0*y1 + z2 + z0 // = x1*y0 + x0*y1// split x, y into "digits" := >> 1// n2 >= 1 , := [:], [0:] // x = x1*b + y0 , := [:], [0:] // y = y1*b + y0// z is used for the result and temporary storage: // // 6*n 5*n 4*n 3*n 2*n 1*n 0*n // z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ] // // For each recursive call of karatsuba, an unused slice of // z is passed in that has (at least) half the length of the // caller's z.// compute z0 and z2 with the result "in place" in z (, , ) // z0 = x0*y0 ([:], , ) // z2 = x1*y1// compute xd (or the negative value if underflow occurs) := 1// sign of product xd*yd := [2* : 2*+]ifsubVV(, , ) != 0 { // x1-x0 = -subVV(, , ) // x0-x1 }// compute yd (or the negative value if underflow occurs) := [2*+ : 3*]ifsubVV(, , ) != 0 { // y0-y1 = -subVV(, , ) // y1-y0 }// p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0 // p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0 := [*3:] (, , )// save original z2:z0 // (ok to use upper half of z since we're done recursing) := [*4:]copy(, [:*2])// add up all partial products // // 2*n n 0 // z = [ z2 | z0 ] // + [ z0 ] // + [ z2 ] // + [ p ] //karatsubaAdd([:], , )karatsubaAdd([:], [:], )if > 0 {karatsubaAdd([:], , ) } else {karatsubaSub([:], , ) }}// alias reports whether x and y share the same base array.// Note: alias assumes that the capacity of underlying arrays// is never changed for nat values; i.e. that there are// no 3-operand slice expressions in this code (or worse,// reflect-based operations to the same effect).func (, nat) bool {returncap() > 0 && cap() > 0 && &[0:cap()][cap()-1] == &[0:cap()][cap()-1]}// addAt implements z += x<<(_W*i); z must be long enough.// (we don't use nat.add because we need z to stay the same// slice, and we don't need to normalize z after each addition)func (, nat, int) {if := len(); > 0 {if := addVV([:+], [:], ); != 0 { := + if < len() {addVW([:], [:], ) } } }}func (, int) int {if > {return }return}// karatsubaLen computes an approximation to the maximum k <= n such that// k = p<<i for a number p <= threshold and an i >= 0. Thus, the// result is the largest number that can be divided repeatedly by 2 before// becoming about the value of threshold.func (, int) int { := uint(0)for > { >>= 1 ++ }return << }func ( nat) (, nat) nat { := len() := len()switch {case < :return .(, )case == 0 || == 0:return [:0]case == 1:return .mulAddWW(, [0], 0) }// m >= n > 1// determine if z can be reusedifalias(, ) || alias(, ) { = nil// z is an alias for x or y - cannot reuse }// use basic multiplication if the numbers are smallif < karatsubaThreshold { = .make( + )basicMul(, , )return .norm() }// m >= n && n >= karatsubaThreshold && n >= 2// determine Karatsuba length k such that // // x = xh*b + x0 (0 <= x0 < b) // y = yh*b + y0 (0 <= y0 < b) // b = 1<<(_W*k) ("base" of digits xi, yi) // := karatsubaLen(, karatsubaThreshold)// k <= n// multiply x0 and y0 via Karatsuba := [0:] // x0 is not normalized := [0:] // y0 is not normalized = .make(max(6*, +)) // enough space for karatsuba of x0*y0 and full result of x*ykaratsuba(, , ) = [0 : +] // z has final length but may be incomplete [2*:].clear() // upper portion of z is garbage (and 2*k <= m+n since k <= n <= m)// If xh != 0 or yh != 0, add the missing terms to z. For // // xh = xi*b^i + ... + x2*b^2 + x1*b (0 <= xi < b) // yh = y1*b (0 <= y1 < b) // // the missing terms are // // x0*y1*b and xi*y0*b^i, xi*y1*b^(i+1) for i > 0 // // since all the yi for i > 1 are 0 by choice of k: If any of them // were > 0, then yh >= b^2 and thus y >= b^2. Then k' = k*2 would // be a larger valid threshold contradicting the assumption about k. //if < || != { := getNat(3 * ) := *// add x0*y1*b := .norm() := [:] // y1 is normalized because y is = .(, ) // update t so we don't lose t's underlying arrayaddAt(, , )// add xi*y0<<i, xi*y1*b<<(i+k) := .norm()for := ; < len(); += { := [:]iflen() > { = [:] } = .norm() = .(, )addAt(, , ) = .(, )addAt(, , +) }putNat() }return .norm()}// basicSqr sets z = x*x and is asymptotically faster than basicMul// by about a factor of 2, but slower for small arguments due to overhead.// Requirements: len(x) > 0, len(z) == 2*len(x)// The (non-normalized) result is placed in z.func (, nat) { := len() := getNat(2 * ) := * // temporary variable to hold the products .clear() [1], [0] = mulWW([0], [0]) // the initial squarefor := 1; < ; ++ { := []// z collects the squares x[i] * x[i] [2*+1], [2*] = mulWW(, )// t collects the products x[i] * x[j] where j < i [2*] = addMulVVW([:2*], [0:], ) } [2*-1] = shlVU([1:2*-1], [1:2*-1], 1) // double the j < i productsaddVV(, , ) // combine the resultputNat()}// karatsubaSqr squares x and leaves the result in z.// len(x) must be a power of 2 and len(z) >= 6*len(x).// The (non-normalized) result is placed in z[0 : 2*len(x)].//// The algorithm and the layout of z are the same as for karatsuba.func (, nat) { := len()if &1 != 0 || < karatsubaSqrThreshold || < 2 {basicSqr([:2*], )return } := >> 1 , := [:], [0:] (, ) ([:], )// s = sign(xd*yd) == -1 for xd != 0; s == 1 for xd == 0 := [2* : 2*+]ifsubVV(, , ) != 0 {subVV(, , ) } := [*3:] (, ) := [*4:]copy(, [:*2])karatsubaAdd([:], , )karatsubaAdd([:], [:], )karatsubaSub([:], , ) // s == -1 for p != 0; s == 1 for p == 0}// Operands that are shorter than basicSqrThreshold are squared using// "grade school" multiplication; for operands longer than karatsubaSqrThreshold// we use the Karatsuba algorithm optimized for x == y.varbasicSqrThreshold = 20// computed by calibrate_test.govarkaratsubaSqrThreshold = 260// computed by calibrate_test.go// z = x*xfunc ( nat) ( nat) nat { := len()switch {case == 0:return [:0]case == 1: := [0] = .make(2) [1], [0] = mulWW(, )return .norm() }ifalias(, ) { = nil// z is an alias for x - cannot reuse }if < basicSqrThreshold { = .make(2 * )basicMul(, , )return .norm() }if < karatsubaSqrThreshold { = .make(2 * )basicSqr(, )return .norm() }// Use Karatsuba multiplication optimized for x == y. // The algorithm and layout of z are the same as for mul.// z = (x1*b + x0)^2 = x1^2*b^2 + 2*x1*x0*b + x0^2 := 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^2putNat() }return .norm()}// mulRange computes the product of all the unsigned integers in the// range [a, b] inclusively. If a > b (empty range), the result is 1.func ( nat) (, uint64) nat {switch {case == 0:// cut long ranges short (optimization)return .setUint64(0)case > :return .setUint64(1)case == :return .setUint64()case +1 == :return .mul(nat(nil).setUint64(), nat(nil).setUint64()) } := ( + ) / 2return .mul(nat(nil).(, ), nat(nil).(+1, ))}// q = (x-r)/y, with 0 <= r < yfunc ( nat) ( nat, Word) ( nat, Word) { := len()switch {case == 0:panic("division by zero")case == 1: = .set() // result is xreturncase == 0: = [:0] // result is 0return }// m > 0 = .make() = divWVW(, 0, , ) = .norm()return}func ( nat) (, , nat) (, nat) {iflen() == 0 {panic("division by zero") }if .cmp() < 0 { = [:0] = .set()return }iflen() == 1 {varWord , = .divW(, [0]) = .setWord()return } , = .divLarge(, , )return}// getNat returns a *nat of len n. The contents may not be zero.// The pool holds *nat to avoid allocation when converting to interface{}.func ( int) *nat {var *natif := natPool.Get(); != nil { = .(*nat) }if == nil { = new(nat) } * = .make()return}func ( *nat) {natPool.Put()}varnatPoolsync.Pool// q = (uIn-r)/vIn, with 0 <= r < vIn// Uses z as storage for q, and u as storage for r if possible.// See Knuth, Volume 2, section 4.3.1, Algorithm D.// Preconditions:// len(vIn) >= 2// len(uIn) >= len(vIn)// u must not alias zfunc ( nat) (, , nat) (, nat) { := len() := len() - // D1. := nlz([-1])// do not modify vIn, it may be used by another goroutine simultaneously := getNat() := *shlVU(, , )// u may safely alias uIn or vIn, the value of uIn is used to set u and vIn was already used = .make(len() + 1) [len()] = shlVU([0:len()], , )// z may safely alias uIn or vIn, both values were used alreadyifalias(, ) { = nil// z is an alias for u - cannot reuse } = .make( + 1)if < divRecursiveThreshold { .divBasic(, ) } else { .divRecursive(, ) }putNat() = .norm()shrVU(, , ) = .norm()return , }// divBasic performs word-by-word division of u by v.// The quotient is written in pre-allocated q.// The remainder overwrites input u.//// Precondition:// - q is large enough to hold the quotient u / v// which has a maximum length of len(u)-len(v)+1.func ( nat) (, nat) { := len() := len() - := getNat( + 1) := *// D2. := [-1] := reciprocalWord()for := ; >= 0; -- {// D3. := Word(_M)varWordif + < len() { = [+] }if != {varWord , = divWW(, [+-1], , )// x1 | x2 = q̂v_{n-2} := [-2] , := mulWW(, )// test if q̂v_{n-2} > br̂ + u_{j+n-2} := [+-2]forgreaterThan(, , , ) { -- := += // v[n-1] >= 0, so this tests for overflow.if < {break } , = mulWW(, ) } }// D4. // Compute the remainder u - (q̂*v) << (_W*j). // The subtraction may overflow if q̂ estimate was off by one. [] = mulAddVWW([0:], , , 0) := len()if + > len() && [] == 0 { -- } := subVV([:+], [:], )if != 0 { := addVV([:+], [:], )// If n == qhl, the carry from subVV and the carry from addVV // cancel out and don't affect u[j+n].if < { [+] += } -- }if == && == len() && == 0 {continue } [] = }putNat()}constdivRecursiveThreshold = 100// divRecursive performs word-by-word division of u by v.// The quotient is written in pre-allocated z.// The remainder overwrites input u.//// Precondition:// - len(z) >= len(u)-len(v)//// See Burnikel, Ziegler, "Fast Recursive Division", Algorithm 1 and 2.func ( nat) (, nat) {// Recursion depth is less than 2 log2(len(v)) // Allocate a slice of temporaries to be reused across recursion. := 2 * bits.Len(uint(len()))// large enough to perform Karatsuba on operands as large as v := getNat(3 * len()) := make([]*nat, ) .clear() .divRecursiveStep(, , 0, , )for , := range {if != nil {putNat() } }putNat()}// divRecursiveStep computes the division of u by v.// - z must be large enough to hold the quotient// - the quotient will overwrite z// - the remainder will overwrite ufunc ( nat) (, nat, int, *nat, []*nat) { = .norm() = .norm()iflen() == 0 { .clear()return } := len()if < divRecursiveThreshold { .divBasic(, )return } := len() - if < 0 {return }// Produce the quotient by blocks of B words. // Division by v (length n) is done using a length n/2 division // and a length n/2 multiplication for each block. The final // complexity is driven by multiplication complexity. := / 2// Allocate a nat for qhat below.if [] == nil { [] = getNat() } else { *[] = [].make( + 1) } := for > {// Divide u[j-B:j+n] by vIn. Keep remainder in u // for next block. // // The following property will be used (Lemma 2): // if u = u1 << s + u0 // v = v1 << s + v0 // then floor(u1/v1) >= floor(u/v) // // Moreover, the difference is at most 2 if len(v1) >= len(u/v) // We choose s = B-1 since len(v)-s >= B+1 >= len(u/v) := ( - 1)// Except for the first step, the top bits are always // a division remainder, so the quotient length is <= n. := [-:] := *[] .clear() .([:+], [:], +1, , ) = .norm()// Adjust the quotient: // u = u_h << s + u_l // v = v_h << s + v_l // u_h = q̂ v_h + rh // u = q̂ (v - v_l) + rh << s + u_l // After the above step, u contains a remainder: // u = rh << s + u_l // and we need to subtract q̂ v_l // // But it may be a bit too large, in which case q̂ needs to be smaller. := .make(3 * ) .clear() = .mul(, [:])for := 0; < 2; ++ { := .cmp(.norm())if <= 0 {break }subVW(, , 1) := subVV([:], [:], [:])iflen() > {subVW([:], [:], ) }addAt([:], [:], 0) }if .cmp(.norm()) > 0 {panic("impossible") } := subVV([:len()], [:len()], )if > 0 {subVW([len():], [len():], ) }addAt(, , -) -= }// Now u < (v<<B), compute lower bits in the same way. // Choose shift = B-1 again. := - 1 := *[] .clear() .([:].norm(), [:], +1, , ) = .norm() := .make(3 * ) .clear() = .mul(, [:])// Set the correct remainder as before.for := 0; < 2; ++ {if := .cmp(.norm()); > 0 {subVW(, , 1) := subVV([:], [:], [:])iflen() > {subVW([:], [:], ) }addAt([:], [:], 0) } }if .cmp(.norm()) > 0 {panic("impossible") } := subVV([0:len()], [0:len()], )if > 0 { = subVW([len():], [len():], ) }if > 0 {panic("impossible") }// Done!addAt(, .norm(), 0)}// Length of x in bits. x must be normalized.func ( nat) () int {if := len() - 1; >= 0 {return *_W + bits.Len(uint([])) }return0}// trailingZeroBits returns the number of consecutive least significant zero// bits of x.func ( nat) () uint {iflen() == 0 {return0 }varuintfor [] == 0 { ++ }// x[i] != 0return *_W + uint(bits.TrailingZeros(uint([])))}func (, nat) bool {returnlen() == len() && len() > 0 && &[0] == &[0]}// z = x << sfunc ( nat) ( nat, uint) nat {if == 0 {ifsame(, ) {return }if !alias(, ) {return .set() } } := len()if == 0 {return [:0] }// m > 0 := + int(/_W) = .make( + 1) [] = shlVU([-:], , %_W) [0 : -].clear()return .norm()}// z = x >> sfunc ( nat) ( nat, uint) nat {if == 0 {ifsame(, ) {return }if !alias(, ) {return .set() } } := len() := - int(/_W)if <= 0 {return [:0] }// n > 0 = .make()shrVU(, [-:], %_W)return .norm()}func ( nat) ( nat, uint, uint) nat { := int( / _W) := Word(1) << ( % _W) := len()switch {case0: = .make()copy(, )if >= {// no need to growreturn } [] &^= return .norm()case1:if >= { = .make( + 1) [:].clear() } else { = .make() }copy(, ) [] |= // no need to normalizereturn }panic("set bit is not 0 or 1")}// bit returns the value of the i'th bit, with lsb == bit 0.func ( nat) ( uint) uint { := / _Wif >= uint(len()) {return0 }// 0 <= j < len(x)returnuint([] >> ( % _W) & 1)}// sticky returns 1 if there's a 1 bit within the// i least significant bits, otherwise it returns 0.func ( nat) ( uint) uint { := / _Wif >= uint(len()) {iflen() == 0 {return0 }return1 }// 0 <= j < len(x)for , := range [:] {if != 0 {return1 } }if []<<(_W-%_W) != 0 {return1 }return0}func ( nat) (, nat) nat { := len() := len()if > { = }// m <= n = .make()for := 0; < ; ++ { [] = [] & [] }return .norm()}func ( nat) (, nat) nat { := len() := len()if > { = }// m >= n = .make()for := 0; < ; ++ { [] = [] &^ [] }copy([:], [:])return .norm()}func ( nat) (, nat) nat { := len() := len() := if < { , = , = }// m >= n = .make()for := 0; < ; ++ { [] = [] | [] }copy([:], [:])return .norm()}func ( nat) (, nat) nat { := len() := len() := if < { , = , = }// m >= n = .make()for := 0; < ; ++ { [] = [] ^ [] }copy([:], [:])return .norm()}// greaterThan reports whether (x1<<_W + x2) > (y1<<_W + y2)func (, , , Word) bool {return > || == && > }// modW returns x % d.func ( nat) ( Word) ( Word) {// TODO(agl): we don't actually need to store the q value.varnat = .make(len())returndivWVW(, 0, , )}// random creates a random integer in [0..limit), using the space in z if// possible. n is the bit length of limit.func ( nat) ( *rand.Rand, nat, int) nat {ifalias(, ) { = nil// z is an alias for limit - cannot reuse } = .make(len()) := uint( % _W)if == 0 { = _W } := Word((1 << ) - 1)for {switch_W {case32:for := range { [] = Word(.Uint32()) }case64:for := range { [] = Word(.Uint32()) | Word(.Uint32())<<32 }default:panic("unknown word size") } [len()-1] &= if .cmp() < 0 {break } }return .norm()}// If m != 0 (i.e., len(m) != 0), expNN sets z to x**y mod m;// otherwise it sets z to x**y. The result is the value of z.func ( nat) (, , nat) nat {ifalias(, ) || alias(, ) {// We cannot allow in-place modification of x or y. = nil }// x**y mod 1 == 0iflen() == 1 && [0] == 1 {return .setWord(0) }// m == 0 || m > 1// x**0 == 1iflen() == 0 {return .setWord(1) }// y > 0// x**1 mod m == x mod miflen() == 1 && [0] == 1 && len() != 0 { _, = nat(nil).div(, , )return }// y > 1iflen() != 0 {// We likely end up being as long as the modulus. = .make(len()) } = .set()// If the base is non-trivial and the exponent is large, we use // 4-bit, windowed exponentiation. This involves precomputing 14 values // (x^2...x^15) but then reduces the number of multiply-reduces by a // third. Even for a 32-bit exponent, this reduces the number of // operations. Uses Montgomery method for odd moduli.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 <<= varnatconst = 1 << (_W - 1)// We walk through the bits of the exponent one by one. Each time we // see a bit, we square, thus doubling the power. If the bit is a one, // we also multiply by x, thus adding one to the power. := _W - int()// zz and r are used to avoid allocating in mul and div as // otherwise the arguments would alias.var , natfor := 0; < ; ++ { = .sqr() , = , if & != 0 { = .mul(, ) , = , }iflen() != 0 { , = .div(, , ) , , , = , , , } <<= 1 }for := len() - 2; >= 0; -- { = []for := 0; < _W; ++ { = .sqr() , = , if & != 0 { = .mul(, ) , = , }iflen() != 0 { , = .div(, , ) , , , = , , , } <<= 1 } }return .norm()}// expNNWindowed calculates x**y mod m using a fixed, 4-bit window.func ( nat) (, , nat) nat {// zz and r are used to avoid allocating in mul and div as otherwise // the arguments would alias.var , natconst = 4// powers[i] contains x^i.var [1 << ]nat [0] = natOne [1] = for := 2; < 1<<; += 2 { , , := &[/2], &[], &[+1] * = .sqr(*) , = .div(, *, ) *, = , * * = .mul(*, ) , = .div(, *, ) *, = , * } = .setWord(1)for := len() - 1; >= 0; -- { := []for := 0; < _W; += {if != len()-1 || != 0 {// Unrolled loop for significant performance // gain. Use go test -bench=".*" in crypto/rsa // to check performance before making changes. = .sqr() , = , , = .div(, , ) , = , = .sqr() , = , , = .div(, , ) , = , = .sqr() , = , , = .div(, , ) , = , = .sqr() , = , , = .div(, , ) , = , } = .mul(, [>>(_W-)]) , = , , = .div(, , ) , = , <<= } }return .norm()}// expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.// Uses Montgomery representation.func ( nat) (, , nat) nat { := len()// We want the lengths of x and m to be equal. // It is OK if x >= m as long as len(x) == len(m).iflen() > { _, = nat(nil).div(nil, , )// Note: now len(x) <= numWords, not guaranteed ==. }iflen() < { := make(nat, )copy(, ) = }// Ideally the precomputations would be performed outside, and reused // k0 = -m**-1 mod 2**_W. Algorithm from: Dumas, J.G. "On Newton–Raphson // Iteration for Multiplicative Inverses Modulo Prime Powers". := 2 - [0] := [0] - 1for := 1; < _W; <<= 1 { *= *= ( + 1) } = -// RR = 2**(2*_W*len(m)) mod m := nat(nil).setWord(1) := nat(nil).shl(, uint(2**_W)) _, = nat(nil).div(, , )iflen() < { = .make()copy(, ) = }// one = 1, with equal length to that of m := make(nat, ) [0] = 1const = 4// powers[i] contains x^ivar [1 << ]nat [0] = [0].montgomery(, , , , ) [1] = [1].montgomery(, , , , )for := 2; < 1<<; ++ { [] = [].montgomery([-1], [1], , , ) }// initialize z = 1 (Montgomery 1) = .make()copy(, [0]) = .make()// same windowed exponent, but with Montgomery multiplicationsfor := len() - 1; >= 0; -- { := []for := 0; < _W; += {if != len()-1 || != 0 { = .montgomery(, , , , ) = .montgomery(, , , , ) = .montgomery(, , , , ) = .montgomery(, , , , ) } = .montgomery(, [>>(_W-)], , , ) , = , <<= } }// convert to regular number = .montgomery(, , , , )// One last reduction, just in case. // See golang.org/issue/13907.if .cmp() >= 0 {// Common case is m has high bit set; in that case, // since zz is the same length as m, there can be just // one multiple of m to remove. Just subtract. // We think that the subtract should be sufficient in general, // so do that unconditionally, but double-check, // in case our beliefs are wrong. // The div is not expected to be reached. = .sub(, )if .cmp() >= 0 { _, = nat(nil).div(nil, , ) } }return .norm()}// bytes writes the value of z into buf using big-endian encoding.// The value of z is encoded in the slice buf[i:]. If the value of z// cannot be represented in buf, bytes panics. The number i of unused// bytes at the beginning of buf is returned as result.func ( nat) ( []byte) ( int) { = len()for , := range {for := 0; < _S; ++ { --if >= 0 { [] = byte() } elseifbyte() != 0 {panic("math/big: buffer too small to fit value") } >>= 8 } }if < 0 { = 0 }for < len() && [] == 0 { ++ }return}// bigEndianWord returns the contents of buf interpreted as a big-endian encoded Word value.func ( []byte) Word {if_W == 64 {returnWord(binary.BigEndian.Uint64()) }returnWord(binary.BigEndian.Uint32())}// setBytes interprets buf as the bytes of a big-endian unsigned// integer, sets z to that value, and returns z.func ( nat) ( []byte) nat { = .make((len() + _S - 1) / _S) := len()for := 0; >= _S; ++ { [] = bigEndianWord([-_S : ]) -= _S }if > 0 {varWordfor := uint(0); > 0; += 8 { |= Word([-1]) << -- } [len()-1] = }return .norm()}// sqrt sets z = ⌊√x⌋func ( nat) ( nat) nat {if .cmp(natOne) <= 0 {return .set() }ifalias(, ) { = nil }// Start with value known to be too large and repeat "z = ⌊(z + ⌊x/z⌋)/2⌋" until it stops getting smaller. // See Brent and Zimmermann, Modern Computer Arithmetic, Algorithm 1.13 (SqrtInt). // https://members.loria.fr/PZimmermann/mca/pub226.html // If x is one less than a perfect square, the sequence oscillates between the correct z and z+1; // otherwise it converges to the correct z and stays there.var , nat = = .setUint64(1) = .shl(, uint(.bitLen()+1)/2) // must be ≥ √xfor := 0; ; ++ { , _ = .div(nil, , ) = .add(, ) = .shr(, 1)if .cmp() >= 0 {// z1 is answer. // Figure out whether z1 or z2 is currently aliased to z by looking at loop count.if &1 == 0 {return }return .set() } , = , }}