librespot/core/src/util/int128.rs

96 lines
2.3 KiB
Rust
Raw Normal View History

2015-06-23 14:38:29 +00:00
use std;
2018-02-11 11:37:08 +00:00
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2015-06-23 14:38:29 +00:00
#[allow(non_camel_case_types)]
pub struct u128 {
high: u64,
2016-01-02 15:19:39 +00:00
low: u64,
2015-06-23 14:38:29 +00:00
}
impl u128 {
pub fn zero() -> u128 {
u128::from_parts(0, 0)
}
2015-06-23 14:38:29 +00:00
pub fn from_parts(high: u64, low: u64) -> u128 {
2016-01-02 15:19:39 +00:00
u128 {
high: high,
low: low,
}
2015-06-23 14:38:29 +00:00
}
pub fn parts(&self) -> (u64, u64) {
(self.high, self.low)
}
}
impl std::ops::Add<u128> for u128 {
type Output = u128;
fn add(self, rhs: u128) -> u128 {
let low = self.low + rhs.low;
2018-02-11 11:37:08 +00:00
let high = self.high + rhs.high + if low < self.low { 1 } else { 0 };
2015-06-23 14:38:29 +00:00
u128::from_parts(high, low)
}
}
2016-01-02 15:19:39 +00:00
impl<'a> std::ops::Add<&'a u128> for u128 {
2015-06-23 14:38:29 +00:00
type Output = u128;
fn add(self, rhs: &'a u128) -> u128 {
let low = self.low + rhs.low;
2018-02-11 11:37:08 +00:00
let high = self.high + rhs.high + if low < self.low { 1 } else { 0 };
2015-06-23 14:38:29 +00:00
u128::from_parts(high, low)
}
}
impl std::convert::From<u8> for u128 {
fn from(n: u8) -> u128 {
u128::from_parts(0, n as u64)
}
}
impl std::ops::Mul<u128> for u128 {
type Output = u128;
fn mul(self, rhs: u128) -> u128 {
2018-02-11 11:37:08 +00:00
let top: [u64; 4] = [
self.high >> 32,
self.high & 0xFFFFFFFF,
self.low >> 32,
self.low & 0xFFFFFFFF,
];
2015-06-23 14:38:29 +00:00
2018-02-11 11:37:08 +00:00
let bottom: [u64; 4] = [
rhs.high >> 32,
rhs.high & 0xFFFFFFFF,
rhs.low >> 32,
rhs.low & 0xFFFFFFFF,
];
2015-06-23 14:38:29 +00:00
let mut rows = [u128::zero(); 16];
2015-06-23 14:38:29 +00:00
for i in 0..4 {
for j in 0..4 {
let shift = i + j;
2016-01-02 15:19:39 +00:00
let product = top[3 - i] * bottom[3 - j];
2015-06-23 14:38:29 +00:00
let (high, low) = match shift {
0 => (0, product),
1 => (product >> 32, product << 32),
2 => (product, 0),
3 => (product << 32, 0),
_ => {
2017-01-29 16:25:09 +00:00
if product == 0 {
2015-06-23 14:38:29 +00:00
(0, 0)
2017-01-29 16:25:09 +00:00
} else {
panic!("Overflow on mul {:?} {:?} ({} {})", self, rhs, i, j)
2015-06-23 14:38:29 +00:00
}
}
};
rows[j * 4 + i] = u128::from_parts(high, low);
}
}
rows.iter().fold(u128::zero(), std::ops::Add::add)
2015-06-23 14:38:29 +00:00
}
}