1
Fork 0
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:
nicoo 2020-07-21 19:39:47 +02:00 committed by Roy Ivy III
parent 86a4749e3a
commit 1172af09c0

View file

@ -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 _
} }
} }