use super::*;
#[derive(Clone, Debug)]
pub struct RodVecComp{
ori: Array2<f64>,
}
impl RodVecComp{
pub fn new(size: usize) -> RodVecComp{
assert!(size > 0, "Size inputted: {}, was not greater than 0", size);
let ori = Array2::<f64>::zeros((3, size).f());
RodVecComp{
ori,
}
}
pub fn new_init(ori: Array2<f64>) -> RodVecComp{
let nrow = ori.rows();
assert!(nrow == 3, "Number of rows of array was: {}, which is not equal to 4", nrow);
{
let strides = ori.strides();
assert!(strides[0] == 1, "The memory stride is not column major (f order)");
}
RodVecComp{
ori,
}
}
pub fn ori_view(&self) -> ArrayView2<f64>{
self.ori.view()
}
pub fn ori_view_mut(&mut self) -> ArrayViewMut2<f64>{
self.ori.view_mut()
}
pub fn par_transpose(&self) -> RodVecComp{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((3, nelems).f());
ori.assign(&(-1.0 * &self.ori));
RodVecComp::new_init(ori)
}
pub fn par_transpose_inplace(&mut self){
self.ori.mapv_inplace(|x| {-1.0_f64 * x});
}
}
impl ParallelOriConv for RodVecComp{
fn par_to_bunge(&self) -> Bunge{
let rmat = self.par_to_rmat();
rmat.par_to_bunge()
}
fn par_to_rmat(&self) -> RMat{
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_rmat()
}
fn par_to_ang_axis(&self) -> AngAxis{
let rod_vec = self.par_to_rod_vec();
rod_vec.par_to_ang_axis()
}
fn par_to_ang_axis_comp(&self) -> AngAxisComp{
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_ang_axis_comp()
}
fn par_to_rod_vec(&self) -> RodVec{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((4, nelems).f());
let tol = std::f64::EPSILON;
par_azip!(mut rodvec (ori.axis_iter_mut(Axis(1))), ref rodvec_comp (self.ori.axis_iter(Axis(1))) in {
let norm_rodvec = f64::sqrt({
rodvec_comp[0] * rodvec_comp[0]
+ rodvec_comp[1] * rodvec_comp[1]
+ rodvec_comp[2] * rodvec_comp[2]
});
if norm_rodvec.abs() < tol {
rodvec[2] = 1.0_f64;
}else if norm_rodvec == std::f64::INFINITY {
rodvec[3] = norm_rodvec;
}else {
let inv_norm_rodvec = 1.0_f64 / norm_rodvec;
rodvec[0] = rodvec_comp[0] * inv_norm_rodvec;
rodvec[1] = rodvec_comp[1] * inv_norm_rodvec;
rodvec[2] = rodvec_comp[2] * inv_norm_rodvec;
rodvec[3] = norm_rodvec;
}
});
RodVec::new_init(ori)
}
fn par_to_rod_vec_comp(&self) -> RodVecComp{
self.clone()
}
fn par_to_quat(&self) -> Quat{
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_quat()
}
fn par_to_homochoric(&self) -> Homochoric{
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_homochoric()
}
fn par_to_bunge_inplace(&self, bunge: &mut Bunge){
let rmat = self.par_to_rmat();
rmat.par_to_bunge_inplace(bunge);
}
fn par_to_rmat_inplace(&self, rmat: &mut RMat){
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_rmat_inplace(rmat);
}
fn par_to_ang_axis_inplace(&self, ang_axis: &mut AngAxis){
let rod_vec = self.par_to_rod_vec();
rod_vec.par_to_ang_axis_inplace(ang_axis);
}
fn par_to_ang_axis_comp_inplace(&self, ang_axis_comp: &mut AngAxisComp){
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_ang_axis_comp_inplace(ang_axis_comp);
}
fn par_to_rod_vec_inplace(&self, rod_vec: &mut RodVec){
let mut ori = rod_vec.ori_view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
let tol = std::f64::EPSILON;
par_azip!(mut rodvec (ori.axis_iter_mut(Axis(1))), ref rodvec_comp (self.ori.axis_iter(Axis(1))) in {
let norm_rodvec = f64::sqrt({
rodvec_comp[0] * rodvec_comp[0]
+ rodvec_comp[1] * rodvec_comp[1]
+ rodvec_comp[2] * rodvec_comp[2]
});
if norm_rodvec.abs() < tol {
rodvec[2] = 1.0_f64;
}else if norm_rodvec == std::f64::INFINITY {
rodvec[3] = norm_rodvec;
}else {
let inv_norm_rodvec = 1.0_f64 / norm_rodvec;
rodvec[0] = rodvec_comp[0] * inv_norm_rodvec;
rodvec[1] = rodvec_comp[1] * inv_norm_rodvec;
rodvec[2] = rodvec_comp[2] * inv_norm_rodvec;
rodvec[3] = norm_rodvec;
}
});
}
fn par_to_rod_vec_comp_inplace(&self, rod_vec_comp: &mut RodVecComp){
let mut ori = rod_vec_comp.ori_view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
ori.assign(&self.ori);
}
fn par_to_quat_inplace(&self, quat: &mut Quat){
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_quat_inplace(quat);
}
fn par_to_homochoric_inplace(&self, homochoric: &mut Homochoric){
let ang_axis = self.par_to_ang_axis();
ang_axis.par_to_homochoric_inplace(homochoric);
}
}