extern crate maths_traits;
extern crate rug;
use maths_traits::{algebra, analysis};
use num_traits::pow;
use std::iter::*;
use std::ops::*;
use std::vec::Vec;
pub trait TensorCalculus<T> {
fn sum(self) -> T;
fn norm<P>(self, p: P) -> T
where
T: pow::Pow<P, Output = T> + algebra::group_like::additive::Zero + analysis::ordered::Sign,
P: algebra::group_like::multiplicative::Inv<Output = P> + Clone;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Tense<T> {
pub val: Vec<T>,
}
impl<T> Deref for Tense<T> {
type Target = [T];
fn deref<'a>(&'a self) -> &'a [T] {
self.val.as_slice()
}
}
impl<I, T, U> algebra::group_like::additive::Add<I> for Tense<T>
where
T: algebra::group_like::additive::Add<U, Output = T> + Clone,
I: Deref<Target = [U]>,
U: Clone,
{
type Output = Tense<T>;
fn add(self, rhs: I) -> Tense<T> {
Tense::<T> {
val: self
.iter()
.zip(rhs.iter().cycle())
.map(|(a, b)| a.clone() + b.clone())
.collect(),
}
}
}
impl<I, T, U> algebra::group_like::additive::AddAssign<I> for Tense<T>
where
T: algebra::group_like::additive::AddAssign<U>,
I: Deref<Target = [U]>,
U: Clone,
{
fn add_assign(&mut self, rhs: I) {
for (i, b) in (0..self.len()).zip(rhs.iter().cycle()) {
self[i] += b.clone();
}
}
}
impl<I, T, U> algebra::group_like::additive::Sub<I> for Tense<T>
where
T: algebra::group_like::additive::Sub<U, Output = T> + Clone,
I: Deref<Target = [U]>,
U: Clone,
{
type Output = Tense<T>;
fn sub(self, rhs: I) -> Tense<T> {
Tense::<T> {
val: self
.iter()
.zip(rhs.iter().cycle())
.map(|(a, b)| a.clone() - b.clone())
.collect(),
}
}
}
impl<I, T, U> algebra::group_like::additive::SubAssign<I> for Tense<T>
where
T: algebra::group_like::additive::SubAssign<U>,
I: Deref<Target = [U]>,
U: Clone,
{
fn sub_assign(&mut self, rhs: I) {
for (i, b) in (0..self.len()).zip(rhs.iter().cycle()) {
self[i] -= b.clone();
}
}
}
impl<I, T, U> algebra::group_like::multiplicative::Mul<I> for Tense<T>
where
T: algebra::group_like::multiplicative::Mul<U, Output = T> + Clone,
I: Deref<Target = [U]>,
U: Clone,
{
type Output = Tense<T>;
fn mul(self, rhs: I) -> Tense<T> {
Tense::<T> {
val: self
.iter()
.zip(rhs.iter().cycle())
.map(|(a, b)| a.clone() * b.clone())
.collect(),
}
}
}
impl<I, T, U> algebra::group_like::multiplicative::MulAssign<I> for Tense<T>
where
T: algebra::group_like::multiplicative::MulAssign<U>,
I: Deref<Target = [U]>,
U: Clone,
{
fn mul_assign(&mut self, rhs: I) {
for (i, b) in (0..self.len()).zip(rhs.iter().cycle()) {
self[i] *= b.clone();
}
}
}
impl<I, T, U> algebra::group_like::multiplicative::Div<I> for Tense<T>
where
T: algebra::group_like::multiplicative::Div<U, Output = T> + Clone,
I: Deref<Target = [U]>,
U: Clone,
{
type Output = Tense<T>;
fn div(self, rhs: I) -> Tense<T> {
Tense::<T> {
val: self
.iter()
.zip(rhs.iter().cycle())
.map(|(a, b)| a.clone() / b.clone())
.collect(),
}
}
}
impl<I, T, U> algebra::group_like::multiplicative::DivAssign<I> for Tense<T>
where
T: algebra::group_like::multiplicative::DivAssign<U>,
I: Deref<Target = [U]>,
U: Clone,
{
fn div_assign(&mut self, rhs: I) {
for (i, b) in (0..self.len()).zip(rhs.iter().cycle()) {
self[i] /= b.clone();
}
}
}
impl<I, T, U> Rem<I> for Tense<T>
where
T: Rem<U, Output = T> + Clone,
I: Deref<Target = [U]>,
U: Clone,
{
type Output = Tense<T>;
fn rem(self, rhs: I) -> Tense<T> {
Tense::<T> {
val: self
.iter()
.zip(rhs.iter().cycle())
.map(|(a, b)| a.clone() % b.clone())
.collect(),
}
}
}
impl<I, T, U> RemAssign<I> for Tense<T>
where
T: RemAssign<U>,
I: Deref<Target = [U]>,
U: Clone,
{
fn rem_assign(&mut self, rhs: I) {
for (i, b) in (0..self.len()).zip(rhs.iter().cycle()) {
self[i] %= b.clone();
}
}
}
impl<T> algebra::group_like::additive::Neg for Tense<T>
where
T: algebra::group_like::additive::Neg<Output = T> + Clone,
{
type Output = Tense<T>;
fn neg(self) -> Tense<T> {
Tense::<T> {
val: self.iter().map(|x| -x.clone()).collect(),
}
}
}
impl<T> algebra::module_like::Index<usize> for Tense<T> {
type Output = T;
fn index(&self, ind: usize) -> &T {
&self.val[ind]
}
}
impl<T> algebra::module_like::IndexMut<usize> for Tense<T> {
fn index_mut(&mut self, ind: usize) -> &mut T {
&mut self.val[ind]
}
}
impl<T> TensorCalculus<T> for Tense<T>
where
T: algebra::group_like::additive::Add<Output = T>
+ algebra::group_like::additive::Sub
+ algebra::group_like::multiplicative::Mul
+ algebra::group_like::multiplicative::Div
+ algebra::group_like::additive::Zero
+ Clone,
{
fn sum(self) -> T {
self.val.iter().fold(T::zero(), |s, i| s + i.clone())
}
fn norm<P>(self, p: P) -> T
where
T: pow::Pow<P, Output = T> + algebra::group_like::additive::Zero + analysis::ordered::Sign,
P: algebra::group_like::multiplicative::Inv<Output = P> + Clone,
{
self.val
.iter()
.map(|x| x.clone().abs().pow(p.clone()))
.fold(T::zero(), |s, i| s + i.clone())
.pow(p.inv())
}
}
#[macro_export]
macro_rules! tense {
{$($v:expr),*} => {Tense::<_> { val: vec![$($v),*]}}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ops() {
assert_eq!(
tense!(tense!(0, 1, 4), tense!(42, 12, 7), tense!(10, 20, -100))
+ tense!(tense!(5, 2, 4), tense!(42, 12, 7), tense!(10, 20, -100))
+ tense!(tense!(1000)),
tense!(
tense!(1005, 1003, 1008),
tense!(1084, 1024, 1014),
tense!(1020, 1040, 800)
)
);
assert_eq!(tense!(10, 20, 30) - tense!(3, 4, 5), tense!(7, 16, 25));
assert_eq!(tense!(10, 2, -5) * tense!(3, -4, -5), tense!(30, -8, 25));
assert_eq!(tense!(100, 12, -25) / tense!(2, -4, -5), tense!(50, -3, 5));
assert_eq!(
-tense!(tense!(1, 2, 3), tense!(-4, -5, -6)),
tense!(tense!(-1, -2, -3), tense!(4, 5, 6))
);
assert_eq!(tense!(tense!(1, 2, 3), tense!(4, 5, 6))[0][1], 2);
let mut m = tense!(tense!(1, 2), tense!(3, 4));
m[1][0] = 5;
assert_eq!(m, tense!(tense!(1, 2), tense!(5, 4)));
m += tense!(tense!(10));
assert_eq!(m, tense!(tense!(11, 12), tense!(15, 14)));
m -= tense!(tense!(10));
assert_eq!(m, tense!(tense!(1, 2), tense!(5, 4)));
m *= tense!(tense!(10));
assert_eq!(m, tense!(tense!(10, 20), tense!(50, 40)));
m /= tense!(tense!(10));
assert_eq!(m, tense!(tense!(1, 2), tense!(5, 4)));
m = tense!(tense!(20, 120), tense!(220, -120));
m %= tense!(tense!(100));
assert_eq!(m, tense!(tense!(20, 20), tense!(20, -20)));
}
#[test]
fn test_tensor_calculus() {
assert_eq!(tense!(1, 2, 3).sum(), 6);
assert_eq!(tense!(3_f32, 4_f32).norm(2_f32), 5_f32);
}
}