#[macro_export]
macro_rules! count_exprs {
() => { 0 };
($e:expr) => { 1 };
($e:expr, $($es:expr),+) => { 1 + count_exprs!($($es),*) };
}
#[macro_export]
macro_rules! collect {
[] => { collect![into _] };
[into $col_ty:ty] => { collect![into $col_ty:] };
[into $col_ty:ty:] => {
{
let col: $col_ty = ::std::default::Default::default();
col
}
};
[into $col_ty:ty: $v0:expr] => { collect![into $col_ty: $v0,] };
[into $col_ty:ty: $v0:expr, $($vs:expr),* $(,)*] => {
{
use std::marker::PhantomData;
const NUM_ELEMS: usize = count_exprs!($v0 $(, $vs)*);
struct SizeHint<E>(PhantomData<E>);
impl<E> SizeHint<E> {
#[inline(always)]
fn type_hint(_: &E) -> SizeHint<E> { SizeHint(PhantomData) }
}
impl<E> Iterator for SizeHint<E> {
type Item = E;
#[inline(always)]
fn next(&mut self) -> Option<E> {
None
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(NUM_ELEMS, Some(NUM_ELEMS))
}
}
let mut col: $col_ty = ::std::default::Default::default();
let v0 = $v0;
Extend::extend(&mut col, SizeHint::type_hint(&v0));
Extend::extend(&mut col, Some(v0).into_iter());
$(Extend::extend(&mut col, Some($vs).into_iter());)*
col
}
};
[$($vs:expr),+] => { collect![into _: $($vs),+] };
[into $col_ty:ty: $($ks:expr => $vs:expr),+] => {
collect![into $col_ty: $(($ks, $vs)),+]
};
[$($ks:expr => $vs:expr),+] => { collect![into _: $($ks => $vs),+] };
}
#[macro_export]
#[cfg(not(cannot_use_dotdotdot))]
macro_rules! sequence {
( $ind:ident: $sty:ty = $closed_form:expr ) => {
{
struct Sequence {
pos: usize,
}
impl Iterator for Sequence {
type Item = $sty;
#[inline]
fn next(&mut self) -> Option<$sty> {
if self.pos == ::std::usize::MAX {
return None
}
let next_val: $sty = {
let $ind = self.pos;
$closed_form
};
self.pos += 1;
Some(next_val)
}
}
Sequence { pos: 0 }
}
};
( $seq:ident [ $ind:ident ]: $sty:ty = $($inits:expr),+ ... $closed_form:expr ) => {
{
const INITS: usize = count_exprs!($($inits),+);
struct Sequence {
inits: [$sty; INITS],
pos: usize,
}
impl Iterator for Sequence {
type Item = $sty;
#[inline]
fn next(&mut self) -> Option<$sty> {
if self.pos == ::std::usize::MAX {
return None
}
if self.pos < INITS {
let next_val = self.inits[self.pos];
self.pos += 1;
Some(next_val)
} else {
let next_val: $sty = {
let $ind = self.pos;
let $seq = &self.inits;
$closed_form
};
self.pos += 1;
Some(next_val)
}
}
}
Sequence { inits: [$($inits),+], pos: 0 }
}
};
}
#[macro_export]
#[cfg(not(cannot_use_dotdotdot))]
macro_rules! recurrence {
( $seq:ident [ $ind:ident ]: $sty:ty = $($inits:expr),+ ... $recur:expr ) => {
{
use std::ops::Index;
const MEMORY: usize = count_exprs!($($inits),+);
struct Recurrence {
mem: [$sty; MEMORY],
pos: usize,
}
struct IndexOffset<'a> {
slice: &'a [$sty; MEMORY],
offset: usize,
}
impl<'a> Index<usize> for IndexOffset<'a> {
type Output = $sty;
#[inline(always)]
fn index<'b>(&'b self, index: usize) -> &'b $sty {
let real_index = index + MEMORY - self.offset;
&self.slice[real_index]
}
}
impl Iterator for Recurrence {
type Item = $sty;
#[inline]
fn next(&mut self) -> Option<$sty> {
if self.pos == ::std::usize::MAX {
return None
}
if self.pos < MEMORY {
let next_val = self.mem[self.pos];
self.pos += 1;
Some(next_val)
} else {
let next_val: $sty = {
let $ind = self.pos;
let $seq = IndexOffset { slice: &self.mem, offset: $ind };
$recur
};
{
use std::mem::swap;
let mut swap_tmp = next_val;
for i in (0..MEMORY).rev() {
swap(&mut swap_tmp, &mut self.mem[i]);
}
}
self.pos += 1;
Some(next_val)
}
}
}
Recurrence { mem: [$($inits),+], pos: 0 }
}
};
}