github.com/cloudflare/circl@v1.5.0/pke/kyber/internal/common/field.go (about) 1 package common 2 3 // Given -2¹⁵ q ≤ x < 2¹⁵ q, returns -q < y < q with x 2⁻¹⁶ = y (mod q). 4 func montReduce(x int32) int16 { 5 // This is Montgomery reduction with R=2¹⁶. 6 // 7 // Note gcd(2¹⁶, q) = 1 as q is prime. Write q' := 62209 = q⁻¹ mod R. 8 // First we compute 9 // 10 // m := ((x mod R) q') mod R 11 // = x q' mod R 12 // = int16(x q') 13 // = int16(int32(x) * int32(q')) 14 // 15 // Note that x q' might be as big as 2³² and could overflow the int32 16 // multiplication in the last line. However for any int32s a and b, 17 // we have int32(int64(a)*int64(b)) = int32(a*b) and so the result is ok. 18 m := int16(x * 62209) 19 20 // Note that x - m q is divisible by R; indeed modulo R we have 21 // 22 // x - m q ≡ x - x q' q ≡ x - x q⁻¹ q ≡ x - x = 0. 23 // 24 // We return y := (x - m q) / R. Note that y is indeed correct as 25 // modulo q we have 26 // 27 // y ≡ x R⁻¹ - m q R⁻¹ = x R⁻¹ 28 // 29 // and as both 2¹⁵ q ≤ m q, x < 2¹⁵ q, we have 30 // 2¹⁶ q ≤ x - m q < 2¹⁶ and so q ≤ (x - m q) / R < q as desired. 31 return int16(uint32(x-int32(m)*int32(Q)) >> 16) 32 } 33 34 // Given any x, returns x R mod q where R=2¹⁶. 35 func toMont(x int16) int16 { 36 // Note |1353 x| ≤ 1353 2¹⁵ ≤ 13318 q ≤ 2¹⁵ q and so we're within 37 // the bounds of montReduce. 38 return montReduce(int32(x) * 1353) // 1353 = R² mod q. 39 } 40 41 // Given any x, compute 0 ≤ y ≤ q with x = y (mod q). 42 // 43 // Beware: we might have barrettReduce(x) = q ≠ 0 for some x. In fact, 44 // this happens if and only if x = -nq for some positive integer n. 45 func barrettReduce(x int16) int16 { 46 // This is standard Barrett reduction. 47 // 48 // For any x we have x mod q = x - ⌊x/q⌋ q. We will use 20159/2²⁶ as 49 // an approximation of 1/q. Note that 0 ≤ 20159/2²⁶ - 1/q ≤ 0.135/2²⁶ 50 // and so | x 20156/2²⁶ - x/q | ≤ 2⁻¹⁰ for |x| ≤ 2¹⁶. For all x 51 // not a multiple of q, the number x/q is further than 1/q from any integer 52 // and so ⌊x 20156/2²⁶⌋ = ⌊x/q⌋. If x is a multiple of q and x is positive, 53 // then x 20156/2²⁶ is larger than x/q so ⌊x 20156/2²⁶⌋ = ⌊x/q⌋ as well. 54 // Finally, if x is negative multiple of q, then ⌊x 20156/2²⁶⌋ = ⌊x/q⌋-1. 55 // Thus 56 // [ q if x=-nq for pos. integer n 57 // x - ⌊x 20156/2²⁶⌋ q = [ 58 // [ x mod q otherwise 59 // 60 // To compute actually compute this, note that 61 // 62 // ⌊x 20156/2²⁶⌋ = (20159 x) >> 26. 63 return x - int16((int32(x)*20159)>>26)*Q 64 } 65 66 // Returns x if x < q and x - q otherwise. Assumes x ≥ -29439. 67 func csubq(x int16) int16 { 68 x -= Q // no overflow due to assumption x ≥ -29439. 69 // If x is positive, then x >> 15 = 0. If x is negative, 70 // then uint16(x >> 15) = 2¹⁶-1. So this will add back in q 71 // if x was smaller than q. 72 x += (x >> 15) & Q 73 return x 74 }