github.com/cloudflare/circl@v1.5.0/sign/internal/dilithium/field.go (about)

     1  package dilithium
     2  
     3  // Returns a y with y < 2q and y = x mod q.
     4  // Note that in general *not*: ReduceLe2Q(ReduceLe2Q(x)) == x.
     5  func ReduceLe2Q(x uint32) uint32 {
     6  	// Note 2²³ = 2¹³ - 1 mod q. So, writing  x = x₁ 2²³ + x₂ with x₂ < 2²³
     7  	// and x₁ < 2⁹, we have x = y (mod q) where
     8  	// y = x₂ + x₁ 2¹³ - x₁ ≤ 2²³ + 2¹³ < 2q.
     9  	x1 := x >> 23
    10  	x2 := x & 0x7FFFFF // 2²³-1
    11  	return x2 + (x1 << 13) - x1
    12  }
    13  
    14  // Returns x mod q.
    15  func modQ(x uint32) uint32 {
    16  	return le2qModQ(ReduceLe2Q(x))
    17  }
    18  
    19  // For x R ≤ q 2³², find y ≤ 2q with y = x mod q.
    20  func montReduceLe2Q(x uint64) uint32 {
    21  	// Qinv = 4236238847 = -(q⁻¹) mod 2³²
    22  	m := (x * Qinv) & 0xffffffff
    23  	return uint32((x + m*uint64(Q)) >> 32)
    24  }
    25  
    26  // Returns x mod q for 0 ≤ x < 2q.
    27  func le2qModQ(x uint32) uint32 {
    28  	x -= Q
    29  	mask := uint32(int32(x) >> 31) // mask is 2³²-1 if x was neg.; 0 otherwise
    30  	return x + (mask & Q)
    31  }
    32  
    33  // Splits 0 ≤ a < Q into a0 and a1 with a = a1*2ᴰ + a0
    34  // and -2ᴰ⁻¹ < a0 < 2ᴰ⁻¹.  Returns a0 + Q and a1.
    35  func power2round(a uint32) (a0plusQ, a1 uint32) {
    36  	// We effectively compute a0 = a mod± 2ᵈ
    37  	//                    and a1 = (a - a0) / 2ᵈ.
    38  	a0 := a & ((1 << D) - 1) // a mod 2ᵈ
    39  
    40  	// a0 is one of  0, 1, ..., 2ᵈ⁻¹-1, 2ᵈ⁻¹, 2ᵈ⁻¹+1, ..., 2ᵈ-1
    41  	a0 -= (1 << (D - 1)) + 1
    42  	// now a0 is     -2ᵈ⁻¹-1, -2ᵈ⁻¹, ..., -2, -1, 0, ..., 2ᵈ⁻¹-2
    43  	// Next, we add 2ᴰ to those a0 that are negative (seen as int32).
    44  	a0 += uint32(int32(a0)>>31) & (1 << D)
    45  	// now a0 is     2ᵈ⁻¹-1, 2ᵈ⁻¹, ..., 2ᵈ-2, 2ᵈ-1, 0, ..., 2ᵈ⁻¹-2
    46  	a0 -= (1 << (D - 1)) - 1
    47  	// now a0 id     0, 1, 2, ..., 2ᵈ⁻¹-1, 2ᵈ⁻¹-1, -2ᵈ⁻¹-1, ...
    48  	// which is what we want.
    49  	a0plusQ = Q + a0
    50  	a1 = (a - a0) >> D
    51  	return
    52  }