hexga_array/
macro_impl.rs

1
2// Fixed Binary Operator 
3#[macro_export]
4macro_rules! impl_fixed_array_like_op_binary
5{
6    ($name: ident, $dim : expr, $op_trait_name: ident, $op_trait_fn_name : ident) =>
7    {
8        impl_fixed_array_like_op_binary_composite!($name,$dim,$op_trait_name,$op_trait_fn_name);
9        impl_fixed_array_like_op_binary_non_composite!($name,$dim,$op_trait_name,$op_trait_fn_name);
10    }
11}
12
13#[macro_export]
14macro_rules! impl_fixed_array_like_op_binary_composite
15{
16    ($name: ident, $dim : expr, $op_trait_name: ident, $op_trait_fn_name : ident) =>
17    {
18        impl<T> $op_trait_name<Self> for $name<T> where T : $op_trait_name<T>
19        {
20            type Output=$name<<T as $op_trait_name<T>>::Output>;
21            fn $op_trait_fn_name(self, rhs: Self) -> Self::Output { self.map_with(rhs, T::$op_trait_fn_name) }
22        }
23    };
24}
25
26#[macro_export]
27macro_rules! impl_fixed_array_like_op_binary_non_composite
28{
29    ($name: ident, $dim : expr, $op_trait_name: ident, $op_trait_fn_name : ident) =>
30    {
31        // Currently binary op are closed (only work with the same type), they are not like
32        // impl<T,O> $op_trait_name<T> for $name<T> where T : $op_trait_name<O> + Copy
33        // because this cause conflict of implementation, especially in the case of matrix multiplication by 
34        // a scalar T, a Vector<T,N>, another Matrix with the good size
35        impl<T> $op_trait_name<T> for $name<T> where T : $op_trait_name<T> + Copy
36        {
37            type Output=$name<<T as $op_trait_name<T>>::Output>;
38            fn $op_trait_fn_name(self, rhs: T) -> Self::Output { <[T;$dim]>::from(self).map(|v| v.$op_trait_fn_name(rhs)).into() }
39        }
40    };
41}
42
43
44// Generic Binary Operator 
45#[macro_export]
46macro_rules! impl_generic_array_like_op_binary
47{
48    ($name: ident, $op_trait_name: ident, $op_trait_fn_name : ident) =>
49    {
50        impl_generic_array_like_op_binary_composite!($name,$op_trait_name,$op_trait_fn_name);
51        impl_generic_array_like_op_binary_non_composite!($name,$op_trait_name,$op_trait_fn_name);
52    }
53}
54
55#[macro_export]
56macro_rules! impl_generic_array_like_op_binary_composite
57{
58    ($name: ident, $op_trait_name: ident, $op_trait_fn_name : ident) =>
59    {
60        impl<T, const N : usize> $op_trait_name<Self> for $name<T, N> where T : $op_trait_name<T>
61        {
62            type Output=$name<<T as $op_trait_name<T>>::Output, N>;
63            fn $op_trait_fn_name(self, rhs: Self) -> Self::Output { self.map_with(rhs, T::$op_trait_fn_name) }
64        }
65    }
66}
67
68#[macro_export]
69macro_rules! impl_generic_array_like_op_binary_non_composite
70{
71    ($name: ident, $op_trait_name: ident, $op_trait_fn_name : ident) =>
72    {
73        impl<T, const N : usize> $op_trait_name<T> for $name<T,N> where T : $op_trait_name<T> + Copy
74        {
75            type Output=$name<<T as $op_trait_name<T>>::Output,N>;
76            fn $op_trait_fn_name(self, rhs: T) -> Self::Output { self.to_array().map(|v| v.$op_trait_fn_name(rhs)).into() }
77        }
78    }
79}
80
81
82#[macro_export]
83macro_rules! impl_fixed_array_like_op_assign
84{
85    ($name: ident, $dim : expr, $op_trait_name: ident, $op_trait_fn_name : ident) =>
86    {
87        impl<T> $op_trait_name<Self> for $name<T> where T : $op_trait_name
88        {
89            fn $op_trait_fn_name(&mut self, rhs: Self) 
90            {
91                let arr : [T; $dim] = rhs.into();
92                self.array_mut().iter_mut().zip(arr.into_iter()).for_each(|(a, b)| a.$op_trait_fn_name(b));
93            }
94        }
95    }
96}
97
98#[macro_export]
99macro_rules! impl_generic_array_like_op_assign
100{
101    ($name: ident, $op_trait_name: ident, $op_trait_fn_name : ident) =>
102    {
103        impl<T, const N : usize> $op_trait_name<Self> for $name<T,N> where T : $op_trait_name
104        {
105            fn $op_trait_fn_name(&mut self, rhs: Self) 
106            {
107                let arr : [T; N] = rhs.into();
108                self.array_mut().iter_mut().zip(arr.into_iter()).for_each(|(a, b)| a.$op_trait_fn_name(b));
109            }
110        }
111    }
112}
113
114#[macro_export]
115macro_rules! impl_fixed_array_like_op
116{
117    ($name: ident, $dim : expr) => 
118    {
119        impl_fixed_array_like_op_binary!($name, $dim, Add, add);
120        impl_fixed_array_like_op_assign!($name, $dim, AddAssign, add_assign);
121
122        impl_fixed_array_like_op_binary!($name, $dim, Sub, sub);
123        impl_fixed_array_like_op_assign!($name, $dim, SubAssign, sub_assign);
124
125        impl_fixed_array_like_op_binary!($name, $dim, Mul, mul);
126        impl_fixed_array_like_op_assign!($name, $dim, MulAssign, mul_assign);
127
128        impl_fixed_array_like_op_binary!($name, $dim, Div, div);
129        impl_fixed_array_like_op_assign!($name, $dim, DivAssign, div_assign);
130
131        impl_fixed_array_like_op_binary!($name, $dim, Rem, rem);
132        impl_fixed_array_like_op_assign!($name, $dim, RemAssign, rem_assign);
133
134        impl_fixed_array_like_op_binary!($name, $dim, BitAnd, bitand);
135        impl_fixed_array_like_op_assign!($name, $dim, BitAndAssign, bitand_assign);
136
137        impl_fixed_array_like_op_binary!($name, $dim, BitOr, bitor);
138        impl_fixed_array_like_op_assign!($name, $dim, BitOrAssign, bitor_assign);
139
140        impl_fixed_array_like_op_binary!($name, $dim, BitXor, bitxor);
141        impl_fixed_array_like_op_assign!($name, $dim, BitXorAssign, bitxor_assign);
142
143        impl_fixed_array_like_op_binary!($name, $dim, Shr, shr);
144        impl_fixed_array_like_op_assign!($name, $dim, ShrAssign, shr_assign);
145
146        impl_fixed_array_like_op_binary!($name, $dim, Shl, shl);
147        impl_fixed_array_like_op_assign!($name, $dim, ShlAssign, shl_assign);
148        
149        // ================= Unary =========
150
151        impl<T> ::std::ops::Not for $name<T> where T : Not
152        {
153            type Output = $name<T::Output>;
154            fn not(self) -> Self::Output { self.map(|v| v.not()) }
155        }
156
157        impl<T> ::std::ops::Neg for $name<T> where T : Neg
158        {
159            type Output = $name<T::Output>;
160            fn neg(self) -> Self::Output { self.map(|v| v.neg()) }
161        }
162
163        // ================= Iter =========
164
165        impl<T> ::std::iter::Sum for $name<T> where Self : Zero + Add<Self,Output = Self>
166        {
167            fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
168                iter.fold(Self::ZERO, Self::add)
169            }
170        }
171
172        impl<T> ::std::iter::Product for $name<T> where Self : One + Mul<Self,Output = Self>
173        {
174            fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
175                iter.fold(Self::ONE, Self::mul)
176            }
177        }
178
179        // ================= Display =========
180
181        impl_fixed_array_like_display!($name, Display);
182        impl_fixed_array_like_display!($name, Debug);
183        impl_fixed_array_like_display!($name, Octal);
184        impl_fixed_array_like_display!($name, Binary);
185        impl_fixed_array_like_display!($name, LowerHex);
186        impl_fixed_array_like_display!($name, UpperHex);
187        impl_fixed_array_like_display!($name, LowerExp);
188        impl_fixed_array_like_display!($name, UpperExp);
189        impl_fixed_array_like_display!($name, Pointer);
190    }
191}
192
193#[macro_export]
194macro_rules! impl_generic_array_like_display
195{
196    ($name: ident, $trait_name :ident) =>
197    {
198        impl<T, const N : usize> std::fmt::$trait_name  for $name<T,N> where T : std::fmt::$trait_name  
199        { 
200            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result 
201            {
202                write!(f, "(")?;
203                let mut it = self.array().iter().peekable();
204                while let Some(v) = it.next()
205                {
206                    v.fmt(f)?;
207                    if it.peek().is_some()
208                    {
209                        write!(f, ", ")?;
210                    }
211                }
212                write!(f, ")")
213            }
214        }
215    }
216}
217
218#[macro_export]
219macro_rules! impl_fixed_array_like_display
220{
221    ($name: ident, $trait_name :ident) =>
222    {
223        impl<T> std::fmt::$trait_name  for $name<T> where T : std::fmt::$trait_name  
224        { 
225            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result 
226            {
227                write!(f, "(")?;
228                let mut it = self.array().iter().peekable();
229                while let Some(v) = it.next()
230                {
231                    v.fmt(f)?;
232                    if it.peek().is_some()
233                    {
234                        write!(f, ", ")?;
235                    }
236                }
237                write!(f, ")")
238            }
239        }
240    }
241}
242
243#[macro_export]
244macro_rules! impl_generic_array_like_op
245{
246    ($name: ident) => 
247    {
248        impl_generic_array_like_op_binary!($name, Add, add);
249        impl_generic_array_like_op_assign!($name, AddAssign, add_assign);
250
251        impl_generic_array_like_op_binary!($name, Sub, sub);
252        impl_generic_array_like_op_assign!($name, SubAssign, sub_assign);
253
254        impl_generic_array_like_op_binary!($name, Mul, mul);
255        impl_generic_array_like_op_assign!($name, MulAssign, mul_assign);
256
257        impl_generic_array_like_op_binary!($name, Div, div);
258        impl_generic_array_like_op_assign!($name, DivAssign, div_assign);
259
260        impl_generic_array_like_op_binary!($name, Rem, rem);
261        impl_generic_array_like_op_assign!($name, RemAssign, rem_assign);
262
263        impl_generic_array_like_op_binary!($name, BitAnd, bitand);
264        impl_generic_array_like_op_assign!($name, BitAndAssign, bitand_assign);
265
266        impl_generic_array_like_op_binary!($name, BitOr, bitor);
267        impl_generic_array_like_op_assign!($name, BitOrAssign, bitor_assign);
268
269        impl_generic_array_like_op_binary!($name, BitXor, bitxor);
270        impl_generic_array_like_op_assign!($name, BitXorAssign, bitxor_assign);
271
272        impl_generic_array_like_op_binary!($name, Shr, shr);
273        impl_generic_array_like_op_assign!($name, ShrAssign, shr_assign);
274
275        impl_generic_array_like_op_binary!($name, Shl, shl);
276        impl_generic_array_like_op_assign!($name, ShlAssign, shl_assign);
277
278        // ================= Unary =========
279
280        impl<T, const N : usize> ::std::ops::Not for $name<T,N> where T : Not
281        {
282            type Output = $name<T::Output,N>;
283            fn not(self) -> Self::Output { self.map(|v| v.not()) }
284        }
285
286        impl<T, const N : usize> ::std::ops::Neg for $name<T,N> where T : Neg
287        {
288            type Output = $name<T::Output,N>;
289            fn neg(self) -> Self::Output { self.map(|v| v.neg()) }
290        }
291
292        // ================= Iter =========
293        
294        impl<T, const N : usize> ::std::iter::Sum for $name<T,N> where Self : ::hexga_number::Zero + ::std::ops::Add<Self,Output = Self>
295        {
296            fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
297                iter.fold(Self::ZERO, Self::add)
298            }
299        }
300
301        impl<T, const N : usize> ::std::iter::Product for $name<T,N> where Self : ::hexga_number::One + ::std::ops::Mul<Self,Output = Self>
302        {
303            fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
304                iter.fold(Self::ONE, Self::mul)
305            }
306        }
307
308        // ================= Display =========
309
310        impl_generic_array_like_display!($name, Display);
311        impl_generic_array_like_display!($name, Debug);
312        impl_generic_array_like_display!($name, Octal);
313        impl_generic_array_like_display!($name, Binary);
314        impl_generic_array_like_display!($name, LowerHex);
315        impl_generic_array_like_display!($name, UpperHex);
316        impl_generic_array_like_display!($name, LowerExp);
317        impl_generic_array_like_display!($name, UpperExp);
318        impl_generic_array_like_display!($name, Pointer);
319    }
320}
321
322#[macro_export]
323macro_rules! impl_fixed_array_like
324{
325    ($name: ident, $dim : expr) => 
326    { 
327        impl<T> ::std::marker::Copy  for $name<T> where T : Copy {}
328        impl<T> ::std::clone::Clone for $name<T> where T : Clone
329        {
330            fn clone(&self) -> Self { self.array().clone().into() }
331        }
332
333        impl<T> ::std::cmp::PartialEq for $name<T> where T : PartialEq
334        {
335            fn eq(&self, rhs : &Self) -> bool { self.array() == rhs.array() }
336        }
337        impl<T> ::std::cmp::Eq for $name<T> where T : Eq {}
338
339        impl<T> ::std::convert::From<T> for $name<T> where T : Copy { fn from(value: T) -> Self { Self::from([value; $dim]) } }
340    
341        impl<T> ::std::convert::From<[T; $dim]> for $name<T> { fn from(value: [T; $dim]) -> Self { unsafe { std::mem::transmute_copy(&value) } } }
342        impl<T> ::std::convert::From<$name<T>> for [T; $dim] { fn from(value: $name<T>) -> Self { unsafe { std::mem::transmute_copy(&value) } } }
343
344        impl<T> ::std::convert::AsRef<[T; $dim]> for $name<T> { fn as_ref(&self) -> &[T; $dim] { unsafe { std::mem::transmute(self) } } }
345        impl<T> ::std::convert::AsMut<[T; $dim]> for $name<T> { fn as_mut(&mut self) -> &mut [T; $dim] { unsafe { std::mem::transmute(self) } } }
346
347        impl<T> $crate::ArrayLike<T, $dim> for $name<T>
348        {
349            type WithType<T2>=$name<T2>;
350
351            fn array(&self) -> &[T; $dim] { unsafe { std::mem::transmute(self) } }
352            fn array_mut(&mut self) -> &mut[T; $dim] { unsafe { std::mem::transmute(self) } }
353        }
354
355        impl<T> ::std::ops::Index   <usize> for $name<T> { type Output=T; fn index(&self, index: usize) -> &Self::Output { self.array().index(index) } }
356        impl<T> ::std::ops::IndexMut<usize> for $name<T> { fn index_mut(&mut self, index: usize) -> &mut Self::Output { self.array_mut().index_mut(index) } }
357    
358        impl<T> ::std::iter::IntoIterator for $name<T> where [T;$dim] : ::std::iter::IntoIterator
359        {
360            type Item = <[T;$dim] as ::std::iter::IntoIterator>::Item;
361            type IntoIter = <[T;$dim] as ::std::iter::IntoIterator>::IntoIter;
362        
363            fn into_iter(self) -> Self::IntoIter 
364            {
365                self.to_array().into_iter()
366            }
367        }
368        
369        impl<'a, T> ::std::iter::IntoIterator for &'a $name<T> where &'a [T;$dim] : ::std::iter::IntoIterator
370        {
371            type Item = <&'a [T;$dim] as ::std::iter::IntoIterator>::Item;
372            type IntoIter = <&'a [T;$dim] as ::std::iter::IntoIterator>::IntoIter;
373        
374            fn into_iter(self) -> Self::IntoIter {
375                self.as_array().into_iter()
376            }
377        }
378        
379        impl<'a, T> ::std::iter::IntoIterator for &'a mut $name<T> where &'a mut [T;$dim] : ::std::iter::IntoIterator
380        {
381            type Item = <&'a mut [T;$dim] as IntoIterator>::Item;
382            type IntoIter = <&'a mut [T;$dim] as IntoIterator>::IntoIter;
383        
384            fn into_iter(self) -> Self::IntoIter {
385                self.as_array_mut().into_iter()
386            }
387        }
388
389        #[cfg(feature = "serde")]
390        impl<T> ::serde::Serialize for $name<T> where [T;$dim] : ::serde::Serialize
391        {
392            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer,
393            { self.as_array().serialize(serializer) }
394        }
395
396        #[cfg(feature = "serde")]
397        impl<'de, T> ::serde::Deserialize<'de> for $name<T> where [T;$dim] : ::serde::Deserialize<'de>{
398            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: ::serde::Deserializer<'de>,
399            {
400                Ok(<[T;$dim]>::deserialize(deserializer)?.into())
401            }
402        }
403    };
404}
405
406
407
408#[macro_export]
409macro_rules! impl_fixed_array_like_with_op
410{
411    ($name: ident, $dim : expr) => 
412    { 
413        impl_fixed_array_like_op!($name, $dim);
414        impl_fixed_array_like!($name, $dim);
415    };
416}
417
418
419
420#[macro_export]
421macro_rules! impl_generic_array_like
422{
423    ($name: ident) => 
424    { 
425        impl<T, const N : usize> ::std::marker::Copy  for $name<T,N> where T : Copy  {}
426        impl<T, const N : usize> ::std::clone::Clone for $name<T,N> where T : Clone
427        {
428            fn clone(&self) -> Self { self.array().clone().into() }
429        }
430
431        impl<T, const N : usize> ::std::cmp::PartialEq for $name<T,N> where T : PartialEq
432        {
433            fn eq(&self, rhs : &Self) -> bool { self.array() == rhs.array() }
434        }
435        impl<T, const N : usize> ::std::cmp::Eq for $name<T,N> where T : Eq{}
436
437        impl<T, const N : usize> ::std::convert::From<T> for $name<T,N> where T : Copy { fn from(value: T) -> Self { Self::from([value; N]) } }
438
439        impl<T, const N : usize> ::std::convert::From<[T; N]> for $name<T,N> { fn from(value: [T; N]) -> Self { unsafe { std::mem::transmute_copy(&value) } } }
440        impl<T, const N : usize> ::std::convert::From<$name<T,N>> for [T; N] { fn from(value: $name<T,N>) -> Self { unsafe { std::mem::transmute_copy(&value) } } }
441
442        impl<T, const N : usize> ::std::convert::AsRef<[T; N]> for $name<T,N> { fn as_ref(&self) -> &[T; N] { unsafe { std::mem::transmute(self) } } }
443        impl<T, const N : usize> ::std::convert::AsMut<[T; N]> for $name<T,N> { fn as_mut(&mut self) -> &mut [T; N] { unsafe { std::mem::transmute(self) } } }
444
445        impl<T, const N : usize> $crate::ArrayLike<T, N> for $name<T,N>
446        {
447            type WithType<T2>=$name<T2,N>;
448
449            fn array(&self) -> &[T; N] { unsafe { std::mem::transmute(self) } }
450            fn array_mut(&mut self) -> &mut[T; N] { unsafe { std::mem::transmute(self) } }
451        }
452
453        impl<T, const N : usize> ::std::ops::Index   <usize> for $name<T,N> { type Output=T; fn index(&self, index: usize) -> &Self::Output { self.array().index(index) } }
454        impl<T, const N : usize> ::std::ops::IndexMut<usize> for $name<T,N> { fn index_mut(&mut self, index: usize) -> &mut Self::Output { self.array_mut().index_mut(index) } }
455    
456        impl<T, const N : usize> ::std::iter::IntoIterator for $name<T,N> where [T;N] : ::std::iter::IntoIterator
457        {
458            type Item = <[T;N] as ::std::iter::IntoIterator>::Item;
459            type IntoIter = <[T;N] as ::std::iter::IntoIterator>::IntoIter;
460        
461            fn into_iter(self) -> Self::IntoIter 
462            {
463                self.to_array().into_iter()
464            }
465        }
466        
467        impl<'a, T, const N : usize> ::std::iter::IntoIterator for &'a $name<T,N> where &'a [T;N] : ::std::iter::IntoIterator
468        {
469            type Item = <&'a [T;N] as ::std::iter::IntoIterator>::Item;
470            type IntoIter = <&'a [T;N] as ::std::iter::IntoIterator>::IntoIter;
471        
472            fn into_iter(self) -> Self::IntoIter {
473                self.as_array().into_iter()
474            }
475        }
476        
477        impl<'a, T, const N : usize> ::std::iter::IntoIterator for &'a mut $name<T,N> where &'a mut [T;N] : ::std::iter::IntoIterator
478        {
479            type Item = <&'a mut [T;N] as IntoIterator>::Item;
480            type IntoIter = <&'a mut [T;N] as IntoIterator>::IntoIter;
481        
482            fn into_iter(self) -> Self::IntoIter {
483                self.as_array_mut().into_iter()
484            }
485        }
486
487        #[cfg(feature = "serde")]
488        impl<T, const N : usize> ::serde::Serialize for $name<T,N> where [T;N] : ::serde::Serialize
489        {
490            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer,
491            { self.as_array().serialize(serializer) }
492        }
493
494        #[cfg(feature = "serde")]
495        impl<'de, T, const N : usize> ::serde::Deserialize<'de> for $name<T,N> where [T;N] : ::serde::Deserialize<'de>{
496            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: ::serde::Deserializer<'de>,
497            {
498                Ok(<[T;N]>::deserialize(deserializer)?.into())
499            }
500        }
501    };
502}
503
504#[macro_export]
505macro_rules! impl_generic_array_like_with_op
506{
507    ($name: ident) => 
508    { 
509        impl_generic_array_like_op!($name);
510        impl_generic_array_like!($name);
511    };
512}