Skip to main content

conspire/math/tensor/rank_1/vec/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::math::{
5    Jacobian, Solution, Tensor, TensorRank0, TensorRank1, TensorRank1List, TensorRank2SparseVec2D,
6    TensorRank2SparseVec2DSymmetric, TensorRank2Vec2D, Vector, tensor::vec::TensorVector,
7};
8use std::{
9    array::from_fn,
10    mem::{forget, transmute},
11    ops::{Div, Sub},
12};
13
14use crate::math::assert::FiniteDifference;
15
16/// A vector of rank-1 tensors.
17pub type TensorRank1Vec<const D: usize, const I: usize> = TensorVector<TensorRank1<D, I>>;
18
19impl<const D: usize, const I: usize> TensorRank1Vec<D, I> {
20    pub fn bounding_box(&self) -> TensorRank1List<D, I, 2> {
21        self.iter()
22            .skip(1)
23            .fold(
24                [self[0].clone(), self[0].clone()],
25                |[mut min, mut max], entry| {
26                    entry
27                        .iter()
28                        .zip(min.iter_mut().zip(max.iter_mut()))
29                        .for_each(|(&entry_i, (min_i, max_i))| {
30                            *min_i = min_i.min(entry_i);
31                            *max_i = max_i.max(entry_i);
32                        });
33                    [min, max]
34                },
35            )
36            .into()
37    }
38    pub fn zero(len: usize) -> Self {
39        (0..len).map(|_| super::zero()).collect()
40    }
41}
42
43impl<const D: usize, const I: usize, const N: usize> From<[[TensorRank0; D]; N]>
44    for TensorRank1Vec<D, I>
45{
46    fn from(array: [[TensorRank0; D]; N]) -> Self {
47        array.into_iter().map(TensorRank1::from).collect()
48    }
49}
50
51impl<const D: usize, const I: usize> From<Vec<[TensorRank0; D]>> for TensorRank1Vec<D, I> {
52    fn from(vec: Vec<[TensorRank0; D]>) -> Self {
53        unsafe { transmute(vec) }
54    }
55}
56
57impl<const D: usize, const I: usize> From<TensorRank1Vec<D, I>> for Vec<[TensorRank0; D]> {
58    fn from(tensor_rank_1_vec: TensorRank1Vec<D, I>) -> Self {
59        unsafe { transmute(tensor_rank_1_vec) }
60    }
61}
62
63impl<const D: usize, const I: usize> From<Vec<Vec<TensorRank0>>> for TensorRank1Vec<D, I> {
64    fn from(vec: Vec<Vec<TensorRank0>>) -> Self {
65        vec.into_iter()
66            .map(|tensor_rank_1| tensor_rank_1.into())
67            .collect()
68    }
69}
70
71impl<const D: usize, const I: usize> From<TensorRank1Vec<D, I>> for Vec<Vec<TensorRank0>> {
72    fn from(tensor_rank_1_vec: TensorRank1Vec<D, I>) -> Self {
73        tensor_rank_1_vec
74            .into_iter()
75            .map(|tensor_rank_1| tensor_rank_1.into())
76            .collect()
77    }
78}
79
80impl<const D: usize, const I: usize> TryFrom<[Vec<TensorRank0>; D]> for TensorRank1Vec<D, I> {
81    type Error = String;
82    fn try_from(vec_array: [Vec<TensorRank0>; D]) -> Result<Self, Self::Error> {
83        let length = vec_array[0].len();
84        if vec_array.iter().any(|vec| vec.len() != length) {
85            Err("Vector length mismatch in type conversion".to_string())
86        } else {
87            Ok((0..length)
88                .map(|j| TensorRank1::const_from(from_fn(|i| vec_array[i][j])))
89                .collect())
90        }
91    }
92}
93
94impl<const D: usize, const I: usize> From<TensorRank1Vec<D, I>> for [Vec<TensorRank0>; D] {
95    fn from(tensor_rank_1_vec: TensorRank1Vec<D, I>) -> Self {
96        let length = tensor_rank_1_vec.len();
97        let mut output = from_fn(|_| Vec::with_capacity(length));
98        tensor_rank_1_vec.into_iter().for_each(|tensor_rank_1| {
99            output
100                .iter_mut()
101                .zip(tensor_rank_1)
102                .for_each(|(entry, value)| entry.push(value))
103        });
104        output
105    }
106}
107
108impl<const D: usize, const I: usize> From<&TensorRank1Vec<D, I>> for [Vec<TensorRank0>; D] {
109    fn from(tensor_rank_1_vec: &TensorRank1Vec<D, I>) -> Self {
110        let length = tensor_rank_1_vec.len();
111        let mut output = from_fn(|_| Vec::with_capacity(length));
112        tensor_rank_1_vec.iter().for_each(|tensor_rank_1| {
113            output
114                .iter_mut()
115                .zip(tensor_rank_1.iter())
116                .for_each(|(entry, &value)| entry.push(value))
117        });
118        output
119    }
120}
121
122impl<const D: usize> From<TensorRank1Vec<D, 0>> for TensorRank1Vec<D, 1> {
123    fn from(tensor_rank_1_vec: TensorRank1Vec<D, 0>) -> Self {
124        let length = tensor_rank_1_vec.len();
125        let pointer = tensor_rank_1_vec.as_ptr() as *mut TensorRank1<D, 1>;
126        forget(tensor_rank_1_vec);
127        unsafe { Self::from(Vec::from_raw_parts(pointer, length, length)) }
128    }
129}
130
131impl<const D: usize> From<&TensorRank1Vec<D, 0>> for TensorRank1Vec<D, 1> {
132    fn from(tensor_rank_1_vec: &TensorRank1Vec<D, 0>) -> Self {
133        tensor_rank_1_vec
134            .iter()
135            .map(|tensor_rank_1| tensor_rank_1.into())
136            .collect()
137    }
138}
139
140impl<const D: usize> From<TensorRank1Vec<D, 1>> for TensorRank1Vec<D, 0> {
141    fn from(tensor_rank_1_vec: TensorRank1Vec<D, 1>) -> Self {
142        let length = tensor_rank_1_vec.len();
143        let pointer = tensor_rank_1_vec.as_ptr() as *mut TensorRank1<D, 0>;
144        forget(tensor_rank_1_vec);
145        unsafe { Self::from(Vec::from_raw_parts(pointer, length, length)) }
146    }
147}
148
149impl<const D: usize> From<&TensorRank1Vec<D, 1>> for TensorRank1Vec<D, 0> {
150    fn from(tensor_rank_1_vec: &TensorRank1Vec<D, 1>) -> Self {
151        tensor_rank_1_vec
152            .iter()
153            .map(|tensor_rank_1| tensor_rank_1.into())
154            .collect()
155    }
156}
157
158impl<const D: usize, const I: usize> From<Vector> for TensorRank1Vec<D, I> {
159    fn from(vector: Vector) -> Self {
160        let n = vector.len();
161        if n.is_multiple_of(D) {
162            let length = n / D;
163            let pointer = vector.as_ptr() as *mut TensorRank1<D, I>;
164            forget(vector);
165            unsafe { Self::from(Vec::from_raw_parts(pointer, length, length)) }
166        } else {
167            panic!("Vector length mismatch.")
168        }
169    }
170}
171
172impl<const D: usize, const I: usize> Jacobian for TensorRank1Vec<D, I> {
173    fn fill_into(self, vector: &mut Vector) {
174        self.into_iter()
175            .flatten()
176            .zip(vector.iter_mut())
177            .for_each(|(self_i, vector_i)| *vector_i = self_i)
178    }
179    fn fill_into_chained(self, other: Vector, vector: &mut Vector) {
180        self.into_iter()
181            .flatten()
182            .chain(other)
183            .zip(vector.iter_mut())
184            .for_each(|(self_i, vector_i)| *vector_i = self_i)
185    }
186    fn retain_from(self, retained: &[bool]) -> Vector {
187        self.into_iter()
188            .flatten()
189            .zip(retained.iter())
190            .filter(|(_, retained)| **retained)
191            .map(|(entry, _)| entry)
192            .collect()
193    }
194    fn zero_out(&mut self, indices: &[usize]) {
195        indices
196            .iter()
197            .for_each(|index| self[index / D][index % D] = 0.0)
198    }
199}
200
201impl<const D: usize, const I: usize> Solution for TensorRank1Vec<D, I> {
202    fn decrement_from(&mut self, other: &Vector) {
203        self.iter_mut()
204            .flat_map(|x| x.iter_mut())
205            .zip(other.iter())
206            .for_each(|(self_i, vector_i)| *self_i -= vector_i)
207    }
208    fn decrement_from_chained(&mut self, other: &mut Vector, vector: Vector) {
209        self.iter_mut()
210            .flat_map(|x| x.iter_mut())
211            .chain(other.iter_mut())
212            .zip(vector)
213            .for_each(|(entry_i, vector_i)| *entry_i -= vector_i)
214    }
215    fn decrement_from_retained(&mut self, retained: &[bool], other: &Vector) {
216        self.iter_mut()
217            .flat_map(|x| x.iter_mut())
218            .zip(retained.iter())
219            .filter(|(_, retained_i)| **retained_i)
220            .zip(other.iter())
221            .for_each(|((self_i, _), vector_i)| *self_i -= vector_i)
222    }
223}
224
225impl<const D: usize, const I: usize> Sub<Vector> for TensorRank1Vec<D, I> {
226    type Output = Self;
227    fn sub(mut self, vector: Vector) -> Self::Output {
228        self.iter_mut().enumerate().for_each(|(a, self_a)| {
229            self_a
230                .iter_mut()
231                .enumerate()
232                .for_each(|(i, self_a_i)| *self_a_i -= vector[D * a + i])
233        });
234        self
235    }
236}
237
238impl<const D: usize, const I: usize> Sub<&Vector> for TensorRank1Vec<D, I> {
239    type Output = Self;
240    fn sub(mut self, vector: &Vector) -> Self::Output {
241        self.iter_mut().enumerate().for_each(|(a, self_a)| {
242            self_a
243                .iter_mut()
244                .enumerate()
245                .for_each(|(i, self_a_i)| *self_a_i -= vector[D * a + i])
246        });
247        self
248    }
249}
250
251impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2Vec2D<D, I, J>>
252    for &TensorRank1Vec<D, I>
253{
254    type Output = TensorRank1Vec<D, J>;
255    fn div(self, _tensor_rank_2_vec_2d: TensorRank2Vec2D<D, I, J>) -> Self::Output {
256        todo!()
257    }
258}
259
260impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2SparseVec2D<D, I, J>>
261    for &TensorRank1Vec<D, I>
262{
263    type Output = TensorRank1Vec<D, J>;
264    fn div(self, _tensor_rank_2_sparse_vec_2d: TensorRank2SparseVec2D<D, I, J>) -> Self::Output {
265        todo!()
266    }
267}
268
269impl<const D: usize, const I: usize, const J: usize> Div<TensorRank2SparseVec2DSymmetric<D, I, J>>
270    for &TensorRank1Vec<D, I>
271{
272    type Output = TensorRank1Vec<D, J>;
273    fn div(
274        self,
275        _tensor_rank_2_sparse_symmetric_vec_2d: TensorRank2SparseVec2DSymmetric<D, I, J>,
276    ) -> Self::Output {
277        todo!()
278    }
279}
280
281impl<const D: usize, const I: usize> FiniteDifference for TensorRank1Vec<D, I> {
282    fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
283        let error_count = self
284            .iter()
285            .zip(comparator.iter())
286            .map(|(entry, comparator_entry)| {
287                entry
288                    .iter()
289                    .zip(comparator_entry.iter())
290                    .filter(|&(&entry_i, &comparator_entry_i)| {
291                        (entry_i / comparator_entry_i - 1.0).abs() >= epsilon
292                            && (entry_i.abs() >= epsilon || comparator_entry_i.abs() >= epsilon)
293                    })
294                    .count()
295            })
296            .sum();
297        if error_count > 0 {
298            let auxiliary = self
299                .iter()
300                .zip(comparator.iter())
301                .map(|(entry, comparator_entry)| {
302                    entry
303                        .iter()
304                        .zip(comparator_entry.iter())
305                        .filter(|&(&entry_i, &comparator_entry_i)| {
306                            (entry_i / comparator_entry_i - 1.0).abs() >= epsilon
307                                && (entry_i - comparator_entry_i).abs() >= epsilon
308                                && (entry_i.abs() >= epsilon || comparator_entry_i.abs() >= epsilon)
309                        })
310                        .count()
311                })
312                .sum::<usize>()
313                > 0;
314            Some((auxiliary, error_count))
315        } else {
316            None
317        }
318    }
319}