Skip to content

Instantly share code, notes, and snippets.

@qryxip
Last active January 23, 2022 22:33
Show Gist options
  • Save qryxip/b8f4259f6dcf77fe89e55c5e424bdf67 to your computer and use it in GitHub Desktop.
Save qryxip/b8f4259f6dcf77fe89e55c5e424bdf67 to your computer and use it in GitHub Desktop.
Flexible integer type
//! 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 <qryxip@gmail.com>"]
//! 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