Skip to content
This repository has been archived by the owner on Apr 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #23 from debris/optimization
Browse files Browse the repository at this point in the history
mul and from optimizations
  • Loading branch information
NikVolf authored Aug 17, 2017
2 parents 5d904b8 + 2840c89 commit 5780bc0
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
target
.idea
Cargo.lock
Cargo.lock
*.swp
25 changes: 25 additions & 0 deletions benches/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,28 @@ fn u128_mul(b: &mut Bencher) {
});
}

#[bench]
fn u256_from_le(b: &mut Bencher) {
b.iter(|| {
let raw = black_box([
1u8, 2, 3, 5, 7, 11, 13, 17,
19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83,
89, 97, 101, 103, 107, 109, 113, 127
]);
let _ = U256::from_little_endian(&raw[..]);
});
}

#[bench]
fn u256_from_be(b: &mut Bencher) {
b.iter(|| {
let raw = black_box([
1u8, 2, 3, 5, 7, 11, 13, 17,
19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83,
89, 97, 101, 103, 107, 109, 113, 127
]);
let _ = U256::from_big_endian(&raw[..]);
});
}
91 changes: 76 additions & 15 deletions src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
//! implementations for even more speed, hidden behind the `x64_arithmetic`
//! feature flag.

use core::str;
use core::{str, mem};
use core::ops::{Shr, Shl, BitAnd, BitOr, BitXor, Not, Div, Rem, Mul, Add, Sub};

use byteorder::{ByteOrder, BigEndian, LittleEndian};
Expand Down Expand Up @@ -392,16 +392,20 @@ macro_rules! uint_overflowing_mul_reg {
let $name(ref you) = $other;
let mut ret = [0u64; 2*$n_words];

for i in 0..$n_words {
let mut i = 0;
for _ in 0..$n_words {
if you[i] == 0 {
i += 1;
continue;
}

let mut carry2 = 0u64;
let (b_u, b_l) = split(you[i]);

for j in 0..$n_words {
let mut j = 0;
for _ in 0..$n_words {
if me[j] == 0 && carry2 == 0 {
j += 1;
continue;
}

Expand All @@ -422,17 +426,21 @@ macro_rules! uint_overflowing_mul_reg {

// Only single overflow possible there
carry2 = (o1 | o2 | o3) as u64;
j += 1;
}
i += 1;
}

let mut res = [0u64; $n_words];
let mut overflow = false;
for i in 0..$n_words {
res[i] = ret[i];
}
res.copy_from_slice(&ret[0..$n_words]);

for i in $n_words..2*$n_words {
overflow |= ret[i] != 0;
unsafe {
let mut ret_ptr = ret.as_ptr().offset($n_words);
for _ in $n_words..2*$n_words {
overflow |= *ret_ptr != 0;
ret_ptr = ret_ptr.offset(1);
}
}

($name(res), overflow)
Expand Down Expand Up @@ -809,11 +817,17 @@ macro_rules! construct_uint {
assert!($n_words * 8 >= slice.len());

let mut ret = [0; $n_words];
for i in 0..slice.len() {
let rev = slice.len() - 1 - i;
let pos = rev / 8;
ret[pos] += (slice[i] as u64) << ((rev % 8) * 8);
unsafe {
let ret_u8: &mut [u8; $n_words * 8] = mem::transmute(&mut ret);
let mut ret_ptr = ret_u8.as_mut_ptr();
let mut slice_ptr = slice.as_ptr().offset(slice.len() as isize - 1);
for _ in 0..slice.len() {
*ret_ptr = *slice_ptr;
ret_ptr = ret_ptr.offset(1);
slice_ptr = slice_ptr.offset(-1);
}
}

$name(ret)
}

Expand All @@ -822,10 +836,11 @@ macro_rules! construct_uint {
assert!($n_words * 8 >= slice.len());

let mut ret = [0; $n_words];
for i in 0..slice.len() {
let pos = i / 8;
ret[pos] += (slice[i] as u64) << ((i % 8) * 8);
unsafe {
let ret_u8: &mut [u8; $n_words * 8] = mem::transmute(&mut ret);
ret_u8[0..slice.len()].copy_from_slice(&slice);
}

$name(ret)
}
}
Expand Down Expand Up @@ -2419,6 +2434,24 @@ mod tests {
assert_eq!(&raw, &new_raw);
}

#[test]
fn slice_roundtrip_le2() {
let raw = [
2, 3, 5, 7, 11, 13, 17,
19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83,
89, 97, 101, 103, 107, 109, 113, 127
];

let u256 = U256::from_little_endian(&raw[..]);

let mut new_raw = [0u8; 32];

u256.to_little_endian(&mut new_raw);

assert_eq!(&raw, &new_raw[..31]);
}

#[test]
fn fixed_arrays_roundtrip() {
let raw: U256 = "7094875209347850239487502394881".into();
Expand All @@ -2427,4 +2460,32 @@ mod tests {

assert_eq!(raw, new_raw);
}

#[test]
fn from_little_endian() {
let source: [u8; 32] = [
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];

let number = U256::from_little_endian(&source[..]);

assert_eq!(U256::from(1), number);
}

#[test]
fn from_big_endian() {
let source: [u8; 32] = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1,
];

let number = U256::from_big_endian(&source[..]);

assert_eq!(U256::from(1), number);
}
}

0 comments on commit 5780bc0

Please sign in to comment.