Skip to main content

rill_core/math/vector/
math.rs

1//! # Математические функции для векторов
2//!
3//! Реализация математических функций (sin, cos, exp, ln, sqrt и т.д.) для векторных типов.
4
5use super::traits::{Vector, VectorTranscendental};
6use crate::Transcendental;
7
8// -----------------------------------------------------------------------------
9// Функции для работы со слайсами
10// -----------------------------------------------------------------------------
11
12/// Поэлементный синус слайса
13pub 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
37/// Поэлементный косинус слайса
38pub 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
62/// Поэлементный тангенс слайса
63pub 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
87/// Поэлементная экспонента слайса
88pub 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
112/// Поэлементный натуральный логарифм слайса
113pub 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
137/// Поэлементный квадратный корень слайса
138pub 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
162/// Поэлементный модуль слайса
163pub 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
187/// Поэлементный минимум двух слайсов
188pub 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
214/// Поэлементный максимум двух слайсов
215pub 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
241/// Поэлементное ограничение слайса
242pub 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// -----------------------------------------------------------------------------
275// Специальные математические функции
276// -----------------------------------------------------------------------------
277
278/// Быстрый синус через аппроксимацию (только для f32)
279#[cfg(feature = "fast_math")]
280pub fn fast_sin_slice_f32(input: &[f32], output: &mut [f32]) {
281    // TODO: реализовать аппроксимацию
282    sin_slice::<f32, 4, crate::math::vector::scalar::ScalarVector4<f32>>(input, output);
283}
284
285/// Быстрый косинус через аппроксимацию (только для f32)
286#[cfg(feature = "fast_math")]
287pub fn fast_cos_slice_f32(input: &[f32], output: &mut [f32]) {
288    // TODO: реализовать аппроксимацию
289    cos_slice::<f32, 4, crate::math::vector::scalar::ScalarVector4<f32>>(input, output);
290}
291
292// -----------------------------------------------------------------------------
293// Тесты
294// -----------------------------------------------------------------------------
295
296#[cfg(test)]
297mod tests {
298    use super::*;
299    use crate::Transcendental;
300
301    // Тесты будут добавлены после реализации скалярных векторов
302}