mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-02 05:57:46 +00:00
factor::numeric::DoubleInt: Clarify methods and associated types
- `DoubleInt::Double` renamed to `DoubleWidth` - `{as,from}_double()` renamed to `{as,from}_double_width()`. This should hopefully clarify that this is not a “double precision” floating-point type, but an integer type with a larger range (used for storing intermediate results, typ. from a multiplication)
This commit is contained in:
parent
86a4749e3a
commit
1172af09c0
1 changed files with 18 additions and 17 deletions
|
@ -80,23 +80,23 @@ pub(crate) struct Montgomery<T: DoubleInt> {
|
||||||
|
|
||||||
impl<T: DoubleInt> Montgomery<T> {
|
impl<T: DoubleInt> Montgomery<T> {
|
||||||
/// computes x/R mod n efficiently
|
/// computes x/R mod n efficiently
|
||||||
fn reduce(&self, x: T::Double) -> T {
|
fn reduce(&self, x: T::DoubleWidth) -> T {
|
||||||
let t_bits = T::zero().count_zeros() as usize;
|
let t_bits = T::zero().count_zeros() as usize;
|
||||||
|
|
||||||
debug_assert!(x < (self.n.as_double()) << t_bits);
|
debug_assert!(x < (self.n.as_double_width()) << t_bits);
|
||||||
// TODO: optimiiiiiiise
|
// TODO: optimiiiiiiise
|
||||||
let Montgomery { a, n } = self;
|
let Montgomery { a, n } = self;
|
||||||
let m = T::from_double(x).wrapping_mul(a);
|
let m = T::from_double_width(x).wrapping_mul(a);
|
||||||
let nm = (n.as_double()) * (m.as_double());
|
let nm = (n.as_double_width()) * (m.as_double_width());
|
||||||
let (xnm, overflow) = x.overflowing_add_(nm); // x + n*m
|
let (xnm, overflow) = x.overflowing_add_(nm); // x + n*m
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
xnm % (T::Double::one() << T::zero().count_zeros() as usize),
|
xnm % (T::DoubleWidth::one() << T::zero().count_zeros() as usize),
|
||||||
T::Double::zero()
|
T::DoubleWidth::zero()
|
||||||
);
|
);
|
||||||
|
|
||||||
// (x + n*m) / R
|
// (x + n*m) / R
|
||||||
// in case of overflow, this is (2¹²⁸ + xnm)/2⁶⁴ - n = xnm/2⁶⁴ + (2⁶⁴ - n)
|
// in case of overflow, this is (2¹²⁸ + xnm)/2⁶⁴ - n = xnm/2⁶⁴ + (2⁶⁴ - n)
|
||||||
let y = T::from_double(xnm >> t_bits)
|
let y = T::from_double_width(xnm >> t_bits)
|
||||||
+ if !overflow {
|
+ if !overflow {
|
||||||
T::zero()
|
T::zero()
|
||||||
} else {
|
} else {
|
||||||
|
@ -131,15 +131,16 @@ impl<T: DoubleInt> Arithmetic for Montgomery<T> {
|
||||||
fn from_u64(&self, x: u64) -> Self::ModInt {
|
fn from_u64(&self, x: u64) -> Self::ModInt {
|
||||||
// TODO: optimise!
|
// TODO: optimise!
|
||||||
debug_assert!(x < self.n.as_u64());
|
debug_assert!(x < self.n.as_u64());
|
||||||
let r = T::from_double(
|
let r = T::from_double_width(
|
||||||
((T::Double::from_u64(x)) << T::zero().count_zeros() as usize) % self.n.as_double(),
|
((T::DoubleWidth::from_u64(x)) << T::zero().count_zeros() as usize)
|
||||||
|
% self.n.as_double_width(),
|
||||||
);
|
);
|
||||||
debug_assert_eq!(x, self.to_u64(r));
|
debug_assert_eq!(x, self.to_u64(r));
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_u64(&self, n: Self::ModInt) -> u64 {
|
fn to_u64(&self, n: Self::ModInt) -> u64 {
|
||||||
self.reduce(n.as_double()).as_u64()
|
self.reduce(n.as_double_width()).as_u64()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
|
fn add(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
|
||||||
|
@ -173,7 +174,7 @@ impl<T: DoubleInt> Arithmetic for Montgomery<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mul(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
|
fn mul(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
|
||||||
let r = self.reduce(a.as_double() * b.as_double());
|
let r = self.reduce(a.as_double_width() * b.as_double_width());
|
||||||
|
|
||||||
// Check that r (reduced back to the usual representation) equals
|
// Check that r (reduced back to the usual representation) equals
|
||||||
// a*b % n
|
// a*b % n
|
||||||
|
@ -223,10 +224,10 @@ pub(crate) trait Int:
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait DoubleInt: Int {
|
pub(crate) trait DoubleInt: Int {
|
||||||
type Double: Int;
|
type DoubleWidth: Int;
|
||||||
|
|
||||||
fn as_double(self) -> Self::Double;
|
fn as_double_width(self) -> Self::DoubleWidth;
|
||||||
fn from_double(n: Self::Double) -> Self;
|
fn from_double_width(n: Self::DoubleWidth) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! int {
|
macro_rules! int {
|
||||||
|
@ -253,12 +254,12 @@ macro_rules! double_int {
|
||||||
( $x:ty, $y:ty ) => {
|
( $x:ty, $y:ty ) => {
|
||||||
int!($x);
|
int!($x);
|
||||||
impl DoubleInt for $x {
|
impl DoubleInt for $x {
|
||||||
type Double = $y;
|
type DoubleWidth = $y;
|
||||||
|
|
||||||
fn as_double(self) -> $y {
|
fn as_double_width(self) -> $y {
|
||||||
self as _
|
self as _
|
||||||
}
|
}
|
||||||
fn from_double(n: $y) -> $x {
|
fn from_double_width(n: $y) -> $x {
|
||||||
n as _
|
n as _
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue