1use std::fmt;
11use super::Dimension;
12use super::IntoDimension;
13use crate::itertools::zip;
14use crate::Ix;
15
16#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
39pub struct Dim<I: ?Sized> {
40 index: I,
41}
42
43impl<I> Dim<I> {
44 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#[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);