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