rill_core/math/vector/
math.rs1use super::traits::{Vector, VectorTranscendental};
6use crate::Transcendental;
7
8pub fn sin_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
14where
15 V: VectorTranscendental<T, N>,
16{
17 assert_eq!(input.len(), output.len());
18
19 let chunks = input.len() / N;
20 let remainder = input.len() % N;
21
22 for i in 0..chunks {
23 let start = i * N;
24 let vec = V::load(&input[start..start + N]);
25 let result = vec.sin();
26 result.store(&mut output[start..start + N]);
27 }
28
29 if remainder > 0 {
30 let start = chunks * N;
31 for i in 0..remainder {
32 output[start + i] = input[start + i].sin();
33 }
34 }
35}
36
37pub fn cos_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
39where
40 V: VectorTranscendental<T, N>,
41{
42 assert_eq!(input.len(), output.len());
43
44 let chunks = input.len() / N;
45 let remainder = input.len() % N;
46
47 for i in 0..chunks {
48 let start = i * N;
49 let vec = V::load(&input[start..start + N]);
50 let result = vec.cos();
51 result.store(&mut output[start..start + N]);
52 }
53
54 if remainder > 0 {
55 let start = chunks * N;
56 for i in 0..remainder {
57 output[start + i] = input[start + i].cos();
58 }
59 }
60}
61
62pub fn tan_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
64where
65 V: VectorTranscendental<T, N>,
66{
67 assert_eq!(input.len(), output.len());
68
69 let chunks = input.len() / N;
70 let remainder = input.len() % N;
71
72 for i in 0..chunks {
73 let start = i * N;
74 let vec = V::load(&input[start..start + N]);
75 let result = vec.tan();
76 result.store(&mut output[start..start + N]);
77 }
78
79 if remainder > 0 {
80 let start = chunks * N;
81 for i in 0..remainder {
82 output[start + i] = input[start + i].tan();
83 }
84 }
85}
86
87pub fn exp_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
89where
90 V: VectorTranscendental<T, N>,
91{
92 assert_eq!(input.len(), output.len());
93
94 let chunks = input.len() / N;
95 let remainder = input.len() % N;
96
97 for i in 0..chunks {
98 let start = i * N;
99 let vec = V::load(&input[start..start + N]);
100 let result = vec.exp();
101 result.store(&mut output[start..start + N]);
102 }
103
104 if remainder > 0 {
105 let start = chunks * N;
106 for i in 0..remainder {
107 output[start + i] = input[start + i].exp();
108 }
109 }
110}
111
112pub fn ln_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
114where
115 V: VectorTranscendental<T, N>,
116{
117 assert_eq!(input.len(), output.len());
118
119 let chunks = input.len() / N;
120 let remainder = input.len() % N;
121
122 for i in 0..chunks {
123 let start = i * N;
124 let vec = V::load(&input[start..start + N]);
125 let result = vec.ln();
126 result.store(&mut output[start..start + N]);
127 }
128
129 if remainder > 0 {
130 let start = chunks * N;
131 for i in 0..remainder {
132 output[start + i] = input[start + i].ln();
133 }
134 }
135}
136
137pub fn sqrt_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
139where
140 V: VectorTranscendental<T, N>,
141{
142 assert_eq!(input.len(), output.len());
143
144 let chunks = input.len() / N;
145 let remainder = input.len() % N;
146
147 for i in 0..chunks {
148 let start = i * N;
149 let vec = V::load(&input[start..start + N]);
150 let result = vec.sqrt();
151 result.store(&mut output[start..start + N]);
152 }
153
154 if remainder > 0 {
155 let start = chunks * N;
156 for i in 0..remainder {
157 output[start + i] = input[start + i].sqrt();
158 }
159 }
160}
161
162pub fn abs_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
164where
165 V: Vector<T, N>,
166{
167 assert_eq!(input.len(), output.len());
168
169 let chunks = input.len() / N;
170 let remainder = input.len() % N;
171
172 for i in 0..chunks {
173 let start = i * N;
174 let vec = V::load(&input[start..start + N]);
175 let result = vec.abs();
176 result.store(&mut output[start..start + N]);
177 }
178
179 if remainder > 0 {
180 let start = chunks * N;
181 for i in 0..remainder {
182 output[start + i] = input[start + i].abs();
183 }
184 }
185}
186
187pub fn min_slice<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], output: &mut [T])
189where
190 V: Vector<T, N>,
191{
192 assert_eq!(a.len(), b.len());
193 assert_eq!(a.len(), output.len());
194
195 let chunks = a.len() / N;
196 let remainder = a.len() % N;
197
198 for i in 0..chunks {
199 let start = i * N;
200 let a_vec = V::load(&a[start..start + N]);
201 let b_vec = V::load(&b[start..start + N]);
202 let result = a_vec.min(&b_vec);
203 result.store(&mut output[start..start + N]);
204 }
205
206 if remainder > 0 {
207 let start = chunks * N;
208 for i in 0..remainder {
209 output[start + i] = a[start + i].min(b[start + i]);
210 }
211 }
212}
213
214pub fn max_slice<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], output: &mut [T])
216where
217 V: Vector<T, N>,
218{
219 assert_eq!(a.len(), b.len());
220 assert_eq!(a.len(), output.len());
221
222 let chunks = a.len() / N;
223 let remainder = a.len() % N;
224
225 for i in 0..chunks {
226 let start = i * N;
227 let a_vec = V::load(&a[start..start + N]);
228 let b_vec = V::load(&b[start..start + N]);
229 let result = a_vec.max(&b_vec);
230 result.store(&mut output[start..start + N]);
231 }
232
233 if remainder > 0 {
234 let start = chunks * N;
235 for i in 0..remainder {
236 output[start + i] = a[start + i].max(b[start + i]);
237 }
238 }
239}
240
241pub fn clamp_slice<T: Transcendental, const N: usize, V>(
243 input: &[T],
244 min: &[T],
245 max: &[T],
246 output: &mut [T],
247) where
248 V: Vector<T, N>,
249{
250 assert_eq!(input.len(), min.len());
251 assert_eq!(input.len(), max.len());
252 assert_eq!(input.len(), output.len());
253
254 let chunks = input.len() / N;
255 let remainder = input.len() % N;
256
257 for i in 0..chunks {
258 let start = i * N;
259 let input_vec = V::load(&input[start..start + N]);
260 let min_vec = V::load(&min[start..start + N]);
261 let max_vec = V::load(&max[start..start + N]);
262 let result = input_vec.clamp(&min_vec, &max_vec);
263 result.store(&mut output[start..start + N]);
264 }
265
266 if remainder > 0 {
267 let start = chunks * N;
268 for i in 0..remainder {
269 output[start + i] = input[start + i].clamp(min[start + i], max[start + i]);
270 }
271 }
272}
273
274#[cfg(feature = "fast_math")]
280pub fn fast_sin_slice_f32(input: &[f32], output: &mut [f32]) {
281 sin_slice::<f32, 4, crate::math::vector::scalar::ScalarVector4<f32>>(input, output);
283}
284
285#[cfg(feature = "fast_math")]
287pub fn fast_cos_slice_f32(input: &[f32], output: &mut [f32]) {
288 cos_slice::<f32, 4, crate::math::vector::scalar::ScalarVector4<f32>>(input, output);
290}
291
292#[cfg(test)]
297mod tests {
298 use super::*;
299 use crate::Transcendental;
300
301 }