cplx 0.3.3

Complex and hypercomplex numbers
use core::slice;
use core::mem;
use core::num::*;
use core::ops::*;
use core::ptr;
use peano;
use peano::Natural;

pub trait LogArrayLength<A>: Natural { type Array; }

impl<A> LogArrayLength<A> for peano::Zero { type Array = A; }
impl<A, N: LogArrayLength<A>> LogArrayLength<A> for peano::Succ<N> { type Array = (N::Array, N::Array); }

#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Array<A, N: LogArrayLength<A>>(pub N::Array);

impl<A: Zero, N: LogArrayLength<A>> Zero for Array<A, N> {
    fn zero() -> Self {
        unsafe {
            let mut a: Self = mem::uninitialized();
            for k in 0..1<<N::to_usize() {
                ptr::write((&mut a as *mut Self as *mut A).offset(k), Zero::zero());
            }
            a
        }
    }
}

impl<A, N: LogArrayLength<A>> Deref for Array<A, N> {
    type Target = [A];
    fn deref(&self) -> &[A] {
        unsafe { slice::from_raw_parts(self as *const Self as *const A, 1<<N::to_usize()) }
    }
}

impl<A, N: LogArrayLength<A>> DerefMut for Array<A, N> {
    fn deref_mut(&mut self) -> &mut [A] {
        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut A, 1<<N::to_usize()) }
    }
}

impl<A, N: LogArrayLength<A>, I> Index<I> for Array<A, N> where [A]: Index<I> {
    type Output = <[A] as Index<I>>::Output;
    fn index(&self, k: I) -> &Self::Output { &(self as &[A])[k] }
}

impl<A, N: LogArrayLength<A>, I> IndexMut<I> for Array<A, N> where [A]: IndexMut<I> {
    fn index_mut(&mut self, k: I) -> &mut Self::Output { &mut (self as &mut [A])[k] }
}

#[cfg(test)] impl<A: Clone + Send + 'static, N: Clone + Send + LogArrayLength<A> + 'static> ::quickcheck::Arbitrary for Array<A, N>
  where N::Array: Clone + Send + ::quickcheck::Arbitrary + 'static {
    fn arbitrary<G: ::quickcheck::Gen>(g: &mut G) -> Self { Array(N::Array::arbitrary(g)) }
}