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