ndarray/dimension/
dim.rs

1// Copyright 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
10use std::fmt;
11use super::Dimension;
12use super::IntoDimension;
13use crate::itertools::zip;
14use crate::Ix;
15
16/// Dimension description.
17///
18/// `Dim` describes the number of axes and the length of each axis
19/// in an array. It is also used as an index type.
20///
21/// See also the [`Dimension`] trait for its methods and
22/// operations.
23///
24/// # Examples
25///
26/// To create an array with a particular dimension, you'd just pass
27/// a tuple (in this example (3, 2) is used), which is converted to
28/// `Dim` by the array constructor.
29///
30/// ```
31/// use ndarray::Array2;
32/// use ndarray::Dim;
33///
34/// let mut array = Array2::zeros((3, 2));
35/// array[[0, 0]] = 1.;
36/// assert_eq!(array.raw_dim(), Dim([3, 2]));
37/// ```
38#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
39pub struct Dim<I: ?Sized> {
40    index: I,
41}
42
43impl<I> Dim<I> {
44    /// Private constructor and accessors for Dim
45    pub(crate) fn new(index: I) -> Dim<I> {
46        Dim { index }
47    }
48    #[inline(always)]
49    pub(crate) fn ix(&self) -> &I {
50        &self.index
51    }
52    #[inline(always)]
53    pub(crate) fn ixm(&mut self) -> &mut I {
54        &mut self.index
55    }
56}
57
58/// Create a new dimension value.
59#[allow(non_snake_case)]
60pub fn Dim<T>(index: T) -> T::Dim
61where
62    T: IntoDimension,
63{
64    index.into_dimension()
65}
66
67impl<I: ?Sized> PartialEq<I> for Dim<I>
68where
69    I: PartialEq,
70{
71    fn eq(&self, rhs: &I) -> bool {
72        self.index == *rhs
73    }
74}
75
76impl<I> fmt::Debug for Dim<I>
77where
78    I: fmt::Debug,
79{
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        write!(f, "{:?}", self.index)
82    }
83}
84
85use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
86
87macro_rules! impl_op {
88    ($op:ident, $op_m:ident, $opassign:ident, $opassign_m:ident, $expr:ident) => {
89        impl<I> $op for Dim<I>
90        where
91            Dim<I>: Dimension,
92        {
93            type Output = Self;
94            fn $op_m(mut self, rhs: Self) -> Self {
95                $expr!(self, &rhs);
96                self
97            }
98        }
99
100        impl<I> $opassign for Dim<I>
101        where
102            Dim<I>: Dimension,
103        {
104            fn $opassign_m(&mut self, rhs: Self) {
105                $expr!(*self, &rhs);
106            }
107        }
108
109        impl<'a, I> $opassign<&'a Dim<I>> for Dim<I>
110        where
111            Dim<I>: Dimension,
112        {
113            fn $opassign_m(&mut self, rhs: &Self) {
114                for (x, &y) in zip(self.slice_mut(), rhs.slice()) {
115                    $expr!(*x, y);
116                }
117            }
118        }
119    };
120}
121
122macro_rules! impl_single_op {
123    ($op:ident, $op_m:ident, $opassign:ident, $opassign_m:ident, $expr:ident) => {
124        impl $op<Ix> for Dim<[Ix; 1]> {
125            type Output = Self;
126            #[inline]
127            fn $op_m(mut self, rhs: Ix) -> Self {
128                $expr!(self, rhs);
129                self
130            }
131        }
132
133        impl $opassign<Ix> for Dim<[Ix; 1]> {
134            #[inline]
135            fn $opassign_m(&mut self, rhs: Ix) {
136                $expr!((*self)[0], rhs);
137            }
138        }
139    };
140}
141
142macro_rules! impl_scalar_op {
143    ($op:ident, $op_m:ident, $opassign:ident, $opassign_m:ident, $expr:ident) => {
144        impl<I> $op<Ix> for Dim<I>
145        where
146            Dim<I>: Dimension,
147        {
148            type Output = Self;
149            fn $op_m(mut self, rhs: Ix) -> Self {
150                $expr!(self, rhs);
151                self
152            }
153        }
154
155        impl<I> $opassign<Ix> for Dim<I>
156        where
157            Dim<I>: Dimension,
158        {
159            fn $opassign_m(&mut self, rhs: Ix) {
160                for x in self.slice_mut() {
161                    $expr!(*x, rhs);
162                }
163            }
164        }
165    };
166}
167
168macro_rules! add {
169    ($x:expr, $y:expr) => {
170        $x += $y;
171    };
172}
173macro_rules! sub {
174    ($x:expr, $y:expr) => {
175        $x -= $y;
176    };
177}
178macro_rules! mul {
179    ($x:expr, $y:expr) => {
180        $x *= $y;
181    };
182}
183impl_op!(Add, add, AddAssign, add_assign, add);
184impl_single_op!(Add, add, AddAssign, add_assign, add);
185impl_op!(Sub, sub, SubAssign, sub_assign, sub);
186impl_single_op!(Sub, sub, SubAssign, sub_assign, sub);
187impl_op!(Mul, mul, MulAssign, mul_assign, mul);
188impl_scalar_op!(Mul, mul, MulAssign, mul_assign, mul);