1#![deny(missing_docs)]
51#![no_std]
52
53extern crate num_traits;
54
55pub extern crate generic_array;
56
57pub use generic_array::{typenum, ArrayLength};
58
59#[cfg(feature = "serde1")]
60extern crate serde;
61
62use core::{cmp, ptr, slice};
63
64use core::borrow::{Borrow, BorrowMut};
65use core::ops::{Deref, DerefMut, Index, IndexMut};
66use core::ops::{Range, RangeFrom, RangeFull, RangeTo};
67
68use core::iter::FromIterator;
69
70use core::fmt::{Debug, Formatter, Result as FmtResult};
71
72use generic_array::functional::*;
73use generic_array::sequence::*;
74use generic_array::{GenericArray, GenericArrayIter};
75
76#[cfg(feature = "serde1")]
77mod impl_serde;
78
79pub mod geometry;
80pub mod impls;
81pub mod simd;
82
83#[repr(transparent)]
92pub struct NumericArray<T, N: ArrayLength>(GenericArray<T, N>);
93
94#[macro_export]
103macro_rules! narr {
104 ($($t:tt)*) => {
105 $crate::NumericArray::new($crate::generic_array::arr!($($t)*))
106 }
107}
108
109unsafe impl<T, N: ArrayLength> GenericSequence<T> for NumericArray<T, N> {
110 type Length = N;
111 type Sequence = Self;
112
113 #[inline(always)]
114 fn generate<F>(f: F) -> Self
115 where
116 F: FnMut(usize) -> T,
117 {
118 NumericArray(GenericArray::generate(f))
119 }
120}
121
122#[derive(Debug, Clone, Copy)]
129#[repr(transparent)]
130pub struct NumericConstant<T>(pub T);
131
132#[macro_export]
134macro_rules! nconstant {
135 ($value:expr) => {
136 $crate::NumericConstant($value)
137 };
138}
139
140impl<T> Deref for NumericConstant<T> {
141 type Target = T;
142
143 fn deref(&self) -> &T {
144 &self.0
145 }
146}
147
148impl<T> DerefMut for NumericConstant<T> {
149 fn deref_mut(&mut self) -> &mut T {
150 &mut self.0
151 }
152}
153
154impl<T: Debug, N: ArrayLength> Debug for NumericArray<T, N> {
155 fn fmt(&self, f: &mut Formatter) -> FmtResult {
156 f.debug_tuple("NumericArray").field(&self.0).finish()
157 }
158}
159
160impl<X, T, N: ArrayLength> From<X> for NumericArray<T, N>
161where
162 X: Into<GenericArray<T, N>>,
163{
164 fn from(x: X) -> NumericArray<T, N> {
165 NumericArray::new(x.into())
166 }
167}
168
169impl<T: Clone, N: ArrayLength> Clone for NumericArray<T, N> {
170 fn clone(&self) -> NumericArray<T, N> {
171 NumericArray(self.0.clone())
172 }
173}
174
175impl<T: Copy, N: ArrayLength> Copy for NumericArray<T, N> where N::ArrayType<T>: Copy {}
176
177impl<T, N: ArrayLength> Deref for NumericArray<T, N> {
178 type Target = [T];
179
180 fn deref(&self) -> &Self::Target {
181 self.as_slice()
182 }
183}
184
185impl<T, N: ArrayLength> DerefMut for NumericArray<T, N> {
186 fn deref_mut(&mut self) -> &mut Self::Target {
187 self.as_mut_slice()
188 }
189}
190
191impl<T, U, N: ArrayLength> PartialEq<NumericArray<U, N>> for NumericArray<T, N>
192where
193 T: PartialEq<U>,
194{
195 fn eq(&self, rhs: &NumericArray<U, N>) -> bool {
196 **self == **rhs
197 }
198}
199
200impl<T, U, N: ArrayLength> PartialEq<GenericArray<U, N>> for NumericArray<T, N>
201where
202 T: PartialEq<U>,
203{
204 fn eq(&self, rhs: &GenericArray<U, N>) -> bool {
205 **self == **rhs
206 }
207}
208
209impl<T, N: ArrayLength> cmp::Eq for NumericArray<T, N> where T: cmp::Eq {}
210
211impl<T, N: ArrayLength> PartialOrd<Self> for NumericArray<T, N>
212where
213 T: PartialOrd,
214{
215 #[inline]
216 fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
217 PartialOrd::partial_cmp(&self.0, &rhs.0)
218 }
219
220 #[inline]
221 fn lt(&self, rhs: &Self) -> bool {
222 PartialOrd::lt(&self.0, &rhs.0)
223 }
224
225 #[inline]
226 fn le(&self, rhs: &Self) -> bool {
227 PartialOrd::le(&self.0, &rhs.0)
228 }
229
230 #[inline]
231 fn gt(&self, rhs: &Self) -> bool {
232 PartialOrd::gt(&self.0, &rhs.0)
233 }
234
235 #[inline]
236 fn ge(&self, rhs: &Self) -> bool {
237 PartialOrd::ge(&self.0, &rhs.0)
238 }
239}
240
241impl<T, N: ArrayLength> PartialOrd<GenericArray<T, N>> for NumericArray<T, N>
242where
243 T: PartialOrd,
244{
245 #[inline]
246 fn partial_cmp(&self, rhs: &GenericArray<T, N>) -> Option<cmp::Ordering> {
247 PartialOrd::partial_cmp(&self.0, rhs)
248 }
249
250 #[inline]
251 fn lt(&self, rhs: &GenericArray<T, N>) -> bool {
252 PartialOrd::lt(&self.0, rhs)
253 }
254
255 #[inline]
256 fn le(&self, rhs: &GenericArray<T, N>) -> bool {
257 PartialOrd::le(&self.0, rhs)
258 }
259
260 #[inline]
261 fn gt(&self, rhs: &GenericArray<T, N>) -> bool {
262 PartialOrd::gt(&self.0, rhs)
263 }
264
265 #[inline]
266 fn ge(&self, rhs: &GenericArray<T, N>) -> bool {
267 PartialOrd::ge(&self.0, rhs)
268 }
269}
270
271impl<T, N: ArrayLength> cmp::Ord for NumericArray<T, N>
272where
273 T: cmp::Ord,
274{
275 #[inline]
276 fn cmp(&self, rhs: &Self) -> cmp::Ordering {
277 cmp::Ord::cmp(&self.0, &rhs.0)
278 }
279}
280
281impl<T, N: ArrayLength> NumericArray<T, N> {
282 #[inline]
300 pub fn new(arr: GenericArray<T, N>) -> NumericArray<T, N> {
301 NumericArray(arr)
302 }
303
304 #[inline]
315 pub fn splat(t: T) -> NumericArray<T, N>
316 where
317 T: Clone,
318 {
319 NumericArray(GenericArray::generate(|_| t.clone()))
320 }
321
322 pub fn convert<U: From<T>>(self) -> NumericArray<U, N> {
324 self.0.map(From::from).into()
325 }
326
327 #[inline]
329 pub fn into_array(self) -> GenericArray<T, N> {
330 self.0
331 }
332
333 #[inline]
335 pub fn as_array(&self) -> &GenericArray<T, N> {
336 &self.0
337 }
338
339 #[inline(always)]
341 pub fn as_mut_array(&mut self) -> &mut GenericArray<T, N> {
342 &mut self.0
343 }
344
345 #[inline(always)]
347 pub fn as_slice(&self) -> &[T] {
348 &self.0
349 }
350
351 #[inline(always)]
353 pub fn as_mut_slice(&mut self) -> &mut [T] {
354 &mut self.0
355 }
356
357 #[inline(always)]
361 pub fn from_slice(slice: &[T]) -> &NumericArray<T, N> {
362 slice.into()
363 }
364
365 #[inline(always)]
369 pub fn from_mut_slice(slice: &mut [T]) -> &mut NumericArray<T, N> {
370 slice.into()
371 }
372}
373
374use core::ops::Sub;
375use typenum::{bit::B1 as True, Diff, IsGreaterOrEqual};
376
377impl<T, N: ArrayLength> NumericArray<T, N> {
378 #[inline(always)]
380 pub fn offset<V: ArrayLength, O: ArrayLength>(&self) -> &NumericArray<T, V>
381 where
382 N: Sub<O>,
383 Diff<N, O>: IsGreaterOrEqual<V, Output = True>,
384 {
385 unsafe { &*((self as *const _ as *const T).add(O::USIZE) as *const NumericArray<T, V>) }
386 }
387
388 #[inline(always)]
390 pub fn offset_mut<V: ArrayLength, O: ArrayLength>(&mut self) -> &mut NumericArray<T, V>
391 where
392 N: Sub<O>,
393 Diff<N, O>: IsGreaterOrEqual<V, Output = True>,
394 {
395 unsafe { &mut *((self as *mut _ as *mut T).add(O::USIZE) as *mut NumericArray<T, V>) }
396 }
397}
398
399impl<'a, T, N: ArrayLength> From<&'a [T]> for &'a NumericArray<T, N> {
400 #[inline(always)]
404 fn from(slice: &[T]) -> &NumericArray<T, N> {
405 debug_assert_eq!(slice.len(), N::to_usize());
406
407 unsafe { &*(slice.as_ptr() as *const NumericArray<T, N>) }
408 }
409}
410
411impl<'a, T, N: ArrayLength> From<&'a mut [T]> for &'a mut NumericArray<T, N> {
412 #[inline(always)]
416 fn from(slice: &mut [T]) -> &mut NumericArray<T, N> {
417 debug_assert_eq!(slice.len(), N::to_usize());
418
419 unsafe { &mut *(slice.as_mut_ptr() as *mut NumericArray<T, N>) }
420 }
421}
422
423impl<T, N: ArrayLength> AsRef<[T]> for NumericArray<T, N> {
424 #[inline(always)]
425 fn as_ref(&self) -> &[T] {
426 self
427 }
428}
429
430impl<T, N: ArrayLength> Borrow<[T]> for NumericArray<T, N> {
431 #[inline(always)]
432 fn borrow(&self) -> &[T] {
433 self
434 }
435}
436
437impl<T, N: ArrayLength> AsMut<[T]> for NumericArray<T, N> {
438 #[inline(always)]
439 fn as_mut(&mut self) -> &mut [T] {
440 self
441 }
442}
443
444impl<T, N: ArrayLength> BorrowMut<[T]> for NumericArray<T, N> {
445 fn borrow_mut(&mut self) -> &mut [T] {
446 self
447 }
448}
449
450impl<T, N: ArrayLength> Index<usize> for NumericArray<T, N> {
451 type Output = T;
452
453 #[inline(always)]
454 fn index(&self, index: usize) -> &T {
455 self.0.index(index)
456 }
457}
458
459impl<T, N: ArrayLength> IndexMut<usize> for NumericArray<T, N> {
460 #[inline(always)]
461 fn index_mut(&mut self, index: usize) -> &mut T {
462 self.0.index_mut(index)
463 }
464}
465
466impl<T, N: ArrayLength> Index<Range<usize>> for NumericArray<T, N> {
467 type Output = [T];
468
469 #[inline(always)]
470 fn index(&self, index: Range<usize>) -> &[T] {
471 self.0.index(index)
472 }
473}
474
475impl<T, N: ArrayLength> IndexMut<Range<usize>> for NumericArray<T, N> {
476 #[inline(always)]
477 fn index_mut(&mut self, index: Range<usize>) -> &mut [T] {
478 self.0.index_mut(index)
479 }
480}
481
482impl<T, N: ArrayLength> Index<RangeTo<usize>> for NumericArray<T, N> {
483 type Output = [T];
484
485 #[inline(always)]
486 fn index(&self, index: RangeTo<usize>) -> &[T] {
487 self.0.index(index)
488 }
489}
490
491impl<T, N: ArrayLength> IndexMut<RangeTo<usize>> for NumericArray<T, N> {
492 #[inline(always)]
493 fn index_mut(&mut self, index: RangeTo<usize>) -> &mut [T] {
494 self.0.index_mut(index)
495 }
496}
497
498impl<T, N: ArrayLength> Index<RangeFrom<usize>> for NumericArray<T, N> {
499 type Output = [T];
500
501 #[inline(always)]
502 fn index(&self, index: RangeFrom<usize>) -> &[T] {
503 self.0.index(index)
504 }
505}
506
507impl<T, N: ArrayLength> IndexMut<RangeFrom<usize>> for NumericArray<T, N> {
508 #[inline(always)]
509 fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut [T] {
510 self.0.index_mut(index)
511 }
512}
513
514impl<T, N: ArrayLength> Index<RangeFull> for NumericArray<T, N> {
515 type Output = [T];
516
517 #[inline(always)]
518 fn index(&self, _index: RangeFull) -> &[T] {
519 self
520 }
521}
522
523impl<T, N: ArrayLength> IndexMut<RangeFull> for NumericArray<T, N> {
524 #[inline(always)]
525 fn index_mut(&mut self, _index: RangeFull) -> &mut [T] {
526 self
527 }
528}
529
530impl<'a, T, N: ArrayLength> IntoIterator for &'a NumericArray<T, N> {
531 type Item = &'a T;
532 type IntoIter = slice::Iter<'a, T>;
533
534 #[inline(always)]
535 fn into_iter(self) -> Self::IntoIter {
536 self.iter()
537 }
538}
539
540impl<'a, T, N: ArrayLength> IntoIterator for &'a mut NumericArray<T, N> {
541 type Item = &'a mut T;
542 type IntoIter = slice::IterMut<'a, T>;
543
544 #[inline(always)]
545 fn into_iter(self) -> Self::IntoIter {
546 self.iter_mut()
547 }
548}
549
550impl<T, N: ArrayLength> IntoIterator for NumericArray<T, N> {
551 type Item = T;
552 type IntoIter = GenericArrayIter<T, N>;
553
554 #[inline(always)]
555 fn into_iter(self) -> Self::IntoIter {
556 self.0.into_iter()
557 }
558}
559
560impl<T, N: ArrayLength> FromIterator<T> for NumericArray<T, N> {
561 #[inline(always)]
562 fn from_iter<I>(iter: I) -> Self
563 where
564 I: IntoIterator<Item = T>,
565 {
566 NumericArray(GenericArray::from_iter(iter))
567 }
568}
569
570impl<T, N: ArrayLength> Default for NumericArray<T, N>
571where
572 T: Default,
573{
574 #[inline(always)]
575 fn default() -> Self {
576 NumericArray(GenericArray::default())
577 }
578}
579
580#[cfg(test)]
581pub mod tests {
582 use num_traits::float::FloatCore;
583
584 #[inline(never)]
586 pub fn black_box<T>(val: T) -> T {
587 use core::{mem, ptr};
588
589 let ret = unsafe { ptr::read_volatile(&val) };
590 mem::forget(val);
591 ret
592 }
593
594 #[test]
595 fn test_ops() {
596 let a = black_box(narr![1, 3, 5, 7]);
597 let b = black_box(narr![2, 4, 6, 8]);
598
599 let c = a + b;
600 let d = c * nconstant!(black_box(5));
601 let e = d << nconstant!(1_usize);
602
603 assert_eq!(e, narr![30, 70, 110, 150])
604 }
605
606 #[test]
607 fn test_constants() {
608 let a = black_box(narr![1, 3, 5, 7]);
609 let b = black_box(narr![2, 4, 6, 8]);
610
611 let c = a + b * nconstant!(2);
612
613 assert_eq!(c, narr![5, 11, 17, 23]);
614 }
615
616 #[test]
617 fn test_floats() {
618 let a = black_box(narr![1.0f32, 3.0, 5.0, 7.0]);
619 let b = black_box(narr![2.0f32, 4.0, 6.0, 8.0]);
620
621 let c = a + b;
622
623 black_box(c);
624 }
625
626 #[test]
627 fn test_other() {
628 use num_traits::Saturating;
629
630 let a = black_box(narr![1, 3, 5, 7]);
631 let b = black_box(narr![2, 4, 6, 8]);
632
633 let c = a.saturating_add(b);
634
635 black_box(c);
636 }
637
638 #[cfg(feature = "std")]
639 #[test]
640 fn test_atan2() {
641 use num_traits::Float;
642
643 let a = black_box(narr![1.0f32, 2.0, 3.0, 4.0]);
644 let b = black_box(narr![2.0f32, 3.0, 4.0, 5.0]);
645
646 let c = a.atan2(b);
647
648 assert_eq!(c, narr![0.4636476, 0.5880026, 0.6435011, 0.67474097]);
649 }
650
651 #[test]
652 fn test_classify() {
653 use core::num::FpCategory;
654
655 let nan = f32::nan();
656 let infinity = f32::infinity();
657
658 let any_nan = black_box(narr![1.0, 2.0, nan, 0.0]);
659 let any_infinite = black_box(narr![1.0, infinity, 2.0, 3.0]);
660 let any_mixed = black_box(narr![1.0, infinity, nan, 0.0]);
661 let all_normal = black_box(narr![1.0, 2.0, 3.0, 4.0]);
662 let all_zero = black_box(narr![0.0, 0.0, 0.0, 0.0]);
663
664 let non_zero = black_box(narr![0.0f32, 1.0, 0.0, 0.0]);
665
666 assert_eq!(any_nan.classify(), FpCategory::Nan);
667 assert_eq!(any_mixed.classify(), FpCategory::Nan);
668 assert_eq!(any_infinite.classify(), FpCategory::Infinite);
669 assert_eq!(all_normal.classify(), FpCategory::Normal);
670 assert_eq!(all_zero.classify(), FpCategory::Zero);
671
672 assert_eq!(non_zero.classify(), FpCategory::Normal);
673
674 assert!(!any_nan.is_infinite());
675 assert!(any_mixed.is_infinite());
676 assert!(any_nan.is_nan());
677 assert!(any_mixed.is_nan());
678 assert!(!any_infinite.is_nan());
679 }
680
681 #[cfg(feature = "std")]
682 #[test]
683 fn test_tanh() {
684 use num_traits::Float;
685
686 let a = black_box(narr![1.0f32, 2.0, 3.0, 4.0]);
687
688 black_box(a.tanh());
689 }
690
691 #[cfg(feature = "std")]
692 #[test]
693 pub fn test_madd() {
694 use num_traits::Float;
695
696 let a = black_box(narr![1.0f32, 2.0, 3.0, 4.0]);
697 let b = black_box(narr![5.0f32, 6.0, 7.0, 8.0]);
698 let c = black_box(narr![9.0f32, 1.0, 2.0, 3.0]);
699
700 let d = a.mul_add(b, c);
701
702 assert_eq!(d, narr![14.0, 13.0, 23.0, 35.0]);
703 }
704
705 #[test]
706 #[no_mangle]
707 pub fn test_select() {
708 use crate::simd::Select;
709
710 let mask = black_box(narr![true, false, false, true]);
711
712 let a = black_box(narr![1, 2, 3, 4]);
713 let b = black_box(narr![5, 6, 7, 8]);
714
715 let selected = mask.select(a, b);
717
718 assert_eq!(selected, narr![1, 6, 7, 4]);
719 }
720}