Fix an issue in Barrett reduction.
This commit is contained in:
@@ -50,8 +50,10 @@ needs = [ Need ModExp (\ size -> [Req size ModMul
|
|||||||
,Req (size + 64) Mul
|
,Req (size + 64) Mul
|
||||||
,Req (size * 2) (Convert ((size * 2) + 64))
|
,Req (size * 2) (Convert ((size * 2) + 64))
|
||||||
,Req ((size * 2) + 64) Shifts
|
,Req ((size * 2) + 64) Shifts
|
||||||
|
,Req ((size * 2) + 128) Shifts
|
||||||
,Req ((size * 2) + 64) Div
|
,Req ((size * 2) + 64) Div
|
||||||
,Req (size + 64) (Convert (size * 2))
|
,Req (size + 64) (Convert (size * 2))
|
||||||
|
,Req (size + 64) (Convert ((size * 2) + 128))
|
||||||
,Req ((size * 2) + 64)
|
,Req ((size * 2) + 64)
|
||||||
(Convert ((size * 2) + 128))
|
(Convert ((size * 2) + 128))
|
||||||
])
|
])
|
||||||
@@ -254,7 +256,7 @@ generateAllTheTests =
|
|||||||
let (db3, gen3) = emptyDatabase gen2
|
let (db3, gen3) = emptyDatabase gen2
|
||||||
generateTests Barretts "barrett_reduce" db3 $ \ size memory0 ->
|
generateTests Barretts "barrett_reduce" db3 $ \ size memory0 ->
|
||||||
let (m, memory1) = generateNum memory0 "m" size
|
let (m, memory1) = generateNum memory0 "m" size
|
||||||
(x, memory2) = generateNum memory1 "x" (min size (2 * k * 64))
|
(x, memory2) = generateNum memory1 "x" (min (2 * size) (2 * k * 64))
|
||||||
k = computeK m
|
k = computeK m
|
||||||
u = barrett m
|
u = barrett m
|
||||||
r = x `mod` m
|
r = x `mod` m
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ macro_rules! barrett_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reduce(&self, x: &$dbl) -> $name {
|
pub fn reduce(&self, x: &$dbl) -> $name {
|
||||||
let m2: $dbl64 = $dbl64::from(&self.m);
|
|
||||||
// 1. q1←⌊x/bk−1⌋, q2←q1 · μ, q3←⌊q2/bk+1⌋.
|
// 1. q1←⌊x/bk−1⌋, q2←q1 · μ, q3←⌊q2/bk+1⌋.
|
||||||
let q1: $name64 = $name64::from(x >> ((self.k - 1) * 64));
|
let q1: $name64 = $name64::from(x >> ((self.k - 1) * 64));
|
||||||
let q2: $dbl64 = $dbl64::from(q1 * &self.mu);
|
let q2 = q1 * &self.mu;
|
||||||
let q3: $name64 = $name64::from(q2 >> ((self.k + 1) * 64));
|
let q3: $name64 = $name64::from(q2 >> ((self.k + 1) * 64));
|
||||||
// 2. r1←x mod bk+1, r2←q3 · m mod bk+1, r←r1 − r2.
|
// 2. r1←x mod bk+1, r2←q3 · m mod bk+1, r←r1 − r2.
|
||||||
let mut r: $dbl64 = $dbl64::from(x);
|
let mut r: $dbl64 = $dbl64::from(x);
|
||||||
@@ -45,9 +44,11 @@ macro_rules! barrett_impl {
|
|||||||
if went_negative {
|
if went_negative {
|
||||||
let mut bk1 = $dbl64::zero();
|
let mut bk1 = $dbl64::zero();
|
||||||
bk1.value[self.k+1] = 1;
|
bk1.value[self.k+1] = 1;
|
||||||
|
// this may overflow, and we should probably be OK with it.
|
||||||
r += &bk1;
|
r += &bk1;
|
||||||
}
|
}
|
||||||
// 4. While r≥m do: r←r−m.
|
// 4. While r≥m do: r←r−m.
|
||||||
|
let m2 = $dbl64::from(&self.m);
|
||||||
while &r > &m2 {
|
while &r > &m2 {
|
||||||
r -= &m2;
|
r -= &m2;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user