135 lines
2.7 KiB
Rust
Executable File
135 lines
2.7 KiB
Rust
Executable File
macro_rules! hty {
|
|
($ty:ty) => {
|
|
<$ty as LargeInt>::HighHalf
|
|
}
|
|
}
|
|
|
|
macro_rules! os_ty {
|
|
($ty:ty) => {
|
|
<$ty as Int>::OtherSign
|
|
}
|
|
}
|
|
|
|
pub mod mul;
|
|
pub mod sdiv;
|
|
pub mod shift;
|
|
pub mod udiv;
|
|
|
|
/// Trait for some basic operations on integers
|
|
pub trait Int {
|
|
/// Type with the same width but other signedness
|
|
type OtherSign;
|
|
/// Unsigned version of Self
|
|
type UnsignedInt;
|
|
|
|
/// Returns the bitwidth of the int type
|
|
fn bits() -> u32;
|
|
|
|
/// Extracts the sign from self and returns a tuple.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```rust,ignore
|
|
/// let i = -25_i32;
|
|
/// let (sign, u) = i.extract_sign();
|
|
/// assert_eq!(sign, true);
|
|
/// assert_eq!(u, 25_u32);
|
|
/// ```
|
|
fn extract_sign(self) -> (bool, Self::UnsignedInt);
|
|
}
|
|
|
|
// TODO: Once i128/u128 support lands, we'll want to add impls for those as well
|
|
impl Int for u32 {
|
|
type OtherSign = i32;
|
|
type UnsignedInt = u32;
|
|
|
|
fn bits() -> u32 {
|
|
32
|
|
}
|
|
|
|
fn extract_sign(self) -> (bool, u32) {
|
|
(false, self)
|
|
}
|
|
}
|
|
|
|
impl Int for i32 {
|
|
type OtherSign = u32;
|
|
type UnsignedInt = u32;
|
|
|
|
fn bits() -> u32 {
|
|
32
|
|
}
|
|
|
|
fn extract_sign(self) -> (bool, u32) {
|
|
if self < 0 {
|
|
(true, !(self as u32) + 1)
|
|
} else {
|
|
(false, self as u32)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Int for u64 {
|
|
type OtherSign = i64;
|
|
type UnsignedInt = u64;
|
|
|
|
fn bits() -> u32 {
|
|
64
|
|
}
|
|
|
|
fn extract_sign(self) -> (bool, u64) {
|
|
(false, self)
|
|
}
|
|
}
|
|
|
|
impl Int for i64 {
|
|
type OtherSign = u64;
|
|
type UnsignedInt = u64;
|
|
|
|
fn bits() -> u32 {
|
|
64
|
|
}
|
|
|
|
fn extract_sign(self) -> (bool, u64) {
|
|
if self < 0 {
|
|
(true, !(self as u64) + 1)
|
|
} else {
|
|
(false, self as u64)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Trait to convert an integer to/from smaller parts
|
|
pub trait LargeInt {
|
|
type LowHalf;
|
|
type HighHalf;
|
|
|
|
fn low(self) -> Self::LowHalf;
|
|
fn high(self) -> Self::HighHalf;
|
|
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
|
|
}
|
|
|
|
macro_rules! large_int {
|
|
($ty:ty, $tylow:ty, $tyhigh:ty, $halfbits:expr) => {
|
|
impl LargeInt for $ty {
|
|
type LowHalf = $tylow;
|
|
type HighHalf = $tyhigh;
|
|
|
|
fn low(self) -> $tylow {
|
|
self as $tylow
|
|
}
|
|
fn high(self) -> $tyhigh {
|
|
(self >> $halfbits) as $tyhigh
|
|
}
|
|
fn from_parts(low: $tylow, high: $tyhigh) -> $ty {
|
|
low as $ty | ((high as $ty) << $halfbits)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
large_int!(u64, u32, u32, 32);
|
|
large_int!(i64, u32, i32, 32);
|
|
large_int!(u128, u64, u64, 64);
|
|
large_int!(i128, u64, i64, 64);
|