Initial commit!
This commit is contained in:
98
src/unsigned/add.rs
Normal file
98
src/unsigned/add.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
pub fn addition(dest: &mut [u64], src: &[u64])
|
||||
{
|
||||
assert_eq!(dest.len(), src.len() + 1);
|
||||
let mut carry: u128 = 0;
|
||||
|
||||
for i in 0..src.len() {
|
||||
let x128 = dest[i] as u128;
|
||||
let y128 = src[i] as u128;
|
||||
let z128 = x128 + y128 + carry;
|
||||
|
||||
dest[i] = z128 as u64;
|
||||
carry = z128 >> 64;
|
||||
}
|
||||
dest[src.len()] = carry as u64;
|
||||
}
|
||||
|
||||
pub fn unsafe_addition(dest: &mut [u64], src: &[u64])
|
||||
{
|
||||
assert_eq!(dest.len(), src.len());
|
||||
let mut carry: u128 = 0;
|
||||
|
||||
for i in 0..src.len() {
|
||||
let x128 = dest[i] as u128;
|
||||
let y128 = src[i] as u128;
|
||||
let z128 = x128 + y128 + carry;
|
||||
|
||||
dest[i] = z128 as u64;
|
||||
carry = z128 >> 64;
|
||||
}
|
||||
assert_eq!(carry, 0, "Unsafe overflow in AddAssign");
|
||||
}
|
||||
|
||||
macro_rules! addition_impls
|
||||
{
|
||||
($base: ident, $bigger: ident) => {
|
||||
impl AddAssign<$base> for $base {
|
||||
fn add_assign(&mut self, rhs: $base) {
|
||||
unsafe_addition(&mut self.value, &rhs.value);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AddAssign<&'a $base> for $base {
|
||||
fn add_assign(&mut self, rhs: &$base) {
|
||||
unsafe_addition(&mut self.value, &rhs.value);
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$base> for $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: $base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a $base> for $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: &$base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<$base> for &'a $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: $base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Add<&'a $base> for &'b $base {
|
||||
type Output = $bigger;
|
||||
|
||||
fn add(self, rhs: &$base) -> $bigger
|
||||
{
|
||||
let mut dest = $bigger::zero();
|
||||
&dest.value[0..rhs.value.len()].copy_from_slice(&self.value);
|
||||
addition(&mut dest.value, &rhs.value);
|
||||
dest
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//addition_impls!(U192, U256);
|
||||
59
src/unsigned/barrett.rs
Normal file
59
src/unsigned/barrett.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
macro_rules! barrett_impl {
|
||||
($bar: ident, $name: ident, $name64: ident, $dbl: ident, $dbl64: ident) => {
|
||||
pub struct $bar {
|
||||
pub(crate) k: usize,
|
||||
pub(crate) m: $name64,
|
||||
pub(crate) mu: $name64
|
||||
}
|
||||
|
||||
impl $bar {
|
||||
pub fn new(m: $name) -> $bar {
|
||||
// Step #1: Figure out k
|
||||
let mut k = 0;
|
||||
for i in 0..m.value.len() {
|
||||
if m.value[i] != 0 {
|
||||
k = i;
|
||||
}
|
||||
}
|
||||
k += 1;
|
||||
// Step #2: Compute b
|
||||
let mut b = $dbl64::zero();
|
||||
b.value[2*k] = 1;
|
||||
// Step #3: Divide b by m.
|
||||
let bigm = $dbl64::from(&m);
|
||||
let quot = b / &bigm;
|
||||
let resm = $name64::from(&m);
|
||||
let mu = $name64::from(");
|
||||
// Done!
|
||||
$bar { k: k, m: resm, mu: mu }
|
||||
}
|
||||
|
||||
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⌋.
|
||||
let q1: $name64 = $name64::from(x >> (self.k - 1));
|
||||
let q2: $dbl64 = $dbl64::from(q1 * &self.mu);
|
||||
let q3: $name64 = $name64::from(q2 >> (self.k + 1));
|
||||
// 2. r1←x mod bk+1, r2←q3 · m mod bk+1, r←r1 − r2.
|
||||
let mut r: $dbl64 = $dbl64::from(x);
|
||||
r.mask(self.k + 1);
|
||||
let mut r2: $dbl64 = $dbl64::from(q3 * &self.m);
|
||||
r2.mask(self.k + 1);
|
||||
let went_negative = &r < &r2;
|
||||
r -= &r2;
|
||||
// 3. If r<0 then r←r+bk+1.
|
||||
if went_negative {
|
||||
let mut bk1 = $dbl64::zero();
|
||||
bk1.value[self.k+1] = 1;
|
||||
r += &bk1;
|
||||
}
|
||||
// 4. While r≥m do: r←r−m.
|
||||
while &r > &m2 {
|
||||
r -= &m2;
|
||||
}
|
||||
// Done!
|
||||
$name::from(&r)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
83
src/unsigned/base.rs
Normal file
83
src/unsigned/base.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
pub trait CryptoNum {
|
||||
fn zero() -> Self;
|
||||
fn is_zero(&self) -> bool;
|
||||
fn is_even(&self) -> bool;
|
||||
fn is_odd(&self) -> bool;
|
||||
fn mask(&mut self, len: usize);
|
||||
}
|
||||
|
||||
macro_rules! generate_base
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
#[derive(Clone)]
|
||||
pub struct $name {
|
||||
pub(crate) value: [u64; $size]
|
||||
}
|
||||
|
||||
impl CryptoNum for $name {
|
||||
fn zero() -> $name {
|
||||
$name{ value: [0; $size] }
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.value.iter().all(|&x| x == 0)
|
||||
}
|
||||
|
||||
fn is_even(&self) -> bool {
|
||||
(self.value[0] & 0x1) == 0
|
||||
}
|
||||
|
||||
fn is_odd(&self) -> bool {
|
||||
(self.value[0] & 0x1) == 1
|
||||
}
|
||||
|
||||
fn mask(&mut self, len: usize) {
|
||||
let dellen = min(len, $size);
|
||||
for i in dellen..$size {
|
||||
self.value[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! generate_base_tests
|
||||
{
|
||||
($name: ident) => {
|
||||
impl fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(stringify!($name))?;
|
||||
f.write_str("{")?;
|
||||
f.debug_list().entries(self.value.iter()).finish()?;
|
||||
f.write_str("}")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn $name() {
|
||||
let fname = format!("testdata/base/{}.tests", stringify!($name));
|
||||
run_test(fname.to_string(), 6, |case| {
|
||||
let (neg0, xbytes) = case.get("x").unwrap();
|
||||
let (neg1, mbytes) = case.get("m").unwrap();
|
||||
let (neg2, zbytes) = case.get("z").unwrap();
|
||||
let (neg3, ebytes) = case.get("e").unwrap();
|
||||
let (neg4, obytes) = case.get("o").unwrap();
|
||||
let (neg5, rbytes) = case.get("r").unwrap();
|
||||
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5);
|
||||
let mut x = $name::from_bytes(xbytes);
|
||||
let m = $name::from_bytes(mbytes);
|
||||
let z = 1 == zbytes[0];
|
||||
let e = 1 == ebytes[0];
|
||||
let o = 1 == obytes[0];
|
||||
let r = $name::from_bytes(rbytes);
|
||||
assert_eq!(x.is_zero(), z);
|
||||
assert_eq!(x.is_even(), e);
|
||||
assert_eq!(x.is_odd(), o);
|
||||
x.mask(usize::from(&m));
|
||||
assert_eq!(x, r);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/unsigned/cmp.rs
Normal file
42
src/unsigned/cmp.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use std::cmp::*;
|
||||
|
||||
pub fn compare(a: &[u64], b: &[u64]) -> Ordering {
|
||||
assert_eq!(a.len(), b.len(), "Incompatible numbers in comparison");
|
||||
|
||||
let mut i = (a.len() - 1) as isize;
|
||||
|
||||
while i >= 0 {
|
||||
let iu = i as usize;
|
||||
match a[iu].cmp(&b[iu]) {
|
||||
Ordering::Greater => return Ordering::Greater,
|
||||
Ordering::Less => return Ordering::Less,
|
||||
Ordering::Equal => i -= 1
|
||||
}
|
||||
}
|
||||
|
||||
Ordering::Equal
|
||||
}
|
||||
|
||||
macro_rules! cmp_impls {
|
||||
($name: ident) => {
|
||||
impl PartialEq for $name {
|
||||
fn eq(&self, rhs: &$name) -> bool {
|
||||
compare(&self.value, &rhs.value) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for $name {}
|
||||
|
||||
impl PartialOrd for $name {
|
||||
fn partial_cmp(&self, rhs: &$name) -> Option<Ordering> {
|
||||
Some(compare(&self.value, &rhs.value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $name {
|
||||
fn cmp(&self, rhs: &$name) -> Ordering {
|
||||
compare(&self.value, &rhs.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
src/unsigned/codec.rs
Normal file
70
src/unsigned/codec.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
pub trait Decoder {
|
||||
fn from_bytes(x: &[u8]) -> Self;
|
||||
}
|
||||
|
||||
pub trait Encoder {
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
pub(crate) fn raw_decoder(input: &[u8], output: &mut [u64])
|
||||
{
|
||||
let mut item = 0;
|
||||
let mut shift = 0;
|
||||
let mut idx = 0;
|
||||
|
||||
for v in input.iter().rev() {
|
||||
item |= (*v as u64) << shift;
|
||||
shift += 8;
|
||||
if shift == 64 {
|
||||
shift = 0;
|
||||
output[idx] = item;
|
||||
idx += 1;
|
||||
item = 0;
|
||||
}
|
||||
}
|
||||
if item != 0 {
|
||||
output[idx] = item;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! generate_decoder {
|
||||
($name: ident) => {
|
||||
impl Decoder for $name {
|
||||
fn from_bytes(x: &[u8]) -> $name {
|
||||
let mut res = $name::zero();
|
||||
raw_decoder(x, &mut res.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! generate_encoder {
|
||||
($name: ident) => {
|
||||
impl Encoder for $name {
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut res = Vec::with_capacity(self.value.len() * 8);
|
||||
for v in self.value.iter().rev() {
|
||||
let val = *v;
|
||||
res.push( (val >> 56) as u8);
|
||||
res.push( (val >> 48) as u8);
|
||||
res.push( (val >> 40) as u8);
|
||||
res.push( (val >> 32) as u8);
|
||||
res.push( (val >> 24) as u8);
|
||||
res.push( (val >> 16) as u8);
|
||||
res.push( (val >> 8) as u8);
|
||||
res.push( (val >> 0) as u8);
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! generate_codec
|
||||
{
|
||||
($name: ident) => {
|
||||
generate_decoder!($name);
|
||||
generate_encoder!($name);
|
||||
}
|
||||
}
|
||||
83
src/unsigned/conversion.rs
Normal file
83
src/unsigned/conversion.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
macro_rules! generate_base_conversions
|
||||
{
|
||||
($name: ident) => {
|
||||
generate_base_type_convert!($name, u8);
|
||||
generate_base_type_convert!($name, u16);
|
||||
generate_base_type_convert!($name, u32);
|
||||
generate_base_type_convert!($name, u64);
|
||||
generate_base_type_convert!($name, usize);
|
||||
|
||||
impl From<u128> for $name {
|
||||
fn from(x: u128) -> $name {
|
||||
let mut res = $name::zero();
|
||||
res.value[0] = x as u64;
|
||||
res.value[1] = (x >> 64) as u64;
|
||||
res
|
||||
}
|
||||
}
|
||||
};
|
||||
() => {};
|
||||
}
|
||||
|
||||
macro_rules! conversion_impls
|
||||
{
|
||||
($name: ident, $other: ident) => {
|
||||
impl<'a> From<&'a $other> for $name {
|
||||
fn from(x: &$other) -> $name {
|
||||
let mut res = $name::zero();
|
||||
let len = res.value.len();
|
||||
assert!(x.value.len() > res.value.len());
|
||||
res.value.copy_from_slice(&x.value[0..len]);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $name> for $other {
|
||||
fn from(x: &$name) -> $other {
|
||||
let mut res = $other::zero();
|
||||
let len = x.value.len();
|
||||
|
||||
assert!(x.value.len() < res.value.len());
|
||||
res.value[0..len].copy_from_slice(&x.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$other> for $name {
|
||||
fn from(x: $other) -> $name {
|
||||
$name::from(&x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for $other {
|
||||
fn from(x: $name) -> $other {
|
||||
$other::from(&x)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! generate_base_type_convert
|
||||
{
|
||||
($name: ident, $base: ident) => {
|
||||
impl From<$base> for $name {
|
||||
fn from(x: $base) -> $name {
|
||||
let mut res = $name::zero();
|
||||
res.value[0] = x as u64;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for $base {
|
||||
fn from(x: $name) -> $base {
|
||||
x.value[0] as $base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $name> for $base {
|
||||
fn from(x: &$name) -> $base {
|
||||
x.value[0] as $base
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
222
src/unsigned/div.rs
Normal file
222
src/unsigned/div.rs
Normal file
@@ -0,0 +1,222 @@
|
||||
pub trait DivMod
|
||||
where Self: Sized
|
||||
{
|
||||
fn divmod(&self, rhs: &Self) -> (Self, Self);
|
||||
}
|
||||
|
||||
pub fn get_number_size(v: &[u64]) -> Option<usize>
|
||||
{
|
||||
for (idx, val) in v.iter().enumerate().rev() {
|
||||
if *val != 0 {
|
||||
return Some(idx);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
macro_rules! safesubidx
|
||||
{
|
||||
($array: expr, $index: expr, $amt: expr) => ({
|
||||
let idx = $index;
|
||||
let amt = $amt;
|
||||
|
||||
if idx < amt {
|
||||
0
|
||||
} else {
|
||||
$array[idx-amt]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! div_impls
|
||||
{
|
||||
($name: ident, $dbl: ident) => {
|
||||
impl DivMod for $name {
|
||||
fn divmod(&self, rhs: &$name) -> ($name, $name) {
|
||||
// if the divisor is larger, then the answer is pretty simple
|
||||
if rhs > self {
|
||||
return ($name::zero(), self.clone());
|
||||
}
|
||||
// compute the basic number sizes
|
||||
let mut n = match get_number_size(&self.value) {
|
||||
None => 0,
|
||||
Some(v) => v
|
||||
};
|
||||
let t = match get_number_size(&rhs.value) {
|
||||
None => panic!("Division by zero!"),
|
||||
Some(v) => v
|
||||
};
|
||||
assert!(t <= n);
|
||||
// now generate mutable versions we can mess with
|
||||
let mut x = $dbl::from(self);
|
||||
let mut y = $dbl::from(rhs);
|
||||
// If we want this to perform reasonable, it's useful if the
|
||||
// value of y[t] is shifted so that the high bit is set.
|
||||
let lambda_shift = y.value[t].leading_zeros() as usize;
|
||||
if lambda_shift != 0 {
|
||||
let dupx = x.value.clone();
|
||||
let dupy = y.value.clone();
|
||||
|
||||
shiftl(&mut x.value, &dupx, lambda_shift);
|
||||
shiftl(&mut y.value, &dupy, lambda_shift);
|
||||
n = get_number_size(&x.value).unwrap();
|
||||
}
|
||||
// now go!
|
||||
// 1. For j from 0 to (n-t) do: q[j] = 0;
|
||||
// [NB: I take some liberties with this concept]
|
||||
let mut q = $dbl::zero();
|
||||
// 2. While (x >= y * b^(n-t)) do the following:
|
||||
let mut ybnt = $dbl::zero();
|
||||
for i in 0..self.value.len() {
|
||||
ybnt.value[(n-t)+i] = y.value[i];
|
||||
if (n-t)+i >= ybnt.value.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while x > ybnt {
|
||||
q.value[n - t] += 1;
|
||||
x -= &ybnt;
|
||||
}
|
||||
// 3. For i from n down to t+1 do the following:
|
||||
let mut i = n;
|
||||
while i >= (t + 1) {
|
||||
// 3.1. If x[i] = y[t]
|
||||
if x.value[i] == y.value[t] {
|
||||
// ... then set q[i-t-1] = b - 1
|
||||
q.value[i-t-1] = 0xFFFFFFFFFFFFFFFF;
|
||||
} else {
|
||||
// ... otherwise set q[i-t-1] =
|
||||
// floor((x[i] * b + x[i-1]) / y[t])
|
||||
let xib = (x.value[i] as u128) << 64;
|
||||
let xi1 = safesubidx!(x.value,i,1) as u128;
|
||||
let yt = y.value[t] as u128;
|
||||
let qit1 = (xib + xi1) / yt;
|
||||
q.value[i-t-1] = qit1 as u64;
|
||||
}
|
||||
// 3.2. While q[i-t-1] * (y[t]*b + y[t-1]) >
|
||||
// (x[i] * b^2 + x[i-1] * b + x[i-2])
|
||||
loop {
|
||||
// three is very close to 2.
|
||||
let qit1 = U192::from(safesubidx!(q.value,i-t,1));
|
||||
let mut ybits = U192::zero();
|
||||
ybits.value[0] = safesubidx!(y.value, t, 1);
|
||||
ybits.value[1] = y.value[t];
|
||||
let qiybs = &qit1 * &ybits;
|
||||
let mut xbits = U384::zero();
|
||||
xbits.value[0] = safesubidx!(x.value,i,2);
|
||||
xbits.value[1] = safesubidx!(x.value,i,1);
|
||||
xbits.value[2] = x.value[i];
|
||||
|
||||
if !(&qiybs > &xbits) {
|
||||
break;
|
||||
}
|
||||
|
||||
// ... do q[i-t-1] = q[i-t-1] - 1
|
||||
q.value[i-t-1] -= 1;
|
||||
}
|
||||
// 3.3. x = x - q[i-t-1] * y * b^(i-t-1)
|
||||
// 3.4. If x < 0
|
||||
// then set x = x + y * b^(i-t-1) and
|
||||
// q[i-t-1] = q[i-t-1] - 1
|
||||
let mut qbit1 = $name::zero();
|
||||
qbit1.value[i-t-1] = q.value[i-t-1];
|
||||
let smallery = $name::from(&y);
|
||||
let mut subpart = &smallery * &qbit1;
|
||||
if subpart > x {
|
||||
let mut addback = $dbl::zero();
|
||||
for (idx, val) in y.value.iter().enumerate() {
|
||||
let dest = idx + (i - t - 1);
|
||||
if dest < addback.value.len() {
|
||||
addback.value[dest] = *val;
|
||||
}
|
||||
}
|
||||
q.value[i-t-1] -= 1;
|
||||
subpart -= &addback;
|
||||
}
|
||||
assert!(subpart <= x);
|
||||
x -= &subpart;
|
||||
i -= 1;
|
||||
}
|
||||
// 4. r = x ... sort of. Remember, we potentially did a bit of shifting
|
||||
// around at the very beginning, which we now need to account for. On the
|
||||
// bright side, we only need to account for this in the remainder.
|
||||
let mut r = $name::from(&x);
|
||||
let dupr = r.value.clone();
|
||||
shiftr(&mut r.value, &dupr, lambda_shift);
|
||||
// 5. Return (q,r)
|
||||
let resq = $name::from(&q);
|
||||
(resq, r)
|
||||
}
|
||||
}
|
||||
impl Div for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: $name) -> $name {
|
||||
let (res, _) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Div<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: &$name) -> $name {
|
||||
let (res, _) = self.divmod(rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Div<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: $name) -> $name {
|
||||
let (res, _) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
impl<'a,'b> Div<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn div(self, rhs: &$name) -> $name {
|
||||
let (res, _) = self.divmod(rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Rem for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: $name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Rem<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: &$name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Rem<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: $name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Rem<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn rem(self, rhs: &$name) -> $name {
|
||||
let (_, res) = self.divmod(&rhs);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1285
src/unsigned/invoc.rs
Normal file
1285
src/unsigned/invoc.rs
Normal file
File diff suppressed because it is too large
Load Diff
63
src/unsigned/mod.rs
Normal file
63
src/unsigned/mod.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
#[macro_use]
|
||||
mod add;
|
||||
#[macro_use]
|
||||
mod barrett;
|
||||
#[macro_use]
|
||||
mod base;
|
||||
#[macro_use]
|
||||
mod cmp;
|
||||
#[macro_use]
|
||||
mod codec;
|
||||
#[macro_use]
|
||||
mod conversion;
|
||||
#[macro_use]
|
||||
mod div;
|
||||
#[macro_use]
|
||||
mod mul;
|
||||
#[macro_use]
|
||||
mod shifts;
|
||||
#[macro_use]
|
||||
mod sub;
|
||||
|
||||
use self::add::{addition,unsafe_addition};
|
||||
use self::base::CryptoNum;
|
||||
use self::cmp::compare;
|
||||
use self::div::{DivMod,get_number_size};
|
||||
use self::codec::{Encoder,Decoder,raw_decoder};
|
||||
use self::mul::multiply;
|
||||
use self::shifts::{shiftl,shiftr};
|
||||
use self::sub::subtract;
|
||||
use std::cmp::{Ordering,min};
|
||||
use std::ops::{Add,AddAssign};
|
||||
use std::ops::{Div,Mul,Rem};
|
||||
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
|
||||
use std::ops::{Sub,SubAssign};
|
||||
|
||||
#[cfg(test)]
|
||||
use std::fmt;
|
||||
|
||||
macro_rules! generate_number
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
generate_base!($name, $size);
|
||||
generate_base_conversions!($name);
|
||||
generate_codec!($name);
|
||||
|
||||
cmp_impls!($name);
|
||||
|
||||
subtraction_impls!($name, $size);
|
||||
shift_impls!($name, $size);
|
||||
};
|
||||
($name: ident, $size: expr, $plus1: ident, $times2: ident) => {
|
||||
generate_number!($name, $size);
|
||||
addition_impls!($name, $plus1);
|
||||
multiply_impls!($name, $times2);
|
||||
div_impls!($name, $times2);
|
||||
};
|
||||
($name: ident, $size: expr, $plus1: ident, $times2: ident, $big: ident, $bar: ident) => {
|
||||
generate_number!($name, $size, $plus1, $times2);
|
||||
barrett_impl!($bar, $name, $plus1, $times2, $big);
|
||||
}
|
||||
}
|
||||
|
||||
include!("invoc.rs");
|
||||
65
src/unsigned/mul.rs
Normal file
65
src/unsigned/mul.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
pub fn multiply(dest: &mut [u64], left: &[u64], right: &[u64])
|
||||
{
|
||||
let len = right.len();
|
||||
|
||||
assert_eq!(left.len(), len, "Uneven argument lengths in multiply");
|
||||
assert_eq!(dest.len(), len*2, "Bad destination size in multiply");
|
||||
|
||||
for i in 0..len {
|
||||
let mut carry = 0;
|
||||
|
||||
for j in 0..len {
|
||||
let old = dest[i+j] as u128;
|
||||
let l128 = left[j] as u128;
|
||||
let r128 = right[i] as u128;
|
||||
let uv = old + (l128 * r128) + carry;
|
||||
dest[i+j] = uv as u64;
|
||||
carry = uv >> 64;
|
||||
}
|
||||
dest[i+len] = carry as u64;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! multiply_impls {
|
||||
($name: ident, $dbl: ident) => {
|
||||
impl Mul<$name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<$name> for &'a $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: $name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a $name> for $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Mul<&'a $name> for &'b $name {
|
||||
type Output = $dbl;
|
||||
|
||||
fn mul(self, rhs: &$name) -> $dbl {
|
||||
let mut res = $dbl::zero();
|
||||
multiply(&mut res.value, &self.value, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
92
src/unsigned/shifts.rs
Normal file
92
src/unsigned/shifts.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
pub(crate) fn shiftl(res: &mut [u64], copy: &[u64], amt: usize) {
|
||||
let digits = amt / 64;
|
||||
let bits = amt % 64;
|
||||
|
||||
let mut carry = 0;
|
||||
let shift = 64 - bits;
|
||||
|
||||
for i in 0..res.len() {
|
||||
let base = if i >= digits { copy[i-digits] } else { 0 };
|
||||
let new_carry = if shift == 64 { 0 } else { base >> shift };
|
||||
res[i] = (base << bits) | carry;
|
||||
carry = new_carry;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn shiftr(res: &mut [u64], copy: &[u64], amt: usize) {
|
||||
let digits = amt / 64;
|
||||
let bits = amt % 64;
|
||||
|
||||
let mut carry = 0;
|
||||
let mask = !(0xFFFFFFFFFFFFFFFF << bits);
|
||||
let shift = (64 - bits) as u32;
|
||||
|
||||
for (idx, val) in res.iter_mut().enumerate().rev() {
|
||||
let target = idx + digits;
|
||||
let base = if target >= copy.len() { 0 } else { copy[target] };
|
||||
let (new_carry, _) = (base & mask).overflowing_shl(shift);
|
||||
*val = (base >> bits) | carry;
|
||||
carry = new_carry;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! shift_impls
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
impl ShlAssign<usize> for $name {
|
||||
fn shl_assign(&mut self, amt: usize) {
|
||||
let copy = self.value.clone();
|
||||
shiftl(&mut self.value, ©, amt);
|
||||
}
|
||||
}
|
||||
|
||||
impl Shl<usize> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shl(mut self, amt: usize) -> $name {
|
||||
let copy = self.value.clone();
|
||||
shiftl(&mut self.value, ©, amt);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shl<usize> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shl(self, amt: usize) -> $name {
|
||||
let mut res = $name{ value: self.value.clone() };
|
||||
shiftl(&mut res.value, &self.value, amt);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ShrAssign<usize> for $name {
|
||||
fn shr_assign(&mut self, amt: usize) {
|
||||
let copy = self.value.clone();
|
||||
shiftr(&mut self.value, ©, amt);
|
||||
}
|
||||
}
|
||||
|
||||
impl Shr<usize> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shr(mut self, amt: usize) -> $name {
|
||||
let copy = self.value.clone();
|
||||
shiftr(&mut self.value, ©, amt);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shr<usize> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn shr(self, amt: usize) -> $name {
|
||||
let mut res = $name{ value: self.value.clone() };
|
||||
shiftr(&mut res.value, &self.value, amt);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//shift_impls!(U192, 3);
|
||||
76
src/unsigned/sub.rs
Normal file
76
src/unsigned/sub.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use unsigned::add::unsafe_addition;
|
||||
|
||||
pub fn subtract(res: &mut [u64], spare: &mut [u64], other: &[u64])
|
||||
{
|
||||
for i in 0..res.len() {
|
||||
res[i] = !res[i];
|
||||
}
|
||||
spare[0] = 1;
|
||||
unsafe_addition(res, &spare);
|
||||
unsafe_addition(res, &other);
|
||||
}
|
||||
|
||||
macro_rules! subtraction_impls
|
||||
{
|
||||
($name: ident, $size: expr) => {
|
||||
impl SubAssign for $name {
|
||||
fn sub_assign(&mut self, rhs: $name) {
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut self.value, &mut temp, &rhs.value);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SubAssign<&'a $name> for $name {
|
||||
fn sub_assign(&mut self, rhs: &$name) {
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut self.value, &mut temp, &rhs.value);
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: $name) -> $name {
|
||||
let mut res = $name::zero();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub<$name> for &'a $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: $name) -> $name {
|
||||
let mut res = $name::zero();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub<&'a $name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: &$name) -> $name {
|
||||
let mut res = $name::zero();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> Sub<&'a $name> for &'b $name {
|
||||
type Output = $name;
|
||||
|
||||
fn sub(self, rhs: &$name) -> $name {
|
||||
let mut res = $name::zero();
|
||||
let mut temp = [0; $size];
|
||||
subtract(&mut res.value, &mut temp, &rhs.value);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//subtraction_impls!(U192, 3);
|
||||
Reference in New Issue
Block a user