Last active
January 23, 2022 22:33
-
-
Save qryxip/b8f4259f6dcf77fe89e55c5e424bdf67 to your computer and use it in GitHub Desktop.
Flexible integer type
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! This code is licensed under the [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/legalcode). | |
//! | |
//! ```cargo | |
//! [package] | |
//! name = "longlong" | |
//! version = "0.0.0" | |
//! authors = ["Ryo Yamashita <[email protected]>"] | |
//! edition = "2018" | |
//! publish = false | |
//! license = "CC0-1.0" | |
//! description = "Flexible integer type." | |
//! | |
//! [dependencies] | |
//! ``` | |
use std::{ | |
any::Any, | |
cmp, | |
collections::VecDeque, | |
convert, fmt, | |
iter::{self, Product, Sum}, | |
marker::PhantomData, | |
num::ParseIntError, | |
ops::{ | |
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Range, RangeFrom, | |
RangeInclusive, Rem, RemAssign, Sub, SubAssign, | |
}, | |
slice::SliceIndex, | |
str::FromStr, | |
}; | |
#[allow(clippy::op_ref)] | |
fn main() { | |
// `str`から直にパース | |
let mut x = "1".parse::<Int>().unwrap(); | |
// 整数型すべてと四則演算可能 | |
x += 1usize; | |
x = 1usize + x; | |
// 整数型すべてと比較可能 | |
assert_eq!(x, 3usize); | |
assert_eq!(3usize, x); | |
// `.sum()`, `.product()`にも対応 | |
let _: Int = vec![1, 2, 3].into_iter().sum(); | |
let _: Int = vec![1, 2, 3].into_iter().product(); | |
let _: usize = vec![x, x, x].into_iter().sum(); | |
let _: usize = vec![x, x, x].into_iter().product(); | |
// そのままprint可能 | |
assert_eq!(x.to_string(), "3"); | |
// `[_]`, `Vec<_>`, `VecDeque<_>`の添字にも使える | |
let xs = vec![Int(1), Int(2), Int(3), Int(4)]; | |
assert_eq!(xs[x], 4); | |
// 整数型と相互に変換可能 (`as`は流石に無理) | |
let _: i64 = x.into(); | |
let _: i64 = x.to_i64(); | |
let _: usize = x.into(); | |
let _: usize = x.to_usize(); | |
let _: Int = 0usize.into(); | |
let x = "1".parse::<Int>().unwrap(); | |
let y = "2".parse::<Int>().unwrap(); | |
let _: Int = 1i64 + x; | |
let _: Int = 1u64 + x; | |
let _: Int = 1usize + x; | |
let _: Int = &1i64 + &x; | |
let _: Int = &1u64 + &x; | |
let _: Int = &1usize + &x; | |
let _: Int = x + 1i64; | |
let _: Int = x + 1u64; | |
let _: Int = x + 1usize; | |
let _: bool = 1i64 == x; | |
let _: bool = 1u64 == x; | |
let _: bool = 1usize == x; | |
let _: Int = vec![1, 2, 3].into_iter().sum(); | |
let _: Int = vec![1, 2, 3].into_iter().product(); | |
let _: usize = vec![x, x, x].into_iter().sum(); | |
let _: usize = vec![x, x, x].into_iter().product(); | |
let xs = vec![x, x, x]; | |
let _: Int = xs[y]; | |
let _: &[Int] = &xs[(y..=y).s()]; | |
for i in (x..y).r() { | |
let _: Int = i; | |
} | |
} | |
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | |
pub struct Int(i64); | |
macro_rules! impl_cast_methods { | |
($(pub const fn $name:ident(self) -> $ty:ty;)*) => { | |
$( | |
pub const fn $name(self) -> $ty { self.0 as _ } | |
)* | |
}; | |
} | |
impl Int { | |
pub const MIN: Self = Self(i64::min_value()); | |
pub const MAX: Self = Self(i64::max_value()); | |
pub const fn get(self) -> i64 { | |
self.0 | |
} | |
impl_cast_methods! { | |
pub const fn to_i8(self) -> i8; | |
pub const fn to_i16(self) -> i16; | |
pub const fn to_i32(self) -> i32; | |
pub const fn to_i64(self) -> i64; | |
pub const fn to_i128(self) -> i128; | |
pub const fn to_isize(self) -> isize; | |
pub const fn to_u8(self) -> u8; | |
pub const fn to_u16(self) -> u16; | |
pub const fn to_u32(self) -> u32; | |
pub const fn to_u64(self) -> u64; | |
pub const fn to_u128(self) -> u128; | |
pub const fn to_usize(self) -> usize; | |
} | |
} | |
#[rustfmt::skip] impl FromStr for Int { type Err = ParseIntError; fn from_str(s: &str) -> Result<Self, ParseIntError> { s.parse().map(Self) } } | |
#[rustfmt::skip] impl From<bool> for Int { fn from(from: bool) -> Self { Self(from as _) } } | |
#[rustfmt::skip] impl AsRef<i64> for Int { fn as_ref(&self) -> &i64 { &self.0 }} | |
#[rustfmt::skip] impl AsMut<i64> for Int { fn as_mut(&mut self) -> &mut i64 { &mut self.0 }} | |
#[rustfmt::skip] impl fmt::Display for Int { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } | |
#[rustfmt::skip] impl fmt::Debug for Int { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } } | |
macro_rules! impl_index { | |
($(impl <$tyarg:ident> {Index<Int>, IndexMut<Int>} for $ty:ty { type Output = $output:ty; })*) => { | |
$( | |
impl<$tyarg> Index<Int> for $ty { type Output = $output; fn index(&self, index: Int) -> &$output { &self[index.0 as usize] } } | |
impl<$tyarg> IndexMut<Int> for $ty { fn index_mut(&mut self, index: Int) -> &mut $output { &mut self[index.0 as usize] } } | |
)* | |
}; | |
} | |
impl_index! { | |
impl<T> {Index<Int>, IndexMut<Int>} for [T] { type Output = T; } | |
impl<T> {Index<Int>, IndexMut<Int>} for Vec<T> { type Output = T; } | |
impl<T> {Index<Int>, IndexMut<Int>} for VecDeque<T> { type Output = T; } | |
} | |
// 流石にこれは駄目だった | |
//impl<T> Index<Range<Int>> for [T] { | |
// type Output = [T]; | |
// | |
// fn index(&self, index: Range<Int>) -> &[T] { | |
// &self[(index.start as usize)..(index.end as usize)] | |
// } | |
//} | |
#[rustfmt::skip] impl Neg for Int { type Output = Int; fn neg(self) -> Int { Int(-self.0) } } | |
#[rustfmt::skip] impl Neg for &'_ Int { type Output = Int; fn neg(self) -> Int { Int(-self.0) } } | |
macro_rules! impl_bin_ops { | |
($(<$lhs:ty> ~ <$rhs:ty>;)*) => { | |
$( | |
impl Add<$rhs> for $lhs { type Output = Int; fn add(self, rhs: $rhs) -> Int { Int(self.0 + rhs.0) } } | |
impl Sub<$rhs> for $lhs { type Output = Int; fn sub(self, rhs: $rhs) -> Int { Int(self.0 - rhs.0) } } | |
impl Mul<$rhs> for $lhs { type Output = Int; fn mul(self, rhs: $rhs) -> Int { Int(self.0 * rhs.0) } } | |
impl Div<$rhs> for $lhs { type Output = Int; fn div(self, rhs: $rhs) -> Int { Int(self.0 / rhs.0) } } | |
impl Rem<$rhs> for $lhs { type Output = Int; fn rem(self, rhs: $rhs) -> Int { Int(self.0 % rhs.0) } } | |
)* | |
}; | |
} | |
impl_bin_ops! { | |
<Int> ~ <Int>; | |
<Int> ~ <&'_ Int>; | |
<&'_ Int> ~ <Int>; | |
<&'_ Int> ~ <&'_ Int>; | |
} | |
macro_rules! impl_bin_assign_ops { | |
($(<Int> ~= <$rhs:ty>;)*) => { | |
$( | |
impl AddAssign<$rhs> for Int { fn add_assign(&mut self, rhs: $rhs) { self.0 += rhs.0; } } | |
impl SubAssign<$rhs> for Int { fn sub_assign(&mut self, rhs: $rhs) { self.0 -= rhs.0; } } | |
impl MulAssign<$rhs> for Int { fn mul_assign(&mut self, rhs: $rhs) { self.0 *= rhs.0; } } | |
impl DivAssign<$rhs> for Int { fn div_assign(&mut self, rhs: $rhs) { self.0 /= rhs.0; } } | |
impl RemAssign<$rhs> for Int { fn rem_assign(&mut self, rhs: $rhs) { self.0 %= rhs.0; } } | |
)* | |
}; | |
} | |
impl_bin_assign_ops! { | |
<Int> ~= <Int>; | |
<Int> ~= <&'_ Int>; | |
} | |
#[rustfmt::skip] impl Sum for Int { fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Int(0), Add::add) } } | |
#[rustfmt::skip] impl<'a> Sum<&'a Self> for Int { fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Int(0), Add::add) } } | |
#[rustfmt::skip] impl Product for Int { fn product<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Int(1), Mul::mul) } } | |
#[rustfmt::skip] impl<'a> Product<&'a Self> for Int { fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Int(1), Mul::mul) } } | |
macro_rules! impl_for_primitive_integers { | |
($($ty:ty),*) => { | |
$( | |
impl From<$ty> for Int { fn from(from: $ty) -> Self { Self(from as _) } } | |
impl From<Int> for $ty { fn from(from: Int) -> Self { from.0 as _ } } | |
impl PartialEq<$ty> for Int { fn eq(&self, other: &$ty) -> bool { self.0 == (*other as i64) } } | |
impl PartialEq<Int> for $ty { fn eq(&self, other: &Int) -> bool { (*self as i64) == other.0 } } | |
impl PartialOrd<$ty> for Int { fn partial_cmp(&self, other: &$ty) -> Option<cmp::Ordering> { Some(self.0.cmp(&(*other as i64))) } } | |
impl PartialOrd<Int> for $ty { fn partial_cmp(&self, other: &Int) -> Option<cmp::Ordering> { Some((*self as i64).cmp(&other.0)) } } | |
impl_bin_ops_for_primitive_integers! { | |
<Int> ~ <$ty> { { |Int(l)| l } ~ { |r| r as i64 } } | |
<Int> ~ <&'_ $ty> { { |Int(l)| l } ~ { |&r| r as i64 } } | |
<&'_ Int> ~ <$ty> { { |&Int(l)| l } ~ { |r| r as i64 } } | |
<&'_ Int> ~ <&'_$ty> { { |&Int(l)| l } ~ { |&r| r as i64 } } | |
<$ty> ~ <Int> { { |l| l as i64 } ~ { |Int(r)| r } } | |
<$ty> ~ <&'_ Int> { { |l| l as i64 } ~ { |&Int(r)| r } } | |
<&'_ $ty> ~ <Int> { { |&l| l as i64 } ~ { |Int(r)| r } } | |
<&'_ $ty> ~ <&'_ Int> { { |&l| l as i64 } ~ { |&Int(r)| r } } | |
} | |
impl_assign_ops_for_primitive_integers! { | |
<Int> ~= <$ty> { *{ AsMut::<i64>::as_mut } ~= { |r| r as i64 } } | |
<Int> ~= <&'_ $ty> { *{ AsMut::<i64>::as_mut } ~= { |&r| r as i64 } } | |
<$ty> ~= <Int> { *{ convert::identity } ~= { |Int(r)| r as $ty } } | |
<$ty> ~= <&'_ Int> { *{ convert::identity } ~= { |&Int(r)| r as $ty } } | |
} | |
impl Sum<$ty> for Int { fn sum<I: Iterator<Item = $ty>>(iter: I) -> Self { Self(iter.map(|x| x as i64).sum()) } } | |
impl<'a> Sum<&'a $ty> for Int { fn sum<I: Iterator<Item = &'a $ty>>(iter: I) -> Self { Self(iter.map(|&x| x as i64).sum()) } } | |
impl Sum<Int> for $ty { fn sum<I: Iterator<Item = Int>>(iter: I) -> Self { iter.map(|Int(x)| x as $ty).sum() } } | |
impl<'a> Sum<&'a Int> for $ty { fn sum<I: Iterator<Item = &'a Int>>(iter: I) -> Self { iter.map(|&Int(x)| x as $ty).sum() } } | |
impl Product<$ty> for Int { fn product<I: Iterator<Item = $ty>>(iter: I) -> Self { Self(iter.map(|x| x as i64).product()) } } | |
impl<'a> Product<&'a $ty> for Int { fn product<I: Iterator<Item = &'a $ty>>(iter: I) -> Self { Self(iter.map(|&x| x as i64).product()) } } | |
impl Product<Int> for $ty { fn product<I: Iterator<Item = Int>>(iter: I) -> Self { iter.map(|Int(x)| x as $ty).product() } } | |
impl<'a> Product<&'a Int> for $ty { fn product<I: Iterator<Item = &'a Int>>(iter: I) -> Self { iter.map(|&Int(x)| x as $ty).product() } } | |
)* | |
}; | |
} | |
macro_rules! impl_bin_ops_for_primitive_integers { | |
($(<$lhs_ty:ty> ~ <$rhs_ty:ty> { { $lhs_val:expr } ~ { $rhs_val:expr } })*) => { | |
$( | |
impl Add<$rhs_ty> for $lhs_ty { type Output = Int; fn add(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) + apply($rhs_val, rhs)) } } | |
impl Sub<$rhs_ty> for $lhs_ty { type Output = Int; fn sub(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) - apply($rhs_val, rhs)) } } | |
impl Mul<$rhs_ty> for $lhs_ty { type Output = Int; fn mul(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) * apply($rhs_val, rhs)) } } | |
impl Div<$rhs_ty> for $lhs_ty { type Output = Int; fn div(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) / apply($rhs_val, rhs)) } } | |
impl Rem<$rhs_ty> for $lhs_ty { type Output = Int; fn rem(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) % apply($rhs_val, rhs)) } } | |
)* | |
}; | |
} | |
macro_rules! impl_assign_ops_for_primitive_integers { | |
($(<$lhs_ty:ty> ~= <$rhs_ty:ty> { *{ $lhs_val:expr } ~= { $rhs_val:expr } })*) => { | |
$( | |
impl AddAssign<$rhs_ty> for $lhs_ty { fn add_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) += $rhs_val(rhs) } } | |
impl SubAssign<$rhs_ty> for $lhs_ty { fn sub_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) -= $rhs_val(rhs) } } | |
impl MulAssign<$rhs_ty> for $lhs_ty { fn mul_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) *= $rhs_val(rhs) } } | |
impl DivAssign<$rhs_ty> for $lhs_ty { fn div_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) /= $rhs_val(rhs) } } | |
impl RemAssign<$rhs_ty> for $lhs_ty { fn rem_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) %= $rhs_val(rhs) } } | |
)* | |
}; | |
} | |
impl_for_primitive_integers!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize); | |
pub trait IntoI64StepRange: Sized { | |
type I64StepRange: Iterator<Item = i64>; | |
fn into_i64_step_range(self) -> Self::I64StepRange; | |
fn r(self) -> iter::Map<Self::I64StepRange, fn(i64) -> Int> { | |
self.into_i64_step_range().map(Int) | |
} | |
} | |
#[rustfmt::skip] impl IntoI64StepRange for Range<Int> { type I64StepRange = Range<i64>; fn into_i64_step_range(self) -> Range<i64> { self.start.0..self.end.0 } } | |
#[rustfmt::skip] impl IntoI64StepRange for RangeFrom<Int> { type I64StepRange = RangeFrom<i64>; fn into_i64_step_range(self) -> RangeFrom<i64> { self.start.0.. } } | |
#[rustfmt::skip] impl IntoI64StepRange for RangeInclusive<Int> { type I64StepRange = RangeInclusive<i64>; fn into_i64_step_range(self) -> RangeInclusive<i64> { self.start().0..=self.end().0 } } | |
pub trait IntoSliceIndex: Sized { | |
type SliceIndex: SliceIndex<[PhantomData<Box<dyn Any>>]>; | |
fn into_slice_index(self) -> Self::SliceIndex; | |
fn s(self) -> Self::SliceIndex { | |
self.into_slice_index() | |
} | |
} | |
#[rustfmt::skip] impl IntoSliceIndex for Range<Int> { type SliceIndex = Range<usize>; fn into_slice_index(self) -> Range<usize> { (self.start.0 as _)..(self.end.0 as _) } } | |
#[rustfmt::skip] impl IntoSliceIndex for RangeFrom<Int> { type SliceIndex = RangeFrom<usize>; fn into_slice_index(self) -> RangeFrom<usize> { (self.start.0 as _).. } } | |
#[rustfmt::skip] impl IntoSliceIndex for RangeInclusive<Int> { type SliceIndex = RangeInclusive<usize>; fn into_slice_index(self) -> RangeInclusive<usize> { (self.start().0 as _)..=(self.end().0 as _) } } | |
fn apply<T, O>(f: fn(T) -> O, x: T) -> O { | |
f(x) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment