1#[macro_export]
2macro_rules! impl_from_f {
3 ($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
4 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> From<F> for $struct<T, F$($(, $dim)*)?>
5 where
6 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
8 {
9 #[inline]
10 fn from(float: F) -> Self {
11 Self::from_re(T::from(float))
12 }
13 }
14 };
15}
16
17#[macro_export]
18macro_rules! impl_zero_one {
19 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
20 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Zero for $struct<T, F$($(, $dim)*)?>
21 where
22 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
24 {
25 #[inline]
26 fn zero() -> Self {
27 Self::from_re(T::zero())
28 }
29
30 #[inline]
31 fn is_zero(&self) -> bool {
32 self.re.is_zero()
33 }
34 }
35
36 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> One for $struct<T, F$($(, $dim)*)?>
37 where
38 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
40 {
41 #[inline]
42 fn one() -> Self {
43 Self::from_re(T::one())
44 }
45
46 #[inline]
47 fn is_one(&self) -> bool {
48 self.re.is_one()
49 }
50 }
51 };
52}
53
54#[macro_export]
55macro_rules! impl_add_sub_rem {
56 ($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
57 impl<'a, 'b, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Add<&'a $struct<T, F$($(, $dim)*)?>>
58 for &'b $struct<T, F$($(, $dim)*)?>
59 where
60 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
62 {
63 type Output = $struct<T, F$($(, $dim)*)?>;
64 #[inline]
65 fn add(self, other: &$struct<T, F$($(, $dim)*)?>) -> $struct<T, F$($(, $dim)*)?> {
66 Self::Output::new(self.re.clone() + &other.re, $(self.$im.clone() + &other.$im,)*)
67 }
68 }
69
70 impl<'a, 'b, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Sub<&'a $struct<T, F$($(, $dim)*)?>>
71 for &'b $struct<T, F$($(, $dim)*)?>
72 where
73 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
75 {
76 type Output = $struct<T, F$($(, $dim)*)?>;
77 #[inline]
78 fn sub(self, other: &$struct<T, F$($(, $dim)*)?>) -> $struct<T, F$($(, $dim)*)?> {
79 Self::Output::new(self.re.clone() - &other.re, $(self.$im.clone() - &other.$im,)*)
80 }
81 }
82
83 impl<'a, 'b, T: DualNum<F>, F$($(, $dim: Dim)*)?> Rem<&'a $struct<T, F$($(, $dim)*)?>> for &'b $struct<T, F$($(, $dim)*)?>
84 where
85 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
87 {
88 type Output = $struct<T, F$($(, $dim)*)?>;
89 #[inline]
90 fn rem(self, _other: &$struct<T, F$($(, $dim)*)?>) -> $struct<T, F$($(, $dim)*)?> {
91 unimplemented!()
92 }
93 }
94 };
95}
96
97#[macro_export]
98macro_rules! forward_binop {
99 ($struct:ident, $trt:ident, $operator:tt, $mth:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
100 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> $trt<$struct<T, F$($(, $dim)*)?>> for &$struct<T, F$($(, $dim)*)?>
101 where
102 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
104 {
105 type Output = $struct<T, F$($(, $dim)*)?>;
106 #[inline]
107 fn $mth(self, rhs: $struct<T, F$($(, $dim)*)?>) -> Self::Output {
108 self $operator &rhs
109 }
110 }
111
112 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> $trt<&$struct<T, F$($(, $dim)*)?>> for $struct<T, F$($(, $dim)*)?>
113 where
114 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
116 {
117 type Output = $struct<T, F$($(, $dim)*)?>;
118 #[inline]
119 fn $mth(self, rhs: &$struct<T, F$($(, $dim)*)?>) -> Self::Output {
120 &self $operator rhs
121 }
122 }
123
124 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> $trt for $struct<T, F$($(, $dim)*)?>
125 where
126 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
128 {
129 type Output = $struct<T, F$($(, $dim)*)?>;
130 #[inline]
131 fn $mth(self, rhs: $struct<T, F$($(, $dim)*)?>) -> Self::Output {
132 &self $operator &rhs
133 }
134 }
135 };
136}
137
138#[macro_export]
139macro_rules! impl_neg {
140 ($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
141 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Neg for $struct<T, F$($(, $dim)*)?>
142 where
143 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
145 {
146 type Output = Self;
147 #[inline]
148 fn neg(self) -> Self {
149 -&self
150 }
151 }
152
153 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Neg for &$struct<T, F$($(, $dim)*)?>
154 where
155 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
157 {
158 type Output = $struct<T, F$($(, $dim)*)?>;
159 #[inline]
160 fn neg(self) -> Self::Output {
161 <$struct<T, F$($(, $dim)*)?>>::new(-self.re.clone(), $(-self.$im.clone()),*)
162 }
163 }
164 };
165}
166
167#[macro_export]
168macro_rules! impl_assign_ops {
169 ($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
170 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> MulAssign for $struct<T, F$($(, $dim)*)?>
171 where
172 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
174 {
175 #[inline]
176 fn mul_assign(&mut self, other: Self) {
177 *self = self.clone() * other;
178 }
179 }
180
181 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> DivAssign for $struct<T, F$($(, $dim)*)?>
182 where
183 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
185 {
186 #[inline]
187 fn div_assign(&mut self, other: Self) {
188 *self = self.clone() / other;
189 }
190 }
191
192 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> AddAssign for $struct<T, F$($(, $dim)*)?>
193 where
194 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
196 {
197 #[inline]
198 fn add_assign(&mut self, other: Self) {
199 self.re += other.re;
200 $(self.$im += other.$im;)*
201 }
202 }
203
204 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> SubAssign for $struct<T, F$($(, $dim)*)?>
205 where
206 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
208 {
209 #[inline]
210 fn sub_assign(&mut self, other: Self) {
211 self.re -= other.re;
212 $(self.$im -= other.$im;)*
213 }
214 }
215
216 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> RemAssign for $struct<T, F$($(, $dim)*)?>
217 where
218 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
220 {
221 #[inline]
222 fn rem_assign(&mut self, _other: Self) {
223 unimplemented!()
224 }
225 }
226 };
227}
228
229#[macro_export]
230macro_rules! impl_scalar_op {
231 ($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
232 impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Mul<F> for $struct<T, F$($(, $dim)*)?>
233 where
234 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
236 {
237 type Output = Self;
238 #[inline]
239 fn mul(mut self, other: F) -> Self {
240 self *= other;
241 self
242 }
243 }
244
245 impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> MulAssign<F> for $struct<T, F$($(, $dim)*)?>
246 where
247 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
249 {
250 #[inline]
251 fn mul_assign(&mut self, other: F) {
252 self.re *= other;
253 $(self.$im *= T::from(other);)*
254 }
255 }
256
257 impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Div<F> for $struct<T, F$($(, $dim)*)?>
258 where
259 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
261 {
262 type Output = Self;
263 #[inline]
264 fn div(mut self, other: F) -> Self {
265 self /= other;
266 self
267 }
268 }
269
270 impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> DivAssign<F> for $struct<T, F$($(, $dim)*)?>
271 where
272 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
274 {
275 #[inline]
276 fn div_assign(&mut self, other: F) {
277 self.re /= other;
278 $(self.$im /= T::from(other);)*
279 }
280 }
281
282 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> Add<F> for $struct<T, F$($(, $dim)*)?>
283 where
284 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
286 {
287 type Output = Self;
288 #[inline]
289 fn add(mut self, other: F) -> Self {
290 self.re += other;
291 self
292 }
293 }
294
295 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> AddAssign<F> for $struct<T, F$($(, $dim)*)?>
296 where
297 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
299 {
300 #[inline]
301 fn add_assign(&mut self, other: F) {
302 self.re += other;
303 }
304 }
305
306 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> Sub<F> for $struct<T, F$($(, $dim)*)?>
307 where
308 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
310 {
311 type Output = Self;
312 #[inline]
313 fn sub(mut self, other: F) -> Self {
314 self.re -= other;
315 self
316 }
317 }
318
319 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> SubAssign<F> for $struct<T, F$($(, $dim)*)?>
320 where
321 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
323 {
324 #[inline]
325 fn sub_assign(&mut self, other: F) {
326 self.re -= other;
327 }
328 }
329
330 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> Rem<F> for $struct<T, F$($(, $dim)*)?>
331 where
332 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
334 {
335 type Output = Self;
336 #[inline]
337 fn rem(self, _other: F) -> Self {
338 unimplemented!()
339 }
340 }
341
342 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> RemAssign<F> for $struct<T, F$($(, $dim)*)?>
343 where
344 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
346 {
347 #[inline]
348 fn rem_assign(&mut self, _other: F) {
349 unimplemented!()
350 }
351 }
352 };
353}
354
355#[macro_export]
356macro_rules! impl_inv {
357 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
358 impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Inv for $struct<T, F$($(, $dim)*)?>
359 where
360 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
362 {
363 type Output = Self;
364 #[inline]
365 fn inv(self) -> Self {
366 self.recip()
367 }
368 }
369 };
370}
371
372#[macro_export]
373macro_rules! impl_iterator {
374 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
375 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Sum for $struct<T, F$($(, $dim)*)?>
376 where
377 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
379 {
380 #[inline]
381 fn sum<I>(iter: I) -> Self
382 where
383 I: Iterator<Item = Self>,
384 {
385 iter.fold(Self::zero(), |acc, c| acc + c)
386 }
387 }
388
389 impl<'a, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Sum<&'a $struct<T, F$($(, $dim)*)?>>
390 for $struct<T, F$($(, $dim)*)?>
391 where
392 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
394 {
395 #[inline]
396 fn sum<I>(iter: I) -> Self
397 where
398 I: Iterator<Item = &'a $struct<T, F$($(, $dim)*)?>>,
399 {
400 iter.fold(Self::zero(), |acc, c| acc + c)
401 }
402 }
403 impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Product for $struct<T, F$($(, $dim)*)?>
404 where
405 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
407 {
408 #[inline]
409 fn product<I>(iter: I) -> Self
410 where
411 I: Iterator<Item = Self>,
412 {
413 iter.fold(Self::one(), |acc, c| acc * c)
414 }
415 }
416 impl<'a, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Product<&'a $struct<T, F$($(, $dim)*)?>>
417 for $struct<T, F$($(, $dim)*)?>
418 where
419 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
421 {
422 #[inline]
423 fn product<I>(iter: I) -> Self
424 where
425 I: Iterator<Item = &'a $struct<T, F$($(, $dim)*)?>>,
426 {
427 iter.fold(Self::one(), |acc, c| acc * c)
428 }
429 }
430 };
431}
432
433#[macro_export]
434macro_rules! impl_from_primitive {
435 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
436 impl<T: DualNum<F>, F: Float + FromPrimitive$($(, $dim: Dim)*)?> FromPrimitive for $struct<T, F$($(, $dim)*)?>
437 where
438 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
440 {
441 #[inline]
442 fn from_isize(n: isize) -> Option<Self> {
443 F::from_isize(n).map(|f| f.into())
444 }
445
446 #[inline]
447 fn from_i8(n: i8) -> Option<Self> {
448 F::from_i8(n).map(|f| f.into())
449 }
450
451 #[inline]
452 fn from_i16(n: i16) -> Option<Self> {
453 F::from_i16(n).map(|f| f.into())
454 }
455
456 #[inline]
457 fn from_i32(n: i32) -> Option<Self> {
458 F::from_i32(n).map(|f| f.into())
459 }
460
461 #[inline]
462 fn from_i64(n: i64) -> Option<Self> {
463 F::from_i64(n).map(|f| f.into())
464 }
465
466 #[inline]
467 fn from_i128(n: i128) -> Option<Self> {
468 F::from_i128(n).map(|f| f.into())
469 }
470
471 #[inline]
472 fn from_usize(n: usize) -> Option<Self> {
473 F::from_usize(n).map(|f| f.into())
474 }
475
476 #[inline]
477 fn from_u8(n: u8) -> Option<Self> {
478 F::from_u8(n).map(|f| f.into())
479 }
480
481 #[inline]
482 fn from_u16(n: u16) -> Option<Self> {
483 F::from_u16(n).map(|f| f.into())
484 }
485
486 #[inline]
487 fn from_u32(n: u32) -> Option<Self> {
488 F::from_u32(n).map(|f| f.into())
489 }
490
491 #[inline]
492 fn from_u64(n: u64) -> Option<Self> {
493 F::from_u64(n).map(|f| f.into())
494 }
495
496 #[inline]
497 fn from_u128(n: u128) -> Option<Self> {
498 F::from_u128(n).map(|f| f.into())
499 }
500
501 #[inline]
502 fn from_f32(n: f32) -> Option<Self> {
503 F::from_f32(n).map(|f| f.into())
504 }
505
506 #[inline]
507 fn from_f64(n: f64) -> Option<Self> {
508 F::from_f64(n).map(|f| f.into())
509 }
510 }
511 };
512}
513
514#[macro_export]
515macro_rules! impl_signed {
516 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
517 impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Signed for $struct<T, F$($(, $dim)*)?>
518 where
519 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
521 {
522 #[inline]
523 fn abs(&self) -> Self {
524 if self.is_positive() {
525 self.clone()
526 } else {
527 -self
528 }
529 }
530
531 #[inline]
532 fn abs_sub(&self, other: &Self) -> Self {
533 if self.re() > other.re() {
534 self - other
535 } else {
536 Self::zero()
537 }
538 }
539
540 #[inline]
541 fn signum(&self) -> Self {
542 if self.is_positive() {
543 Self::one()
544 } else if self.is_zero() {
545 Self::zero()
546 } else {
547 -Self::one()
548 }
549 }
550
551 #[inline]
552 fn is_positive(&self) -> bool {
553 self.re.is_positive()
554 }
555
556 #[inline]
557 fn is_negative(&self) -> bool {
558 self.re.is_negative()
559 }
560 }
561 };
562}
563
564#[macro_export]
565macro_rules! impl_float_const {
566 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
567 impl<T: DualNum<F>, F: Float + FloatConst$($(, $dim: Dim)*)?> FloatConst for $struct<T, F$($(, $dim)*)?>
568 where
569 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
571 {
572 fn E() -> Self {
573 Self::from(F::E())
574 }
575
576 fn FRAC_1_PI() -> Self {
577 Self::from(F::FRAC_1_PI())
578 }
579
580 fn FRAC_1_SQRT_2() -> Self {
581 Self::from(F::FRAC_1_SQRT_2())
582 }
583
584 fn FRAC_2_PI() -> Self {
585 Self::from(F::FRAC_2_PI())
586 }
587
588 fn FRAC_2_SQRT_PI() -> Self {
589 Self::from(F::FRAC_2_SQRT_PI())
590 }
591
592 fn FRAC_PI_2() -> Self {
593 Self::from(F::FRAC_PI_2())
594 }
595
596 fn FRAC_PI_3() -> Self {
597 Self::from(F::FRAC_PI_3())
598 }
599
600 fn FRAC_PI_4() -> Self {
601 Self::from(F::FRAC_PI_4())
602 }
603
604 fn FRAC_PI_6() -> Self {
605 Self::from(F::FRAC_PI_6())
606 }
607
608 fn FRAC_PI_8() -> Self {
609 Self::from(F::FRAC_PI_8())
610 }
611
612 fn LN_10() -> Self {
613 Self::from(F::LN_10())
614 }
615
616 fn LN_2() -> Self {
617 Self::from(F::LN_2())
618 }
619
620 fn LOG10_E() -> Self {
621 Self::from(F::LOG10_E())
622 }
623
624 fn LOG2_E() -> Self {
625 Self::from(F::LOG2_E())
626 }
627
628 fn PI() -> Self {
629 Self::from(F::PI())
630 }
631
632 fn SQRT_2() -> Self {
633 Self::from(F::SQRT_2())
634 }
635 }
636 };
637}
638
639#[macro_export]
640macro_rules! impl_num {
641 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
642 impl<T: DualNum<F> + Signed, F: Float$($(, $dim: Dim)*)?> Num for $struct<T, F$($(, $dim)*)?>
643 where
644 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
646 {
647 type FromStrRadixErr = F::FromStrRadixErr;
648 #[inline]
649 fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
650 unimplemented!()
651 }
652 }
653 };
654}
655
656#[macro_export]
657macro_rules! impl_dual_struct {
658 ($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
659 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> $crate::DualStruct<Self,F> for $struct<T, F$($(, $dim)*)?>
660 where
661 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
663 {
664 type Real = F;
665 type Inner = T;
666 #[inline]
667 fn re(&self) -> Self::Real {
668 self.re.re()
669 }
670 #[inline]
671 fn from_inner(inner: &Self::Inner) -> Self {
672 Self::from_re(inner.clone())
673 }
674 }
675
676 impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> $crate::Mappable<Self> for $struct<T, F$($(, $dim)*)?>
677 where
678 $($(DefaultAllocator: Allocator<$($ddim,)*>),*)?
680 {
681 type Output<O> = O;
682 #[inline]
683 fn map_dual<G: Fn(Self) -> O, O>(self, g: G) -> O {
684 g(self)
685 }
686 }
687 };
688}
689
690#[macro_export]
691macro_rules! impl_dual {
692 ($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])*)?) => {
693 impl_from_f!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])*)?);
694 impl_zero_one!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
695 impl_add_sub_rem!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])*)?);
696 forward_binop!($struct, Add, +, add$(, [$($dim),*]$(, [$($ddim),*])*)?);
697 forward_binop!($struct, Sub, -, sub$(, [$($dim),*]$(, [$($ddim),*])*)?);
698 forward_binop!($struct, Mul, *, mul$(, [$($dim),*]$(, [$($ddim),*])*)?);
699 forward_binop!($struct, Div, /, div$(, [$($dim),*]$(, [$($ddim),*])*)?);
700 forward_binop!($struct, Rem, %, rem$(, [$($dim),*]$(, [$($ddim),*])*)?);
701 impl_neg!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])*)?);
702 impl_assign_ops!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])*)?);
703 impl_scalar_op!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])*)?);
704 impl_inv!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
705 impl_iterator!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
706 impl_from_primitive!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
707 impl_signed!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
708 impl_num!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
709 impl_float_const!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
710 impl_dual_struct!($struct$(, [$($dim),*]$(, [$($ddim),*])*)?);
711 };
712}