use crate::CausalMultiField;
use deep_causality_haft::{
Applicative, CoMonad, Functor, HKT, Monad, NoConstraint, Pure, Satisfies,
};
use deep_causality_metric::Metric;
use deep_causality_num::Field;
use deep_causality_tensor::CausalTensor;
use std::marker::PhantomData;
#[derive(Debug, Clone, Copy, Default)]
pub struct CausalMultiFieldWitness<T>(PhantomData<T>);
impl<T> CausalMultiFieldWitness<T> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl<T> HKT for CausalMultiFieldWitness<T>
where
T: Satisfies<NoConstraint>,
{
type Constraint = NoConstraint;
type Type<A> = CausalMultiField<A>;
}
impl<T> Functor<CausalMultiFieldWitness<T>> for CausalMultiFieldWitness<T>
where
T: Field + Copy + Default + PartialOrd + Satisfies<NoConstraint>,
{
fn fmap<A, C, Func>(fa: CausalMultiField<A>, mut f: Func) -> CausalMultiField<C>
where
A: Satisfies<NoConstraint>,
C: Satisfies<NoConstraint>,
Func: FnMut(A) -> C,
{
unsafe {
let fa_ptr = &fa as *const CausalMultiField<A> as *const CausalMultiField<T>;
let fa_concrete = &*fa_ptr;
let data_vec = fa_concrete.data().as_slice();
let transformed: Vec<T> = data_vec
.iter()
.map(|x| {
let a_val = std::mem::transmute_copy::<T, A>(x);
let c_val = f(a_val);
std::mem::transmute_copy::<C, T>(&c_val)
})
.collect();
let dx = *fa_concrete.dx();
let new_tensor = CausalTensor::from_slice(&transformed, fa_concrete.data().shape());
let result = CausalMultiField::<T> {
data: new_tensor,
metric: fa_concrete.metric(),
dx,
shape: *fa_concrete.shape(),
};
let result_ptr = &result as *const CausalMultiField<T> as *const CausalMultiField<C>;
let ret = std::ptr::read(result_ptr);
std::mem::forget(result);
ret
}
}
}
impl<T> Pure<CausalMultiFieldWitness<T>> for CausalMultiFieldWitness<T>
where
T: Field + Copy + Default + PartialOrd + Satisfies<NoConstraint>,
{
fn pure<A>(value: A) -> CausalMultiField<A>
where
A: Satisfies<NoConstraint>,
{
unsafe {
let val_ptr = &value as *const A as *const T;
let val_t = *val_ptr;
let metric = Metric::from_signature(1, 3, 0);
let shape = [1, 1, 1];
let dx = [T::one(), T::one(), T::one()];
let matrix_dim = 1 << (metric.dimension().div_ceil(2));
let total_size = shape[0] * shape[1] * shape[2] * matrix_dim * matrix_dim;
let data = vec![val_t; total_size];
let tensor = CausalTensor::from_slice(
&data,
&[shape[0], shape[1], shape[2], matrix_dim, matrix_dim],
);
let result = CausalMultiField::<T> {
data: tensor,
metric,
dx,
shape,
};
let result_ptr = &result as *const CausalMultiField<T> as *const CausalMultiField<A>;
let ret = std::ptr::read(result_ptr);
std::mem::forget(result);
ret
}
}
}
impl<T> Applicative<CausalMultiFieldWitness<T>> for CausalMultiFieldWitness<T>
where
T: Field + Copy + Default + PartialOrd + Satisfies<NoConstraint>,
{
fn apply<A, C, Func>(
_ff: CausalMultiField<Func>,
_fa: CausalMultiField<A>,
) -> CausalMultiField<C>
where
A: Satisfies<NoConstraint> + Clone,
C: Satisfies<NoConstraint>,
Func: Satisfies<NoConstraint> + FnMut(A) -> C,
{
panic!(
"CausalMultiField::apply is not supported. \
Use fmap for function application over field values."
);
}
}
impl<T> Monad<CausalMultiFieldWitness<T>> for CausalMultiFieldWitness<T>
where
T: Field + Copy + Default + PartialOrd + Satisfies<NoConstraint>,
{
fn bind<A, C, Func>(ma: CausalMultiField<A>, mut f: Func) -> CausalMultiField<C>
where
A: Satisfies<NoConstraint>,
C: Satisfies<NoConstraint>,
Func: FnMut(A) -> CausalMultiField<C>,
{
unsafe {
let ma_ptr = &ma as *const CausalMultiField<A> as *const CausalMultiField<T>;
let ma_concrete = &*ma_ptr;
let data_vec = ma_concrete.data().as_slice();
if let Some(&first_val) = data_vec.first() {
let a_val = std::mem::transmute_copy::<T, A>(&first_val);
let result = f(a_val);
return result;
}
let metric = ma_concrete.metric();
let shape = *ma_concrete.shape();
let dx = *ma_concrete.dx();
let matrix_dim = 1 << (metric.dimension().div_ceil(2));
let total_size = shape[0] * shape[1] * shape[2] * matrix_dim * matrix_dim;
let data = vec![T::zero(); total_size];
let tensor = CausalTensor::from_slice(
&data,
&[shape[0], shape[1], shape[2], matrix_dim, matrix_dim],
);
let result = CausalMultiField::<T> {
data: tensor,
metric,
dx,
shape,
};
let result_ptr = &result as *const CausalMultiField<T> as *const CausalMultiField<C>;
let ret = std::ptr::read(result_ptr);
std::mem::forget(result);
ret
}
}
}
impl<T> CoMonad<CausalMultiFieldWitness<T>> for CausalMultiFieldWitness<T>
where
T: Field + Copy + Default + PartialOrd + Satisfies<NoConstraint>,
{
fn extract<A>(fa: &CausalMultiField<A>) -> A
where
A: Satisfies<NoConstraint> + Clone,
{
unsafe {
let fa_ptr = fa as *const CausalMultiField<A> as *const CausalMultiField<T>;
let fa_concrete = &*fa_ptr;
let data_vec = fa_concrete.data().as_slice();
let first_val = data_vec.first().copied().unwrap_or_else(T::zero);
std::mem::transmute_copy::<T, A>(&first_val)
}
}
fn extend<A, C, Func>(fa: &CausalMultiField<A>, mut f: Func) -> CausalMultiField<C>
where
A: Satisfies<NoConstraint> + Clone,
C: Satisfies<NoConstraint>,
Func: FnMut(&CausalMultiField<A>) -> C,
{
unsafe {
let c_val = f(fa);
let c_t = std::mem::transmute_copy::<C, T>(&c_val);
let fa_ptr = fa as *const CausalMultiField<A> as *const CausalMultiField<T>;
let fa_concrete = &*fa_ptr;
let metric = fa_concrete.metric();
let shape = *fa_concrete.shape();
let dx = *fa_concrete.dx();
let matrix_dim = 1 << (metric.dimension().div_ceil(2));
let total_size = shape[0] * shape[1] * shape[2] * matrix_dim * matrix_dim;
let data = vec![c_t; total_size];
let tensor = CausalTensor::from_slice(
&data,
&[shape[0], shape[1], shape[2], matrix_dim, matrix_dim],
);
let result = CausalMultiField::<T> {
data: tensor,
metric,
dx,
shape,
};
let result_ptr = &result as *const CausalMultiField<T> as *const CausalMultiField<C>;
let ret = std::ptr::read(result_ptr);
std::mem::forget(result);
std::mem::forget(c_val);
ret
}
}
}