Skip to main content

rill_core/math/vector/
ops.rs

1//! # Arithmetic operations for vectors
2//!
3//! Implementation of basic arithmetic operations for vector types.
4
5use super::traits::*;
6use crate::Transcendental;
7
8// -----------------------------------------------------------------------------
9// Helper functions
10
11/// Element-wise addition of two slices, storing the result in a third
12pub fn add_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
13where
14    V: Vector<T, N>,
15{
16    assert_eq!(a.len(), b.len());
17    assert_eq!(a.len(), out.len());
18
19    let chunks = a.len() / N;
20    let remainder = a.len() % N;
21
22    for i in 0..chunks {
23        let start = i * N;
24        let a_vec = V::load(&a[start..start + N]);
25        let b_vec = V::load(&b[start..start + N]);
26        let result = a_vec + b_vec;
27        result.store(&mut out[start..start + N]);
28    }
29
30    // Handle remainder
31    if remainder > 0 {
32        let start = chunks * N;
33        for i in 0..remainder {
34            out[start + i] = a[start + i] + b[start + i];
35        }
36    }
37}
38
39/// Element-wise subtraction of two slices
40pub fn sub_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
41where
42    V: Vector<T, N>,
43{
44    assert_eq!(a.len(), b.len());
45    assert_eq!(a.len(), out.len());
46
47    let chunks = a.len() / N;
48    let remainder = a.len() % N;
49
50    for i in 0..chunks {
51        let start = i * N;
52        let a_vec = V::load(&a[start..start + N]);
53        let b_vec = V::load(&b[start..start + N]);
54        let result = a_vec - b_vec;
55        result.store(&mut out[start..start + N]);
56    }
57
58    if remainder > 0 {
59        let start = chunks * N;
60        for i in 0..remainder {
61            out[start + i] = a[start + i] - b[start + i];
62        }
63    }
64}
65
66/// Element-wise multiplication of two slices
67pub fn mul_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
68where
69    V: Vector<T, N>,
70{
71    assert_eq!(a.len(), b.len());
72    assert_eq!(a.len(), out.len());
73
74    let chunks = a.len() / N;
75    let remainder = a.len() % N;
76
77    for i in 0..chunks {
78        let start = i * N;
79        let a_vec = V::load(&a[start..start + N]);
80        let b_vec = V::load(&b[start..start + N]);
81        let result = a_vec * b_vec;
82        result.store(&mut out[start..start + N]);
83    }
84
85    if remainder > 0 {
86        let start = chunks * N;
87        for i in 0..remainder {
88            out[start + i] = a[start + i] * b[start + i];
89        }
90    }
91}
92
93/// Element-wise division of two slices
94pub fn div_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
95where
96    V: Vector<T, N>,
97{
98    assert_eq!(a.len(), b.len());
99    assert_eq!(a.len(), out.len());
100
101    let chunks = a.len() / N;
102    let remainder = a.len() % N;
103
104    for i in 0..chunks {
105        let start = i * N;
106        let a_vec = V::load(&a[start..start + N]);
107        let b_vec = V::load(&b[start..start + N]);
108        let result = a_vec / b_vec;
109        result.store(&mut out[start..start + N]);
110    }
111
112    if remainder > 0 {
113        let start = chunks * N;
114        for i in 0..remainder {
115            out[start + i] = a[start + i] / b[start + i];
116        }
117    }
118}
119
120/// Multiply a slice by a scalar
121pub fn mul_scalar_slice<T: Transcendental, const N: usize, V>(a: &[T], scalar: T, out: &mut [T])
122where
123    V: Vector<T, N>,
124{
125    assert_eq!(a.len(), out.len());
126
127    let scalar_vec = V::splat(scalar);
128    let chunks = a.len() / N;
129    let remainder = a.len() % N;
130
131    for i in 0..chunks {
132        let start = i * N;
133        let a_vec = V::load(&a[start..start + N]);
134        let result = a_vec * scalar_vec;
135        result.store(&mut out[start..start + N]);
136    }
137
138    if remainder > 0 {
139        let start = chunks * N;
140        for i in 0..remainder {
141            out[start + i] = a[start + i] * scalar;
142        }
143    }
144}
145
146/// Add a scalar to a slice
147pub fn add_scalar_slice<T: Transcendental, const N: usize, V>(a: &[T], scalar: T, out: &mut [T])
148where
149    V: Vector<T, N>,
150{
151    assert_eq!(a.len(), out.len());
152
153    let scalar_vec = V::splat(scalar);
154    let chunks = a.len() / N;
155    let remainder = a.len() % N;
156
157    for i in 0..chunks {
158        let start = i * N;
159        let a_vec = V::load(&a[start..start + N]);
160        let result = a_vec + scalar_vec;
161        result.store(&mut out[start..start + N]);
162    }
163
164    if remainder > 0 {
165        let start = chunks * N;
166        for i in 0..remainder {
167            out[start + i] = a[start + i] + scalar;
168        }
169    }
170}
171
172// -----------------------------------------------------------------------------
173// Tests
174// -----------------------------------------------------------------------------
175
176#[cfg(test)]
177mod tests {
178    use super::*;
179
180    // Test implementations for scalar vectors will be added later
181    // #[test]
182    // fn test_add_slices() {
183    // }
184}