use std::fmt::{Debug};
use super::{div_mod, Coated, Isomorphic};
pub trait Size: Debug + Copy + PartialEq {
fn each<I: Index<Size=Self>>(self, f: impl FnMut(I)) { I::each(self, f); }
}
impl Size for usize {}
impl Size for () {}
impl<A: Size> Size for (A,) {}
impl<A: Size, B: Size> Size for (A, B) {}
impl<A: Size, B: Size, C: Size> Size for (A, B, C) {}
impl<S: Size> Size for Coated<S> {}
pub trait Index: Debug + Copy + PartialEq {
type Size: Size;
fn length(size: Self::Size) -> usize;
fn to_usize(self, size: Self::Size) -> usize;
fn from_usize(size: Self::Size, index: usize) -> (usize, Self);
fn each(size: Self::Size, mut f: impl FnMut(Self)) {
for i in 0..Self::length(size) { f(Self::from_usize(size, i).1); }
}
fn all(size: impl Isomorphic<Self::Size>) -> All<Self> { All(size.to_iso()) }
}
impl<I: Index> Index for (I,) {
type Size = (I::Size,);
#[inline(always)]
fn length(size: Self::Size) -> usize {
I::length(size.0)
}
#[inline(always)]
fn to_usize(self, size: Self::Size) -> usize {
let index = 0;
let index = index * I::length(size.0) + self.0.to_usize(size.0);
index
}
fn from_usize(size: Self::Size, index: usize) -> (usize, Self) {
let (index, i) = I::from_usize(size.0, index);
(index, (i,))
}
fn each(size: Self::Size, mut f: impl FnMut(Self)) {
size.0.each(|i| f((i,)));
}
}
impl<I: Index, J: Index> Index for (I, J) {
type Size = (I::Size, J::Size);
#[inline(always)]
fn length(size: Self::Size) -> usize {
I::length(size.0) * J::length(size.1)
}
#[inline(always)]
fn to_usize(self, size: Self::Size) -> usize {
let index = 0;
let index = index * I::length(size.0) + self.0.to_usize(size.0);
let index = index * J::length(size.1) + self.1.to_usize(size.1);
index
}
fn from_usize(size: Self::Size, index: usize) -> (usize, Self) {
let (index, j) = J::from_usize(size.1, index);
let (index, i) = I::from_usize(size.0, index);
(index, (i, j))
}
fn each(size: Self::Size, mut f: impl FnMut(Self)) {
size.0.each(|i| size.1.each(|j| f((i, j))));
}
}
impl<I: Index, J: Index, K: Index> Index for (I, J, K) {
type Size = (I::Size, J::Size, K::Size);
#[inline(always)]
fn length(size: Self::Size) -> usize {
I::length(size.0) * J::length(size.1) * K::length(size.2)
}
#[inline(always)]
fn to_usize(self, size: Self::Size) -> usize {
let index = 0;
let index = index * I::length(size.0) + self.0.to_usize(size.0);
let index = index * J::length(size.1) + self.1.to_usize(size.1);
let index = index * K::length(size.2) + self.2.to_usize(size.2);
index
}
fn from_usize(size: Self::Size, index: usize) -> (usize, Self) {
let (index, k) = K::from_usize(size.2, index);
let (index, j) = J::from_usize(size.1, index);
let (index, i) = I::from_usize(size.0, index);
(index, (i, j, k))
}
fn each(size: Self::Size, mut f: impl FnMut(Self)) {
size.0.each(|i| size.1.each(|j| size.2.each(|k| f((i, j, k)))));
}
}
impl<I: Index> Index for Coated<I> {
type Size = Coated<I::Size>;
#[inline(always)]
fn length(size: Self::Size) -> usize { I::length(size.0) }
#[inline(always)]
fn to_usize(self, size: Self::Size) -> usize { self.0.to_usize(size.0) }
fn from_usize(size: Self::Size, index: usize) -> (usize, Self) {
let (q, r) = I::from_usize(size.0, index);
(q, Coated(r))
}
fn each(size: Self::Size, mut f: impl FnMut(Self)) {
I::each(size.0, |i| f(Coated(i)));
}
}
#[derive(Debug, Copy, Clone)]
pub struct All<I: Index>(I::Size);
impl<I: Index> super::View for All<I> {
type I = I;
type T = I;
#[inline(always)]
fn size(&self) -> <Self::I as Index>::Size { self.0 }
#[inline(always)]
fn at(&self, index: Self::I) -> Self::T { index }
}
pub trait StaticIndex: 'static + Index<Size=()> {
const ALL: &'static [Self];
fn to_usize(self) -> usize;
fn from_usize(index: usize) -> Self { Self::ALL[index] }
}
impl<I: StaticIndex> Index for I {
type Size = ();
#[inline(always)] fn length((): Self::Size) -> usize { Self::ALL.len() }
#[inline(always)]
fn to_usize(self, (): Self::Size) -> usize {
let index = StaticIndex::to_usize(self);
assert_eq!(self, Self::ALL[index]);
index
}
#[inline(always)] fn from_usize(_: Self::Size, index: usize) -> (usize, Self) {
let (q, r) = div_mod(index, Self::length(()));
(q, StaticIndex::from_usize(r))
}
fn each(_: Self::Size, mut f: impl FnMut(Self)) {
for i in 0..Self::length(()) { f(StaticIndex::from_usize(i)); }
}
}
impl StaticIndex for () {
const ALL: &'static [Self] = &[()];
fn to_usize(self) -> usize { 0 }
fn from_usize(_: usize) -> Self { () }
}
impl StaticIndex for bool {
const ALL: &'static [Self] = &[false, true];
fn to_usize(self) -> usize { self as usize }
fn from_usize(index: usize) -> Self { index != 0 }
}
impl<I: Index> Index for Option<I> {
type Size = I::Size;
#[inline(always)]
fn length(size: Self::Size) -> usize { 1 + I::length(size) }
#[inline(always)]
fn to_usize(self, size: Self::Size) -> usize {
match self {
None => 0,
Some(i) => 1 + i.to_usize(size),
}
}
fn from_usize(size: Self::Size, index: usize) -> (usize, Self) {
let (q, r) = div_mod(index, Self::length(size));
(q, r.checked_sub(1).map(|some_index| {
let (zero, r) = I::from_usize(size, some_index);
assert_eq!(zero, 0);
r
}))
}
fn each(size: Self::Size, mut f: impl FnMut(Self)) {
f(None);
I::each(size, |index| f(Some(index)));
}
}