Skip to main content

rill_core/math/vector/
ops.rs

1//! # Арифметические операции для векторов
2//!
3//! Реализация базовых арифметических операций для векторных типов.
4
5use super::traits::*;
6use crate::Transcendental;
7
8// -----------------------------------------------------------------------------
9// Вспомогательные функции
10// -----------------------------------------------------------------------------
11
12/// Поэлементное сложение двух слайсов с сохранением результата в третий
13pub fn add_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
14where
15    V: Vector<T, N>,
16{
17    assert_eq!(a.len(), b.len());
18    assert_eq!(a.len(), out.len());
19
20    let chunks = a.len() / N;
21    let remainder = a.len() % N;
22
23    for i in 0..chunks {
24        let start = i * N;
25        let a_vec = V::load(&a[start..start + N]);
26        let b_vec = V::load(&b[start..start + N]);
27        let result = a_vec + b_vec;
28        result.store(&mut out[start..start + N]);
29    }
30
31    // Обработка остатка
32    if remainder > 0 {
33        let start = chunks * N;
34        for i in 0..remainder {
35            out[start + i] = a[start + i] + b[start + i];
36        }
37    }
38}
39
40/// Поэлементное вычитание двух слайсов
41pub fn sub_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
42where
43    V: Vector<T, N>,
44{
45    assert_eq!(a.len(), b.len());
46    assert_eq!(a.len(), out.len());
47
48    let chunks = a.len() / N;
49    let remainder = a.len() % N;
50
51    for i in 0..chunks {
52        let start = i * N;
53        let a_vec = V::load(&a[start..start + N]);
54        let b_vec = V::load(&b[start..start + N]);
55        let result = a_vec - b_vec;
56        result.store(&mut out[start..start + N]);
57    }
58
59    if remainder > 0 {
60        let start = chunks * N;
61        for i in 0..remainder {
62            out[start + i] = a[start + i] - b[start + i];
63        }
64    }
65}
66
67/// Поэлементное умножение двух слайсов
68pub fn mul_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
69where
70    V: Vector<T, N>,
71{
72    assert_eq!(a.len(), b.len());
73    assert_eq!(a.len(), out.len());
74
75    let chunks = a.len() / N;
76    let remainder = a.len() % N;
77
78    for i in 0..chunks {
79        let start = i * N;
80        let a_vec = V::load(&a[start..start + N]);
81        let b_vec = V::load(&b[start..start + N]);
82        let result = a_vec * b_vec;
83        result.store(&mut out[start..start + N]);
84    }
85
86    if remainder > 0 {
87        let start = chunks * N;
88        for i in 0..remainder {
89            out[start + i] = a[start + i] * b[start + i];
90        }
91    }
92}
93
94/// Поэлементное деление двух слайсов
95pub fn div_slices<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], out: &mut [T])
96where
97    V: Vector<T, N>,
98{
99    assert_eq!(a.len(), b.len());
100    assert_eq!(a.len(), out.len());
101
102    let chunks = a.len() / N;
103    let remainder = a.len() % N;
104
105    for i in 0..chunks {
106        let start = i * N;
107        let a_vec = V::load(&a[start..start + N]);
108        let b_vec = V::load(&b[start..start + N]);
109        let result = a_vec / b_vec;
110        result.store(&mut out[start..start + N]);
111    }
112
113    if remainder > 0 {
114        let start = chunks * N;
115        for i in 0..remainder {
116            out[start + i] = a[start + i] / b[start + i];
117        }
118    }
119}
120
121/// Умножение слайса на скаляр
122pub fn mul_scalar_slice<T: Transcendental, const N: usize, V>(a: &[T], scalar: T, out: &mut [T])
123where
124    V: Vector<T, N>,
125{
126    assert_eq!(a.len(), out.len());
127
128    let scalar_vec = V::splat(scalar);
129    let chunks = a.len() / N;
130    let remainder = a.len() % N;
131
132    for i in 0..chunks {
133        let start = i * N;
134        let a_vec = V::load(&a[start..start + N]);
135        let result = a_vec * scalar_vec;
136        result.store(&mut out[start..start + N]);
137    }
138
139    if remainder > 0 {
140        let start = chunks * N;
141        for i in 0..remainder {
142            out[start + i] = a[start + i] * scalar;
143        }
144    }
145}
146
147/// Сложение слайса со скаляром
148pub fn add_scalar_slice<T: Transcendental, const N: usize, V>(a: &[T], scalar: T, out: &mut [T])
149where
150    V: Vector<T, N>,
151{
152    assert_eq!(a.len(), out.len());
153
154    let scalar_vec = V::splat(scalar);
155    let chunks = a.len() / N;
156    let remainder = a.len() % N;
157
158    for i in 0..chunks {
159        let start = i * N;
160        let a_vec = V::load(&a[start..start + N]);
161        let result = a_vec + scalar_vec;
162        result.store(&mut out[start..start + N]);
163    }
164
165    if remainder > 0 {
166        let start = chunks * N;
167        for i in 0..remainder {
168            out[start + i] = a[start + i] + scalar;
169        }
170    }
171}
172
173// -----------------------------------------------------------------------------
174// Тесты
175// -----------------------------------------------------------------------------
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180
181    // Тестовые реализации для скалярных векторов будут добавлены позже
182    // #[test]
183    // fn test_add_slices() {
184    // }
185}