use core::default::Default;
#[cfg(feature = "no_std")]
use alloc::borrow::ToOwned;
pub struct Uint128 {
pub high: u64,
pub low: u64,
}
impl Default for Uint128{
fn default() -> Self {
Self {
high: Default::default(),
low: Default::default(),
}
}
}
pub fn qrc_donna128_shift_right(x: Uint128, shift: usize) -> Uint128 {
let mut r = Uint128::default();
let carry = x.high << (64 - shift);
r.high = x.high >> shift;
r.low = (x.low >> shift) | carry;
return r;
}
pub fn qrc_donna128_shift_left(x: Uint128, shift: usize) -> Uint128 {
let mut r = Uint128::default();
let carry = x.low >> (64 - shift);
r.low = x.low << shift;
r.high = (x.high << shift) | carry;
return r;
}
pub fn qrc_donna128_andl(x: Uint128, mask: u64) -> u64 {
return x.low & mask;
}
pub fn qrc_donna128_andh(x: Uint128, mask: u64) -> u64 {
return x.high & mask;
}
pub fn qrc_donna128_add(x: Uint128, y: Uint128) -> Uint128 {
let mut r = Uint128::default();
r.low = x.low + y.low;
r.high = x.high + y.high;
let carry = (x.low < y.low) as u64;
r.high += carry;
return r;
}
pub fn qrc_donna128_multiply(x: Uint128, y: u64) -> Uint128 {
let mut r = Uint128::default();
let low = &mut 0;
let high = &mut 0;
mul64x64to128(x.low, y, low, high);
r.low = low.to_owned();
r.high = high.to_owned();
return r;
}
pub fn qrc_donna128_or(x: Uint128, y: Uint128) -> Uint128 {
let mut r = Uint128::default();
r.low = x.low | y.low;
r.high = x.high | y.high;
return r;
}
fn mul64x64to128(x: u64, y: u64, low: &mut u64, high: &mut u64) {
const HWORD_BITS: usize = 32;
const HWORD_MASK: u32 = 0xFFFFFFFF;
let ah = (x >> HWORD_BITS) as u32;
let al = (x as u32) & HWORD_MASK;
let bh = (y >> HWORD_BITS) as u32;
let bl = (y as u32) & HWORD_MASK;
let mut x0 = (ah as u64).wrapping_mul(bh as u64);
let x1 = (al as u64).wrapping_mul(bh as u64);
let mut x2 = (ah as u64).wrapping_mul(bl as u64);
let x3 = (al as u64).wrapping_mul(bl as u64);
x2 = x2.wrapping_add(x3 >> HWORD_BITS);
x2 = x2.wrapping_add(x1);
x0 = x0.wrapping_add(((x2 < x1) as u64) << HWORD_BITS);
*high = x0.wrapping_add(x2 >> HWORD_BITS);
*low = ((x2 & HWORD_MASK as u64) << HWORD_BITS).wrapping_add(x3 & HWORD_MASK as u64);
}