Initial commit!

This commit is contained in:
2018-09-26 14:47:30 -05:00
commit 3b68363b49
389 changed files with 1415972 additions and 0 deletions

4
src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
#![recursion_limit="1024"]
pub mod unsigned;
#[cfg(test)]
pub mod testing;

62
src/testing.rs Normal file
View File

@@ -0,0 +1,62 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::str::Lines;
fn next_value_set(line: &str) -> (String, bool, Vec<u8>)
{
assert!(line.is_ascii());
let mut items = line.split(": ");
let key = items.next().unwrap();
let valbits = items.next().unwrap();
let neg = valbits.contains('-');
let valbitsnoneg = valbits.trim_left_matches("-");
let mut nibble_iter = valbitsnoneg.chars().rev();
let mut val = Vec::new();
while let Some(c1) = nibble_iter.next() {
match nibble_iter.next() {
None => {
val.push( c1.to_digit(16).unwrap() as u8 );
}
Some(c2) => {
let b1 = c1.to_digit(16).unwrap() as u8;
let b2 = c2.to_digit(16).unwrap() as u8;
val.push( (b2 << 4) | b1 );
}
}
}
val.reverse();
(key.to_string(), neg, val)
}
fn next_test_case(contents: &mut Lines, lines: usize) ->
Option<HashMap<String,(bool,Vec<u8>)>>
{
let mut res = HashMap::new();
let mut count = 0;
while count < lines {
let line = contents.next()?;
let (key, neg, val) = next_value_set(line);
res.insert(key, (neg,val));
count += 1;
}
Some(res)
}
pub fn run_test<F>(fname: String, i: usize, f: F)
where F: Fn(HashMap<String,(bool,Vec<u8>)>)
{
let mut file = File::open(fname).unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
let mut iter = contents.lines();
while let Some(scase) = next_test_case(&mut iter, i) {
f(scase);
}
}

98
src/unsigned/add.rs Normal file
View 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
View 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(&quot);
// 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/bk1⌋, 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←rm.
while &r > &m2 {
r -= &m2;
}
// Done!
$name::from(&r)
}
}
};
}

83
src/unsigned/base.rs Normal file
View 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
View 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
View 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);
}
}

View 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
View 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

File diff suppressed because it is too large Load Diff

63
src/unsigned/mod.rs Normal file
View 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
View 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
View 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, &copy, 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, &copy, 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, &copy, 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, &copy, 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
View 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);