1use std::array;
2use std::ops::{Deref, DerefMut, MulAssign};
3
4use num_traits::{Float, NumCast, ToPrimitive};
5
6use crate::boxed_ref::{BoxedRef, BoxedRefMut};
7use crate::core::{ToInputArray, ToInputOutputArray, ToOutputArray, _InputArray, _InputOutputArray, _OutputArray};
8use crate::traits::{Boxed, OpenCVFromExtern, OpenCVIntoExternContainer, OpenCVType, OpenCVTypeExternContainer};
9use crate::{extern_receive, extern_send, sys, Result};
10
11mod operations;
12
13#[repr(C)]
16#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)]
17pub struct VecN<T, const N: usize>(pub [T; N]);
18
19impl<T, const N: usize> Default for VecN<T, N>
20where
21 [T; N]: Default,
22{
23 #[inline]
24 fn default() -> Self {
25 Self(Default::default())
26 }
27}
28
29impl<T, const N: usize> VecN<T, N> {
30 #[inline]
31 pub const fn from_array(val: [T; N]) -> Self {
32 Self(val)
33 }
34
35 #[inline]
36 pub const fn all(v0: T) -> Self
37 where
38 T: Copy,
39 {
40 Self::from_array([v0; N])
41 }
42
43 #[inline]
45 pub fn mul(&self, v: Self) -> Self
46 where
47 T: MulAssign,
48 Self: Copy,
49 {
50 let mut out = *self;
51 out.iter_mut().zip(v).for_each(|(dest, m)| *dest *= m);
52 out
53 }
54
55 #[inline]
57 pub fn to<D: NumCast + Default + Copy>(self) -> Option<VecN<D, N>>
58 where
59 T: ToPrimitive,
60 {
61 let mut out = [D::default(); N];
62 for (dest, src) in out.iter_mut().zip(self) {
63 *dest = D::from(src)?;
64 }
65 Some(VecN(out))
66 }
67}
68
69impl<T, const N: usize> From<[T; N]> for VecN<T, N> {
70 #[inline]
71 fn from(s: [T; N]) -> Self {
72 Self::from_array(s)
73 }
74}
75
76impl<T, const N: usize> Deref for VecN<T, N> {
77 type Target = [T; N];
78
79 #[inline]
80 fn deref(&self) -> &Self::Target {
81 &self.0
82 }
83}
84
85impl<T, const N: usize> DerefMut for VecN<T, N> {
86 #[inline]
87 fn deref_mut(&mut self) -> &mut Self::Target {
88 &mut self.0
89 }
90}
91
92impl<T, const N: usize> IntoIterator for VecN<T, N> {
93 type Item = T;
94 type IntoIter = array::IntoIter<T, N>;
95
96 #[inline]
97 fn into_iter(self) -> array::IntoIter<T, N> {
98 self.0.into_iter()
99 }
100}
101
102impl<F: Float> VecN<F, 2> {
103 #[inline]
105 pub fn conj(&self) -> Self {
106 Self([self[0], -self[1]])
107 }
108}
109
110impl<F: Float> VecN<F, 3> {
111 #[inline]
113 pub fn cross(&self, v: Self) -> Self {
114 Self([
115 self[1] * v[2] - self[2] * v[1],
116 self[2] * v[0] - self[0] * v[2],
117 self[0] * v[1] - self[1] * v[0],
118 ])
119 }
120}
121
122impl<F: Float> VecN<F, 4> {
123 #[inline]
125 pub fn conj(&self) -> Self {
126 Self([self[0], -self[1], -self[2], -self[3]])
127 }
128}
129
130impl<T, const N: usize> OpenCVType<'_> for VecN<T, N> {
131 type Arg = Self;
132}
133
134impl<T, const N: usize> OpenCVFromExtern for VecN<T, N> {
135 type ExternReceive = Self;
136
137 #[inline]
138 unsafe fn opencv_from_extern(s: Self::ExternReceive) -> Self {
139 s
140 }
141}
142
143impl<T, const N: usize> OpenCVIntoExternContainer for VecN<T, N> {
144 type ExternContainer = Self;
145
146 #[inline]
147 fn opencv_into_extern_container_nofail(self) -> Self::ExternContainer {
148 self
149 }
150}
151
152impl<T, const N: usize> OpenCVTypeExternContainer for VecN<T, N> {
153 type ExternSend = *const Self;
154 type ExternSendMut = *mut Self;
155
156 #[inline]
157 fn opencv_as_extern(&self) -> Self::ExternSend {
158 self
159 }
160
161 #[inline]
162 fn opencv_as_extern_mut(&mut self) -> Self::ExternSendMut {
163 self
164 }
165}
166
167impl<T, const N: usize> ToInputArray for VecN<T, N>
168where
169 Self: VecExtern,
170{
171 #[inline]
172 fn input_array(&self) -> Result<BoxedRef<'_, _InputArray>> {
173 unsafe { self.extern_input_array() }
174 .into_result()
175 .map(|ptr| unsafe { _InputArray::from_raw(ptr) }.into())
176 }
177}
178
179impl<T, const N: usize> ToInputArray for &VecN<T, N>
180where
181 VecN<T, N>: VecExtern,
182{
183 #[inline]
184 fn input_array(&self) -> Result<BoxedRef<'_, _InputArray>> {
185 (*self).input_array()
186 }
187}
188
189impl<T, const N: usize> ToOutputArray for VecN<T, N>
190where
191 Self: VecExtern,
192{
193 #[inline]
194 fn output_array(&mut self) -> Result<BoxedRefMut<'_, _OutputArray>> {
195 unsafe { self.extern_output_array() }
196 .into_result()
197 .map(|ptr| unsafe { _OutputArray::from_raw(ptr) }.into())
198 }
199}
200
201impl<T, const N: usize> ToOutputArray for &mut VecN<T, N>
202where
203 VecN<T, N>: VecExtern,
204{
205 #[inline]
206 fn output_array(&mut self) -> Result<BoxedRefMut<'_, _OutputArray>> {
207 (*self).output_array()
208 }
209}
210
211impl<T, const N: usize> ToInputOutputArray for VecN<T, N>
212where
213 Self: VecExtern,
214{
215 #[inline]
216 fn input_output_array(&mut self) -> Result<BoxedRefMut<'_, _InputOutputArray>> {
217 unsafe { self.extern_input_output_array() }
218 .into_result()
219 .map(|ptr| unsafe { _InputOutputArray::from_raw(ptr) }.into())
220 }
221}
222
223impl<T, const N: usize> ToInputOutputArray for &mut VecN<T, N>
224where
225 VecN<T, N>: VecExtern,
226{
227 #[inline]
228 fn input_output_array(&mut self) -> Result<BoxedRefMut<'_, _InputOutputArray>> {
229 (*self).input_output_array()
230 }
231}
232
233#[doc(hidden)]
234pub trait VecExtern {
235 #[doc(hidden)]
236 unsafe fn extern_input_array(&self) -> sys::Result<extern_receive!(_InputArray)>;
237 #[doc(hidden)]
238 unsafe fn extern_output_array(&mut self) -> sys::Result<extern_receive!(_OutputArray)>;
239 #[doc(hidden)]
240 unsafe fn extern_input_output_array(&mut self) -> sys::Result<extern_receive!(_InputOutputArray)>;
241}
242
243macro_rules! vecn_extern {
244 ($type: ty, $len: expr, $extern_input_array: ident, $extern_ouput_array: ident, $extern_input_array_output: ident) => {
245 unsafe extern "C" {
246 fn $extern_input_array(instance: extern_send!($crate::core::VecN<$type, $len>), ocvrs_return: *mut $crate::sys::Result<extern_receive!($crate::core::_InputArray)>);
247 fn $extern_ouput_array(instance: extern_send!(mut $crate::core::VecN<$type, $len>), ocvrs_return: *mut $crate::sys::Result<extern_receive!($crate::core::_OutputArray)>);
248 fn $extern_input_array_output(instance: extern_send!(mut $crate::core::VecN<$type, $len>), ocvrs_return: *mut $crate::sys::Result<extern_receive!($crate::core::_InputOutputArray)>);
249 }
250
251 impl $crate::core::VecExtern for $crate::core::VecN<$type, $len> {
252 #[inline]
253 unsafe fn extern_input_array(&self) -> $crate::sys::Result<extern_receive!($crate::core::_InputArray)> {
254 return_send!(via ocvrs_return);
255 unsafe { $extern_input_array(self, ocvrs_return.as_mut_ptr()); }
256 return_receive!(ocvrs_return => ret);
257 ret
258 }
259
260 #[inline]
261 unsafe fn extern_output_array(&mut self) -> $crate::sys::Result<extern_receive!($crate::core::_OutputArray)> {
262 return_send!(via ocvrs_return);
263 unsafe { $extern_ouput_array(self, ocvrs_return.as_mut_ptr()); }
264 return_receive!(ocvrs_return => ret);
265 ret
266 }
267
268 #[inline]
269 unsafe fn extern_input_output_array(&mut self) -> $crate::sys::Result<extern_receive!($crate::core::_InputOutputArray)> {
270 return_send!(via ocvrs_return);
271 unsafe { $extern_input_array_output(self, ocvrs_return.as_mut_ptr()); }
272 return_receive!(ocvrs_return => ret);
273 ret
274 }
275 }
276 }
277}
278
279vecn_extern!(
280 u8,
281 2,
282 cv_Vec2b_input_array,
283 cv_Vec2b_output_array,
284 cv_Vec2b_input_output_array
285);
286vecn_extern!(
287 f64,
288 2,
289 cv_Vec2d_input_array,
290 cv_Vec2d_output_array,
291 cv_Vec2d_input_output_array
292);
293vecn_extern!(
294 f32,
295 2,
296 cv_Vec2f_input_array,
297 cv_Vec2f_output_array,
298 cv_Vec2f_input_output_array
299);
300vecn_extern!(
301 i32,
302 2,
303 cv_Vec2i_input_array,
304 cv_Vec2i_output_array,
305 cv_Vec2i_input_output_array
306);
307vecn_extern!(
308 i16,
309 2,
310 cv_Vec2s_input_array,
311 cv_Vec2s_output_array,
312 cv_Vec2s_input_output_array
313);
314vecn_extern!(
315 u16,
316 2,
317 cv_Vec2w_input_array,
318 cv_Vec2w_output_array,
319 cv_Vec2w_input_output_array
320);
321
322vecn_extern!(
323 u8,
324 3,
325 cv_Vec3b_input_array,
326 cv_Vec3b_output_array,
327 cv_Vec3b_input_output_array
328);
329vecn_extern!(
330 f64,
331 3,
332 cv_Vec3d_input_array,
333 cv_Vec3d_output_array,
334 cv_Vec3d_input_output_array
335);
336vecn_extern!(
337 f32,
338 3,
339 cv_Vec3f_input_array,
340 cv_Vec3f_output_array,
341 cv_Vec3f_input_output_array
342);
343vecn_extern!(
344 i32,
345 3,
346 cv_Vec3i_input_array,
347 cv_Vec3i_output_array,
348 cv_Vec3i_input_output_array
349);
350vecn_extern!(
351 i16,
352 3,
353 cv_Vec3s_input_array,
354 cv_Vec3s_output_array,
355 cv_Vec3s_input_output_array
356);
357vecn_extern!(
358 u16,
359 3,
360 cv_Vec3w_input_array,
361 cv_Vec3w_output_array,
362 cv_Vec3w_input_output_array
363);
364
365vecn_extern!(
366 u8,
367 4,
368 cv_Vec4b_input_array,
369 cv_Vec4b_output_array,
370 cv_Vec4b_input_output_array
371);
372vecn_extern!(
373 f64,
374 4,
375 cv_Vec4d_input_array,
376 cv_Vec4d_output_array,
377 cv_Vec4d_input_output_array
378);
379vecn_extern!(
380 f32,
381 4,
382 cv_Vec4f_input_array,
383 cv_Vec4f_output_array,
384 cv_Vec4f_input_output_array
385);
386vecn_extern!(
387 i32,
388 4,
389 cv_Vec4i_input_array,
390 cv_Vec4i_output_array,
391 cv_Vec4i_input_output_array
392);
393vecn_extern!(
394 i16,
395 4,
396 cv_Vec4s_input_array,
397 cv_Vec4s_output_array,
398 cv_Vec4s_input_output_array
399);
400vecn_extern!(
401 u16,
402 4,
403 cv_Vec4w_input_array,
404 cv_Vec4w_output_array,
405 cv_Vec4w_input_output_array
406);
407
408vecn_extern!(
409 f64,
410 6,
411 cv_Vec6d_input_array,
412 cv_Vec6d_output_array,
413 cv_Vec6d_input_output_array
414);
415vecn_extern!(
416 f32,
417 6,
418 cv_Vec6f_input_array,
419 cv_Vec6f_output_array,
420 cv_Vec6f_input_output_array
421);
422vecn_extern!(
423 i32,
424 6,
425 cv_Vec6i_input_array,
426 cv_Vec6i_output_array,
427 cv_Vec6i_input_output_array
428);
429
430vecn_extern!(
431 i32,
432 8,
433 cv_Vec8i_input_array,
434 cv_Vec8i_output_array,
435 cv_Vec8i_input_output_array
436);
437
438vecn_extern!(
439 f64,
440 18,
441 cv_Vec18d_input_array,
442 cv_Vec18d_output_array,
443 cv_Vec18d_input_output_array
444);