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