ndarray/dimension/
conversion.rs

1// Copyright 2014-2016 bluss and ndarray developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Tuple to array conversion, IntoDimension, and related things
10
11use num_traits::Zero;
12use std::ops::{Index, IndexMut};
13use alloc::vec::Vec;
14
15use crate::{Dim, Dimension, Ix, Ix1, IxDyn, IxDynImpl};
16
17/// $m: macro callback
18/// $m is called with $arg and then the indices corresponding to the size argument
19macro_rules! index {
20    ($m:ident $arg:tt 0) => ($m!($arg));
21    ($m:ident $arg:tt 1) => ($m!($arg 0));
22    ($m:ident $arg:tt 2) => ($m!($arg 0 1));
23    ($m:ident $arg:tt 3) => ($m!($arg 0 1 2));
24    ($m:ident $arg:tt 4) => ($m!($arg 0 1 2 3));
25    ($m:ident $arg:tt 5) => ($m!($arg 0 1 2 3 4));
26    ($m:ident $arg:tt 6) => ($m!($arg 0 1 2 3 4 5));
27    ($m:ident $arg:tt 7) => ($m!($arg 0 1 2 3 4 5 6));
28}
29
30macro_rules! index_item {
31    ($m:ident $arg:tt 0) => ();
32    ($m:ident $arg:tt 1) => ($m!($arg 0););
33    ($m:ident $arg:tt 2) => ($m!($arg 0 1););
34    ($m:ident $arg:tt 3) => ($m!($arg 0 1 2););
35    ($m:ident $arg:tt 4) => ($m!($arg 0 1 2 3););
36    ($m:ident $arg:tt 5) => ($m!($arg 0 1 2 3 4););
37    ($m:ident $arg:tt 6) => ($m!($arg 0 1 2 3 4 5););
38    ($m:ident $arg:tt 7) => ($m!($arg 0 1 2 3 4 5 6););
39}
40
41/// Argument conversion a dimension.
42pub trait IntoDimension {
43    type Dim: Dimension;
44    fn into_dimension(self) -> Self::Dim;
45}
46
47impl IntoDimension for Ix {
48    type Dim = Ix1;
49    #[inline(always)]
50    fn into_dimension(self) -> Ix1 {
51        Ix1(self)
52    }
53}
54
55impl<D> IntoDimension for D
56where
57    D: Dimension,
58{
59    type Dim = D;
60    #[inline(always)]
61    fn into_dimension(self) -> Self {
62        self
63    }
64}
65
66impl IntoDimension for IxDynImpl {
67    type Dim = IxDyn;
68    #[inline(always)]
69    fn into_dimension(self) -> Self::Dim {
70        Dim::new(self)
71    }
72}
73
74impl IntoDimension for Vec<Ix> {
75    type Dim = IxDyn;
76    #[inline(always)]
77    fn into_dimension(self) -> Self::Dim {
78        Dim::new(IxDynImpl::from(self))
79    }
80}
81
82pub trait Convert {
83    type To;
84    fn convert(self) -> Self::To;
85}
86
87macro_rules! sub {
88    ($_x:tt $y:tt) => {
89        $y
90    };
91}
92
93macro_rules! tuple_type {
94    ([$T:ident] $($index:tt)*) => (
95        ( $(sub!($index $T), )* )
96    )
97}
98
99macro_rules! tuple_expr {
100    ([$self_:expr] $($index:tt)*) => (
101        ( $($self_[$index], )* )
102    )
103}
104
105macro_rules! array_expr {
106    ([$self_:expr] $($index:tt)*) => (
107        [$($self_ . $index, )*]
108    )
109}
110
111macro_rules! array_zero {
112    ([] $($index:tt)*) => (
113        [$(sub!($index 0), )*]
114    )
115}
116
117macro_rules! tuple_to_array {
118    ([] $($n:tt)*) => {
119        $(
120        impl Convert for [Ix; $n] {
121            type To = index!(tuple_type [Ix] $n);
122            #[inline]
123            fn convert(self) -> Self::To {
124                index!(tuple_expr [self] $n)
125            }
126        }
127
128        impl IntoDimension for [Ix; $n] {
129            type Dim = Dim<[Ix; $n]>;
130            #[inline(always)]
131            fn into_dimension(self) -> Self::Dim {
132                Dim::new(self)
133            }
134        }
135
136        impl IntoDimension for index!(tuple_type [Ix] $n) {
137            type Dim = Dim<[Ix; $n]>;
138            #[inline(always)]
139            fn into_dimension(self) -> Self::Dim {
140                Dim::new(index!(array_expr [self] $n))
141            }
142        }
143
144        impl Index<usize> for Dim<[Ix; $n]> {
145            type Output = usize;
146            #[inline(always)]
147            fn index(&self, index: usize) -> &Self::Output {
148                &self.ix()[index]
149            }
150        }
151
152        impl IndexMut<usize> for Dim<[Ix; $n]> {
153            #[inline(always)]
154            fn index_mut(&mut self, index: usize) -> &mut Self::Output {
155                &mut self.ixm()[index]
156            }
157        }
158
159        impl Zero for Dim<[Ix; $n]> {
160            #[inline]
161            fn zero() -> Self {
162                Dim::new(index!(array_zero [] $n))
163            }
164            fn is_zero(&self) -> bool {
165                self.slice().iter().all(|x| *x == 0)
166            }
167        }
168
169        )*
170    }
171}
172
173index_item!(tuple_to_array [] 7);