#![feature(associated_type_defaults)]
#![feature(zero_one)]
#![cfg_attr(test, feature(plugin))]
#![no_std]
#![cfg_attr(test, plugin(quickcheck_macros))]
extern crate peano;
#[cfg(test)] extern crate quickcheck;
#[cfg(test)] #[macro_use] extern crate std;
use core::fmt;
use core::marker::PhantomData;
use core::num::*;
use core::ops::*;
use peano::Natural;
mod array;
mod basis;
pub use basis::Basis;
use array::*;
pub trait TotalDimensional {
type DimTotal: Natural;
}
pub struct Signature<DimFlat: Natural, DimElliptic: Natural, DimHyperbolic: Natural>(DimFlat, DimElliptic, DimHyperbolic);
impl<DimFlat: Natural, DimElliptic: Natural, DimHyperbolic: Natural> TotalDimensional for Signature<DimFlat, DimElliptic, DimHyperbolic>
// well this is ridiculous
where DimFlat: Add<<DimElliptic as Add<DimHyperbolic>>::Output>,
DimElliptic: Add<DimHyperbolic>,
<DimFlat as Add<<DimElliptic as Add<DimHyperbolic>>::Output>>::Output: Natural {
type DimTotal = <DimFlat as Add<<DimElliptic as Add<DimHyperbolic>>::Output>>::Output;
}
pub struct Complex<A, S: TotalDimensional = Signature<peano::Zero, peano::Succ<peano::Zero>, peano::Zero>>(PhantomData<S>, Array<A, S::DimTotal>) where S::DimTotal: LogArrayLength<A>;
impl<A: Clone, S: TotalDimensional> Clone for Complex<A, S> where S::DimTotal: LogArrayLength<A>, Array<A, S::DimTotal>: Clone {
fn clone(&self) -> Self { let &Complex(_, ref a) = self; Complex(PhantomData, a.clone()) }
}
impl<A: Copy, S: TotalDimensional> Copy for Complex<A, S> where S::DimTotal: LogArrayLength<A>, Array<A, S::DimTotal>: Copy {}
impl<A: PartialEq, S: TotalDimensional> PartialEq for Complex<A, S> where S::DimTotal: LogArrayLength<A> {
fn eq(&self, &Complex(_, ref b): &Self) -> bool { let &Complex(_, ref a) = self; a[..] == b[..] }
}
impl<A: Eq, S: TotalDimensional> Eq for Complex<A, S> where S::DimTotal: LogArrayLength<A> {}
impl<A: fmt::Debug, S: TotalDimensional> fmt::Debug for Complex<A, S> where S::DimTotal: LogArrayLength<A> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let &Complex(_, ref a) = self; a[..].fmt(fmt) }
}
impl<A: Copy + Neg<Output = A>, S: TotalDimensional> Complex<A, S> where S::DimTotal: LogArrayLength<A> {
#[inline] pub fn conjugate(self) -> Self {
let Complex(_, mut a) = self;
for p in a.iter_mut() { *p = (*p).neg() }
Complex(PhantomData, a)
}
}
impl<A: Copy + Add<Output = A>, S: TotalDimensional> Add for Complex<A, S> where S::DimTotal: LogArrayLength<A> {
type Output = Self;
#[inline] fn add(self, Complex(_, b): Self) -> Self {
let Complex(_, mut a) = self;
for i in 0..S::DimTotal::to_usize() { a[i] = a[i] + b[i] }
Complex(PhantomData, a)
}
}
impl<A: Zero, S: TotalDimensional> Zero for Complex<A, S> where S::DimTotal: LogArrayLength<A> {
#[inline] fn zero() -> Self { Complex(PhantomData, Zero::zero()) }
}
impl<A: Copy + Add<Output = A> + Sub<Output = A> + Zero + Mul<Output = A>,
DimFlat: Natural, DimElliptic: Natural, DimHyperbolic: Natural> Mul for Complex<A, Signature<DimFlat, DimElliptic, DimHyperbolic>>
where Signature<DimFlat, DimElliptic, DimHyperbolic>: TotalDimensional,
<Signature<DimFlat, DimElliptic, DimHyperbolic> as TotalDimensional>::DimTotal: LogArrayLength<A> {
type Output = Self;
#[inline] fn mul(self, Complex(_, b): Self) -> Self {
let Complex(_, a) = self;
let Complex(_, mut c) = Self::zero();
for j in 0..(<Signature<DimFlat, DimElliptic, DimHyperbolic> as TotalDimensional>::DimTotal::to_usize()) {
for i in 0..(<Signature<DimFlat, DimElliptic, DimHyperbolic> as TotalDimensional>::DimTotal::to_usize()) {
if let Some((p, k)) = basis::mul::<DimFlat, DimElliptic, DimHyperbolic>(i, j) {
c[k] = (if p { Sub::sub as fn(A, A) -> A } else { Add::add as fn (A, A) -> A })(c[k], a[i]*b[j])
}
}
}
Complex(PhantomData, c)
}
}
impl<A: Zero + One, S: TotalDimensional> One for Complex<A, S> where S::DimTotal: LogArrayLength<A> {
#[inline] fn one() -> Self {
let mut a: Array<A, S::DimTotal> = Zero::zero();
a[0] = One::one();
Complex(PhantomData, a)
}
}
#[cfg(test)] mod tests {
use quickcheck as qc;
use std::marker::PhantomData;
use super::*;
impl<A: qc::Arbitrary> qc::Arbitrary for Complex<A> {
fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { Complex(PhantomData, qc::Arbitrary::arbitrary(g)) }
}
#[quickcheck] fn multiplication(x: Complex<i32>, y: Complex<i32>) -> bool {
use array::Array;
let Complex(_, Array((a, b))) = x;
let Complex(_, Array((c, d))) = y;
let w = Complex(PhantomData, Array((a*c-b*d, a*d+b*c)));
let z = x*y;
println!("{:?} ?= {:?}", w, z);
w == z
}
}