1use super::traits::*;
35use crate::Transcendental;
36use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
37
38pub fn add_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
43where
44 V: Vector<T, N>,
45{
46 assert_eq!(a.len(), b.len());
47 assert_eq!(a.len(), out.len());
48
49 let chunks = a.len() / N;
50 let remainder = a.len() % N;
51
52 for i in 0..chunks {
53 let start = i * N;
54 let a_vec = V::load(&a[start..start + N]);
55 let b_vec = V::load(&b[start..start + N]);
56 let result = a_vec + b_vec;
57 result.store(&mut out[start..start + N]);
58 }
59
60 if remainder > 0 {
62 let start = chunks * N;
63 for i in 0..remainder {
64 out[start + i] = a[start + i] + b[start + i];
65 }
66 }
67}
68
69pub fn sub_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
71where
72 V: Vector<T, N>,
73{
74 assert_eq!(a.len(), b.len());
75 assert_eq!(a.len(), out.len());
76
77 let chunks = a.len() / N;
78 let remainder = a.len() % N;
79
80 for i in 0..chunks {
81 let start = i * N;
82 let a_vec = V::load(&a[start..start + N]);
83 let b_vec = V::load(&b[start..start + N]);
84 let result = a_vec - b_vec;
85 result.store(&mut out[start..start + N]);
86 }
87
88 if remainder > 0 {
89 let start = chunks * N;
90 for i in 0..remainder {
91 out[start + i] = a[start + i] - b[start + i];
92 }
93 }
94}
95
96pub fn mul_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
98where
99 V: Vector<T, N>,
100{
101 assert_eq!(a.len(), b.len());
102 assert_eq!(a.len(), out.len());
103
104 let chunks = a.len() / N;
105 let remainder = a.len() % N;
106
107 for i in 0..chunks {
108 let start = i * N;
109 let a_vec = V::load(&a[start..start + N]);
110 let b_vec = V::load(&b[start..start + N]);
111 let result = a_vec * b_vec;
112 result.store(&mut out[start..start + N]);
113 }
114
115 if remainder > 0 {
116 let start = chunks * N;
117 for i in 0..remainder {
118 out[start + i] = a[start + i] * b[start + i];
119 }
120 }
121}
122
123pub fn div_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
125where
126 V: Vector<T, N>,
127{
128 assert_eq!(a.len(), b.len());
129 assert_eq!(a.len(), out.len());
130
131 let chunks = a.len() / N;
132 let remainder = a.len() % N;
133
134 for i in 0..chunks {
135 let start = i * N;
136 let a_vec = V::load(&a[start..start + N]);
137 let b_vec = V::load(&b[start..start + N]);
138 let result = a_vec / b_vec;
139 result.store(&mut out[start..start + N]);
140 }
141
142 if remainder > 0 {
143 let start = chunks * N;
144 for i in 0..remainder {
145 out[start + i] = a[start + i] / b[start + i];
146 }
147 }
148}
149
150pub fn mul_scalar_slice<T: Transcendental, const N: usize, V>(a: &[T], scalar: T, out: &mut [T])
152where
153 V: Vector<T, N>,
154{
155 assert_eq!(a.len(), out.len());
156
157 let scalar_vec = V::splat(scalar);
158 let chunks = a.len() / N;
159 let remainder = a.len() % N;
160
161 for i in 0..chunks {
162 let start = i * N;
163 let a_vec = V::load(&a[start..start + N]);
164 let result = a_vec * scalar_vec;
165 result.store(&mut out[start..start + N]);
166 }
167
168 if remainder > 0 {
169 let start = chunks * N;
170 for i in 0..remainder {
171 out[start + i] = a[start + i] * scalar;
172 }
173 }
174}
175
176pub fn add_scalar_slice<T: Transcendental, const N: usize, V>(a: &[T], scalar: T, out: &mut [T])
178where
179 V: Vector<T, N>,
180{
181 assert_eq!(a.len(), out.len());
182
183 let scalar_vec = V::splat(scalar);
184 let chunks = a.len() / N;
185 let remainder = a.len() % N;
186
187 for i in 0..chunks {
188 let start = i * N;
189 let a_vec = V::load(&a[start..start + N]);
190 let result = a_vec + scalar_vec;
191 result.store(&mut out[start..start + N]);
192 }
193
194 if remainder > 0 {
195 let start = chunks * N;
196 for i in 0..remainder {
197 out[start + i] = a[start + i] + scalar;
198 }
199 }
200}
201
202#[derive(Debug)]
212pub struct SliceMut<'a, T>(pub &'a mut [T]);
213
214impl<'a, T: Transcendental> SliceMut<'a, T> {
215 #[inline(always)]
217 pub fn new(slice: &'a mut [T]) -> Self {
218 Self(slice)
219 }
220
221 #[inline(always)]
223 pub fn into_inner(self) -> &'a mut [T] {
224 self.0
225 }
226}
227
228impl<'a, T: Transcendental> AddAssign<&[T]> for SliceMut<'a, T> {
229 fn add_assign(&mut self, rhs: &[T]) {
230 for (a, &b) in self.0.iter_mut().zip(rhs.iter()) {
231 *a += b;
232 }
233 }
234}
235
236impl<'a, T: Transcendental> SubAssign<&[T]> for SliceMut<'a, T> {
237 fn sub_assign(&mut self, rhs: &[T]) {
238 for (a, &b) in self.0.iter_mut().zip(rhs.iter()) {
239 *a -= b;
240 }
241 }
242}
243
244impl<'a, T: Transcendental> MulAssign<&[T]> for SliceMut<'a, T> {
245 fn mul_assign(&mut self, rhs: &[T]) {
246 for (a, &b) in self.0.iter_mut().zip(rhs.iter()) {
247 *a *= b;
248 }
249 }
250}
251
252impl<'a, T: Transcendental> DivAssign<&[T]> for SliceMut<'a, T> {
253 fn div_assign(&mut self, rhs: &[T]) {
254 for (a, &b) in self.0.iter_mut().zip(rhs.iter()) {
255 *a /= b;
256 }
257 }
258}
259
260impl<'a, T: Transcendental> AddAssign<T> for SliceMut<'a, T> {
261 fn add_assign(&mut self, rhs: T) {
262 for v in self.0.iter_mut() {
263 *v = *v + rhs;
264 }
265 }
266}
267
268impl<'a, T: Transcendental> SubAssign<T> for SliceMut<'a, T> {
269 fn sub_assign(&mut self, rhs: T) {
270 for v in self.0.iter_mut() {
271 *v = *v - rhs;
272 }
273 }
274}
275
276impl<'a, T: Transcendental> MulAssign<T> for SliceMut<'a, T> {
277 fn mul_assign(&mut self, rhs: T) {
278 for v in self.0.iter_mut() {
279 *v = *v * rhs;
280 }
281 }
282}
283
284impl<'a, T: Transcendental> DivAssign<T> for SliceMut<'a, T> {
285 fn div_assign(&mut self, rhs: T) {
286 for v in self.0.iter_mut() {
287 *v = *v / rhs;
288 }
289 }
290}
291
292pub struct SlicePair<'a, T>(pub &'a [T], pub &'a [T]);
313
314impl<'a, T: Transcendental> SlicePair<'a, T> {
315 #[inline(always)]
317 pub fn new(a: &'a [T], b: &'a [T]) -> Self {
318 Self(a, b)
319 }
320
321 #[inline(always)]
323 pub fn add_into<const N: usize, V: Vector<T, N>>(self, out: &mut [T]) {
324 add_slices::<T, N, V>(self.0, self.1, out)
325 }
326
327 #[inline(always)]
329 pub fn sub_into<const N: usize, V: Vector<T, N>>(self, out: &mut [T]) {
330 sub_slices::<T, N, V>(self.0, self.1, out)
331 }
332
333 #[inline(always)]
335 pub fn mul_into<const N: usize, V: Vector<T, N>>(self, out: &mut [T]) {
336 mul_slices::<T, N, V>(self.0, self.1, out)
337 }
338
339 #[inline(always)]
341 pub fn div_into<const N: usize, V: Vector<T, N>>(self, out: &mut [T]) {
342 div_slices::<T, N, V>(self.0, self.1, out)
343 }
344
345 pub fn rem_into<const N: usize, V: Vector<T, N>>(self, out: &mut [T]) {
347 for (o, (&a, &b)) in out.iter_mut().zip(self.0.iter().zip(self.1.iter())) {
348 *o = a % b;
349 }
350 }
351}
352
353#[cfg(test)]
358mod tests {
359 use super::*;
360
361 }