Skip to content

Instantly share code, notes, and snippets.

@pizzacat83
Last active March 17, 2020 12:34
Show Gist options
  • Save pizzacat83/498dee7d940d5ad22d68288e515d45b4 to your computer and use it in GitHub Desktop.
Save pizzacat83/498dee7d940d5ad22d68288e515d45b4 to your computer and use it in GitHub Desktop.
[WIP] Z/nZライブラリ
use num::Num;
use std::ops;
#[derive(std::cmp::PartialEq, Clone, Copy)]
struct ResidueRing<T>
where T: std::fmt::Display + Copy + num::Num + num::Unsigned + PartialEq
{
n: T,
modulo: T,
}
impl<T> ResidueRing<T>
where T: std::fmt::Display + Copy + num::Num + num::Unsigned + PartialEq
{
fn from(n: T, modulo: T) -> Self {
Self {
n: n % modulo, modulo
}
}
}
impl<T> std::ops::Add for ResidueRing<T>
where T: std::fmt::Display + Copy + num::Num + num::Unsigned + PartialEq
{
type Output = Self;
fn add(self, other: Self) -> Self {
#[cfg(debug_assertions)]
{
if self.modulo != other.modulo {
panic!("different modulo: {} (mod {}) + {} (mod {})", self.n, self.modulo, other.n, other.modulo);
}
}
Self {
n: (self.n + other.n) % self.modulo,
modulo: self.modulo,
}
}
}
impl<T> std::ops::Add<T> for ResidueRing<T>
where T: std::fmt::Display + Copy + num::Num + num::Unsigned + PartialEq
{
type Output = Self;
fn add(self, other: T) -> Self {
#[cfg(debug_assertions)]
let other = Self::from(other, self.modulo);
self + other
}
}
impl<T> std::ops::Sub for ResidueRing<T>
where T: std::fmt::Display + Copy + num::Num + num::Unsigned + PartialEq
{
type Output = Self;
fn sub(self, other: Self) -> Self {
#[cfg(debug_assertions)]
{
if self.modulo != other.modulo {
panic!("different modulo: {} (mod {}) - {} (mod {})", self.n, self.modulo, other.n, other.modulo);
}
}
Self {
n: (self.modulo + self.n - other.n) % self.modulo,
modulo: self.modulo,
}
}
}
impl<T> std::ops::Sub<T> for ResidueRing<T>
where T: std::fmt::Display + Copy + num::Num + num::Unsigned + PartialEq
{
type Output = Self;
fn sub(self, other: T) -> Self {
#[cfg(debug_assertions)]
let other = Self::from(other, self.modulo);
self - other
}
}
impl<T> std::ops::Index<ResidueRing<usize>> for Vec<T> {
type Output = T;
fn index(&self, index: ResidueRing<usize>) -> &T {
&self[index.n]
}
}
impl<T> std::ops::IndexMut<ResidueRing<usize>> for Vec<T> {
fn index_mut(&mut self, index: ResidueRing<usize>) -> &mut T {
&mut self[index.n]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment