easy_ml/differentiation/
trace_operations.rs

1#![allow(clippy::double_parens)]
2/*!
3* Operator implementations for Traces
4*
5* These implementations are written here but Rust docs will display them on the
6* [Trace] struct page.
7*
8* Traces of any Numeric type (provided the type also implements the operations by reference
9* as described in the [numeric](super::super::numeric) module) implement all the standard
10* library traits for addition, subtraction, multiplication and division, so you can
11* use the normal `+ - * /` operators as you can with normal number types. As a convenience,
12* these operations can also be used with a Trace on the left hand side and a the same type
13* that the Trace is generic over on the right hand side, so you can do
14*
15* ```
16* use easy_ml::differentiation::Trace;
17* let x: Trace<f32> = Trace::variable(2.0);
18* let y: f32 = 2.0;
19* let z: Trace<f32> = x * y;
20* assert_eq!(z.number, 4.0);
21* ```
22*
23* or more succinctly
24*
25* ```
26* use easy_ml::differentiation::Trace;
27* assert_eq!((Trace::variable(2.0) * 2.0).number, 4.0);
28* ```
29*
30* Traces of a [Real] type (provided the type also implements the operations by reference as
31* described in the [numeric](super::super::numeric::extra) module) also implement
32* all of those extra traits and operations. Note that to use a method defined in a trait
33* you have to import the trait as well as have a type that implements it!
34*/
35
36use crate::differentiation::{Primitive, Trace};
37use crate::numeric::extra::{Cos, Exp, Ln, Pi, Pow, Real, RealRef, Sin, Sqrt};
38use crate::numeric::{FromUsize, Numeric, NumericRef, ZeroOne};
39use std::cmp::Ordering;
40use std::iter::Sum;
41use std::ops::{Add, Div, Mul, Neg, Sub};
42
43/**
44 * A trace is displayed by showing its number component.
45 */
46impl<T: std::fmt::Display + Primitive> std::fmt::Display for Trace<T> {
47    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
48        write!(f, "{}", self.number)
49    }
50}
51
52/**
53 * Trace implements ZeroOne by returning constants.
54 */
55impl<T: Numeric + Primitive> ZeroOne for Trace<T> {
56    #[inline]
57    fn zero() -> Trace<T> {
58        Trace::constant(T::zero())
59    }
60    #[inline]
61    fn one() -> Trace<T> {
62        Trace::constant(T::one())
63    }
64}
65
66impl<T: Numeric + Primitive> FromUsize for Trace<T> {
67    #[inline]
68    fn from_usize(n: usize) -> Option<Trace<T>> {
69        Some(Trace::constant(T::from_usize(n)?))
70    }
71}
72
73/**
74 * Any trace of a Cloneable type implements clone
75 */
76impl<T: Clone + Primitive> Clone for Trace<T> {
77    #[inline]
78    fn clone(&self) -> Self {
79        Trace {
80            number: self.number.clone(),
81            derivative: self.derivative.clone(),
82        }
83    }
84}
85
86/**
87 * Any trace of a Copy type implements Copy
88 */
89impl<T: Copy + Primitive> Copy for Trace<T> {}
90
91/**
92 * Any trace of a PartialEq type implements PartialEq
93 *
94 * Note that as a Trace is intended to be substitutable with its
95 * type T only the number parts of the trace are compared.
96 * Hence the following is true
97 * ```
98 * use easy_ml::differentiation::Trace;
99 * assert_eq!(Trace { number: 0, derivative: 1 }, Trace { number: 0, derivative: 2 })
100 * ```
101 */
102impl<T: PartialEq + Primitive> PartialEq for Trace<T> {
103    #[inline]
104    fn eq(&self, other: &Self) -> bool {
105        self.number == other.number
106    }
107}
108
109/**
110 * Any trace of a PartialOrd type implements PartialOrd
111 *
112 * Note that as a Trace is intended to be substitutable with its
113 * type T only the number parts of the trace are compared.
114 * Hence the following is true
115 * ```
116 * use easy_ml::differentiation::Trace;
117 * assert!(Trace { number: 1, derivative: 1 } > Trace { number: 0, derivative: 2 })
118 * ```
119 */
120impl<T: PartialOrd + Primitive> PartialOrd for Trace<T> {
121    #[inline]
122    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
123        self.number.partial_cmp(&other.number)
124    }
125}
126
127/**
128 * Any trace of a Numeric type implements Sum, which is
129 * the same as adding a bunch of Trace types together.
130 */
131impl<T: Numeric + Primitive> Sum for Trace<T> {
132    #[inline]
133    fn sum<I>(mut iter: I) -> Trace<T>
134    where
135        I: Iterator<Item = Trace<T>>,
136    {
137        let mut total = Trace::<T>::zero();
138        loop {
139            match iter.next() {
140                None => return total,
141                Some(next) => {
142                    total = Trace {
143                        number: total.number + next.number,
144                        derivative: total.derivative + next.derivative,
145                    }
146                }
147            }
148        }
149    }
150}
151
152/**
153 * Addition for two traces of the same type with both referenced.
154 */
155impl<'l, 'r, T: Numeric + Primitive> Add<&'r Trace<T>> for &'l Trace<T>
156where
157    for<'a> &'a T: NumericRef<T>,
158{
159    type Output = Trace<T>;
160    #[inline]
161    fn add(self, rhs: &Trace<T>) -> Self::Output {
162        Trace {
163            number: self.number.clone() + rhs.number.clone(),
164            derivative: self.derivative.clone() + rhs.derivative.clone(),
165        }
166    }
167}
168
169macro_rules! operator_impl_value_value {
170    (impl $op:tt for Trace { fn $method:ident }) => {
171        /**
172         * Operation for two traces of the same type.
173         */
174        impl<T: Numeric + Primitive> $op for Trace<T>
175        where
176            for<'a> &'a T: NumericRef<T>,
177        {
178            type Output = Trace<T>;
179            #[inline]
180            fn $method(self, rhs: Trace<T>) -> Self::Output {
181                (&self).$method(&rhs)
182            }
183        }
184    };
185}
186
187macro_rules! operator_impl_value_reference {
188    (impl $op:tt for Trace { fn $method:ident }) => {
189        /**
190         * Operation for two traces of the same type with the right referenced.
191         */
192        impl<T: Numeric + Primitive> $op<&Trace<T>> for Trace<T>
193        where
194            for<'a> &'a T: NumericRef<T>,
195        {
196            type Output = Trace<T>;
197            #[inline]
198            fn $method(self, rhs: &Trace<T>) -> Self::Output {
199                (&self).$method(rhs)
200            }
201        }
202    };
203}
204
205macro_rules! operator_impl_reference_value {
206    (impl $op:tt for Trace { fn $method:ident }) => {
207        /**
208         * Operation for two traces of the same type with the left referenced.
209         */
210        impl<T: Numeric + Primitive> $op<Trace<T>> for &Trace<T>
211        where
212            for<'a> &'a T: NumericRef<T>,
213        {
214            type Output = Trace<T>;
215            #[inline]
216            fn $method(self, rhs: Trace<T>) -> Self::Output {
217                self.$method(&rhs)
218            }
219        }
220    };
221}
222
223operator_impl_value_value!(impl Add for Trace { fn add });
224operator_impl_reference_value!(impl Add for Trace { fn add });
225operator_impl_value_reference!(impl Add for Trace { fn add });
226
227/**
228 * Addition for a trace and a constant of the same type with both referenced.
229 */
230impl<T: Numeric + Primitive> Add<&T> for &Trace<T>
231where
232    for<'a> &'a T: NumericRef<T>,
233{
234    type Output = Trace<T>;
235    #[inline]
236    fn add(self, rhs: &T) -> Self::Output {
237        Trace {
238            number: self.number.clone() + rhs.clone(),
239            derivative: self.derivative.clone(),
240        }
241    }
242}
243
244macro_rules! trace_number_operator_impl_value_value {
245    (impl $op:tt for Trace { fn $method:ident }) => {
246        /**
247         * Operation for a trace and a constant of the same type.
248         */
249        impl<T: Numeric + Primitive> $op<T> for Trace<T>
250        where
251            for<'a> &'a T: NumericRef<T>,
252        {
253            type Output = Trace<T>;
254            #[inline]
255            fn $method(self, rhs: T) -> Self::Output {
256                (&self).$method(&rhs)
257            }
258        }
259    };
260}
261
262macro_rules! trace_number_operator_impl_value_reference {
263    (impl $op:tt for Trace { fn $method:ident }) => {
264        /**
265         * Operation for a trace and a constant of the same type with the right referenced.
266         */
267        impl<T: Numeric + Primitive> $op<&T> for Trace<T>
268        where
269            for<'a> &'a T: NumericRef<T>,
270        {
271            type Output = Trace<T>;
272            #[inline]
273            fn $method(self, rhs: &T) -> Self::Output {
274                (&self).$method(rhs)
275            }
276        }
277    };
278}
279
280macro_rules! trace_number_operator_impl_reference_value {
281    (impl $op:tt for Trace { fn $method:ident }) => {
282        /**
283         * Operation for a trace and a constant of the same type with the left referenced.
284         */
285        impl<T: Numeric + Primitive> $op<T> for &Trace<T>
286        where
287            for<'a> &'a T: NumericRef<T>,
288        {
289            type Output = Trace<T>;
290            #[inline]
291            fn $method(self, rhs: T) -> Self::Output {
292                self.$method(&rhs)
293            }
294        }
295    };
296}
297
298trace_number_operator_impl_value_value!(impl Add for Trace { fn add });
299trace_number_operator_impl_reference_value!(impl Add for Trace { fn add });
300trace_number_operator_impl_value_reference!(impl Add for Trace { fn add });
301
302/**
303 * Multiplication for two referenced traces of the same type.
304 */
305impl<'l, 'r, T: Numeric + Primitive> Mul<&'r Trace<T>> for &'l Trace<T>
306where
307    for<'a> &'a T: NumericRef<T>,
308{
309    type Output = Trace<T>;
310    #[inline]
311    fn mul(self, rhs: &Trace<T>) -> Self::Output {
312        Trace {
313            number: self.number.clone() * rhs.number.clone(),
314            // u'v + uv'
315            derivative: (self.derivative.clone() * rhs.number.clone())
316                + (self.number.clone() * rhs.derivative.clone()),
317        }
318    }
319}
320
321operator_impl_value_value!(impl Mul for Trace { fn mul });
322operator_impl_reference_value!(impl Mul for Trace { fn mul });
323operator_impl_value_reference!(impl Mul for Trace { fn mul });
324
325/**
326 * Multiplication for a trace and a constant of the same type with both referenced.
327 */
328impl<T: Numeric + Primitive> Mul<&T> for &Trace<T>
329where
330    for<'a> &'a T: NumericRef<T>,
331{
332    type Output = Trace<T>;
333    #[inline]
334    fn mul(self, rhs: &T) -> Self::Output {
335        Trace {
336            number: self.number.clone() * rhs.clone(),
337            derivative: self.derivative.clone() * rhs.clone(),
338        }
339    }
340}
341
342trace_number_operator_impl_value_value!(impl Mul for Trace { fn mul });
343trace_number_operator_impl_reference_value!(impl Mul for Trace { fn mul });
344trace_number_operator_impl_value_reference!(impl Mul for Trace { fn mul });
345
346/**
347 * Subtraction for two referenced traces of the same type.
348 */
349impl<'l, 'r, T: Numeric + Primitive> Sub<&'r Trace<T>> for &'l Trace<T>
350where
351    for<'a> &'a T: NumericRef<T>,
352{
353    type Output = Trace<T>;
354    #[inline]
355    fn sub(self, rhs: &Trace<T>) -> Self::Output {
356        Trace {
357            number: self.number.clone() - rhs.number.clone(),
358            derivative: self.derivative.clone() - rhs.derivative.clone(),
359        }
360    }
361}
362
363operator_impl_value_value!(impl Sub for Trace { fn sub });
364operator_impl_reference_value!(impl Sub for Trace { fn sub });
365operator_impl_value_reference!(impl Sub for Trace { fn sub });
366
367/**
368 * Subtraction for a trace and a constant of the same type with both referenced.
369 */
370impl<T: Numeric + Primitive> Sub<&T> for &Trace<T>
371where
372    for<'a> &'a T: NumericRef<T>,
373{
374    type Output = Trace<T>;
375    #[inline]
376    fn sub(self, rhs: &T) -> Self::Output {
377        Trace {
378            number: self.number.clone() - rhs.clone(),
379            derivative: self.derivative.clone(),
380        }
381    }
382}
383
384trace_number_operator_impl_value_value!(impl Sub for Trace { fn sub });
385trace_number_operator_impl_reference_value!(impl Sub for Trace { fn sub });
386trace_number_operator_impl_value_reference!(impl Sub for Trace { fn sub });
387
388/**
389 * Division for two referenced traces of the same type.
390 */
391impl<'l, 'r, T: Numeric + Primitive> Div<&'r Trace<T>> for &'l Trace<T>
392where
393    for<'a> &'a T: NumericRef<T>,
394{
395    type Output = Trace<T>;
396    #[inline]
397    fn div(self, rhs: &Trace<T>) -> Self::Output {
398        Trace {
399            number: self.number.clone() / rhs.number.clone(),
400            // (u'v - uv') / v^2
401            #[rustfmt::skip]
402            derivative: (
403                ((self.derivative.clone() * rhs.number.clone())
404                - (self.number.clone() * rhs.derivative.clone()))
405                / (rhs.number.clone() * rhs.number.clone())
406            ),
407        }
408    }
409}
410
411operator_impl_value_value!(impl Div for Trace { fn div });
412operator_impl_reference_value!(impl Div for Trace { fn div });
413operator_impl_value_reference!(impl Div for Trace { fn div });
414
415/**
416 * Dvision for a trace and a constant of the same type with both referenced.
417 */
418impl<T: Numeric + Primitive> Div<&T> for &Trace<T>
419where
420    for<'a> &'a T: NumericRef<T>,
421{
422    type Output = Trace<T>;
423    #[inline]
424    fn div(self, rhs: &T) -> Self::Output {
425        Trace {
426            number: self.number.clone() / rhs.clone(),
427            derivative: (self.derivative.clone() * rhs.clone()) / (rhs.clone() * rhs.clone()),
428        }
429    }
430}
431
432trace_number_operator_impl_value_value!(impl Div for Trace { fn div });
433trace_number_operator_impl_reference_value!(impl Div for Trace { fn div });
434trace_number_operator_impl_value_reference!(impl Div for Trace { fn div });
435
436/**
437 * Negation for a referenced Trace of some type.
438 */
439impl<T: Numeric + Primitive> Neg for &Trace<T>
440where
441    for<'a> &'a T: NumericRef<T>,
442{
443    type Output = Trace<T>;
444    #[inline]
445    fn neg(self) -> Self::Output {
446        Trace::<T>::zero() - self
447    }
448}
449
450/**
451 * Negation for a Trace by value of some type.
452 */
453impl<T: Numeric + Primitive> Neg for Trace<T>
454where
455    for<'a> &'a T: NumericRef<T>,
456{
457    type Output = Trace<T>;
458    #[inline]
459    fn neg(self) -> Self::Output {
460        Trace::<T>::zero() - self
461    }
462}
463
464/**
465 * Sine of a Trace by reference.
466 */
467impl<T: Real + Primitive> Sin for &Trace<T>
468where
469    for<'a> &'a T: RealRef<T>,
470{
471    type Output = Trace<T>;
472    #[inline]
473    fn sin(self) -> Self::Output {
474        Trace {
475            number: self.number.clone().sin(),
476            // u' cos(u)
477            derivative: self.derivative.clone() * self.number.clone().cos(),
478        }
479    }
480}
481
482macro_rules! trace_real_operator_impl_value {
483    (impl $op:tt for Trace { fn $method:ident }) => {
484        /**
485         * Operation for a trace by value.
486         */
487        impl<T: Real + Primitive> $op for Trace<T>
488        where
489            for<'a> &'a T: RealRef<T>,
490        {
491            type Output = Trace<T>;
492            #[inline]
493            fn $method(self) -> Self::Output {
494                (&self).$method()
495            }
496        }
497    };
498}
499
500trace_real_operator_impl_value!(impl Sin for Trace { fn sin });
501
502/**
503 * Cosine of a Trace by reference.
504 */
505impl<T: Real + Primitive> Cos for &Trace<T>
506where
507    for<'a> &'a T: RealRef<T>,
508{
509    type Output = Trace<T>;
510    #[inline]
511    fn cos(self) -> Self::Output {
512        Trace {
513            number: self.number.clone().cos(),
514            // -u' sin(u)
515            derivative: -self.derivative.clone() * self.number.clone().sin(),
516        }
517    }
518}
519
520trace_real_operator_impl_value!(impl Cos for Trace { fn cos });
521
522/**
523 * Exponential, ie e<sup>x</sup> of a Trace by reference.
524 */
525impl<T: Real + Primitive> Exp for &Trace<T>
526where
527    for<'a> &'a T: RealRef<T>,
528{
529    type Output = Trace<T>;
530    #[inline]
531    fn exp(self) -> Self::Output {
532        Trace {
533            number: self.number.clone().exp(),
534            // u' exp(u)
535            derivative: self.derivative.clone() * self.number.clone().exp(),
536        }
537    }
538}
539
540trace_real_operator_impl_value!(impl Exp for Trace { fn exp });
541
542/**
543 * Natural logarithm, ie ln(x) of a Trace by reference.
544 */
545impl<T: Real + Primitive> Ln for &Trace<T>
546where
547    for<'a> &'a T: RealRef<T>,
548{
549    type Output = Trace<T>;
550    #[inline]
551    fn ln(self) -> Self::Output {
552        Trace {
553            number: self.number.clone().ln(),
554            // u' / u
555            derivative: self.derivative.clone() / self.number.clone(),
556        }
557    }
558}
559
560trace_real_operator_impl_value!(impl Ln for Trace { fn ln });
561
562/**
563 * Square root of a Trace by reference.
564 */
565impl<T: Real + Primitive> Sqrt for &Trace<T>
566where
567    for<'a> &'a T: RealRef<T>,
568{
569    type Output = Trace<T>;
570    #[inline]
571    fn sqrt(self) -> Self::Output {
572        Trace {
573            number: self.number.clone().sqrt(),
574            // u'/(2*sqrt(u))
575            #[rustfmt::skip]
576            derivative: (
577                self.derivative.clone() / ((T::one() + T::one()) * self.number.clone().sqrt())
578            ),
579        }
580    }
581}
582
583trace_real_operator_impl_value!(impl Sqrt for Trace { fn sqrt });
584
585/**
586 * Power of one Trace to another, ie self^rhs for two traces of
587 * the same type with both referenced.
588 */
589impl<'l, 'r, T: Real + Primitive> Pow<&'r Trace<T>> for &'l Trace<T>
590where
591    for<'a> &'a T: RealRef<T>,
592{
593    type Output = Trace<T>;
594    #[inline]
595    fn pow(self, rhs: &Trace<T>) -> Self::Output {
596        Trace {
597            number: self.number.clone().pow(rhs.number.clone()),
598            // (u' * d(u^v)/du) + (v' * d(u^v)/dv) ==
599            // (u' * v * u^(v-1)) + (v' * u^v * ln(u))
600            #[rustfmt::skip]
601            derivative: (
602                (self.derivative.clone() * rhs.number.clone()
603                    * (self.number.clone().pow(rhs.number.clone() - T::one())))
604                + (rhs.derivative.clone()
605                    * (self.number.clone().pow(rhs.number.clone())) * self.number.clone().ln())
606            ),
607        }
608    }
609}
610
611macro_rules! trace_real_operator_impl_value_value {
612    (impl $op:tt for Trace { fn $method:ident }) => {
613        /**
614         * Operation for two traces of the same type.
615         */
616        impl<T: Real + Primitive> $op for Trace<T>
617        where
618            for<'a> &'a T: RealRef<T>,
619        {
620            type Output = Trace<T>;
621            #[inline]
622            fn $method(self, rhs: Trace<T>) -> Self::Output {
623                (&self).$method(&rhs)
624            }
625        }
626    };
627}
628
629macro_rules! trace_real_operator_impl_value_reference {
630    (impl $op:tt for Trace { fn $method:ident }) => {
631        /**
632         * Operation for two traces of the same type with the right referenced.
633         */
634        impl<T: Real + Primitive> $op<&Trace<T>> for Trace<T>
635        where
636            for<'a> &'a T: RealRef<T>,
637        {
638            type Output = Trace<T>;
639            #[inline]
640            fn $method(self, rhs: &Trace<T>) -> Self::Output {
641                (&self).$method(rhs)
642            }
643        }
644    };
645}
646
647macro_rules! trace_real_operator_impl_reference_value {
648    (impl $op:tt for Trace { fn $method:ident }) => {
649        /**
650         * Operation for two traces of the same type with the left referenced.
651         */
652        impl<T: Real + Primitive> $op<Trace<T>> for &Trace<T>
653        where
654            for<'a> &'a T: RealRef<T>,
655        {
656            type Output = Trace<T>;
657            #[inline]
658            fn $method(self, rhs: Trace<T>) -> Self::Output {
659                self.$method(&rhs)
660            }
661        }
662    };
663}
664
665trace_real_operator_impl_value_value!(impl Pow for Trace { fn pow });
666trace_real_operator_impl_reference_value!(impl Pow for Trace { fn pow });
667trace_real_operator_impl_value_reference!(impl Pow for Trace { fn pow });
668
669/**
670 * Power of a trace to a constant of the same type with both referenced.
671 */
672impl<T: Real + Primitive> Pow<&T> for &Trace<T>
673where
674    for<'a> &'a T: RealRef<T>,
675{
676    type Output = Trace<T>;
677    #[allow(clippy::double_parens)]
678    #[inline]
679    fn pow(self, rhs: &T) -> Self::Output {
680        Trace {
681            number: self.number.clone().pow(rhs.clone()),
682            // (u' * d(u^v)/du) == (u' * v * u^(v-1))
683            #[rustfmt::skip]
684            derivative: (
685                (self.derivative.clone() * rhs.clone()
686                * (self.number.clone().pow(rhs.clone() - T::one())))
687            ),
688        }
689    }
690}
691
692macro_rules! trace_real_number_operator_impl_value_value {
693    (impl $op:tt for Trace { fn $method:ident }) => {
694        /**
695         * Operation for a trace and a constant of the same type.
696         */
697        impl<T: Real + Primitive> $op<T> for Trace<T>
698        where
699            for<'a> &'a T: RealRef<T>,
700        {
701            type Output = Trace<T>;
702            #[inline]
703            fn $method(self, rhs: T) -> Self::Output {
704                (&self).$method(&rhs)
705            }
706        }
707    };
708}
709
710macro_rules! trace_real_number_operator_impl_value_reference {
711    (impl $op:tt for Trace { fn $method:ident }) => {
712        /**
713         * Operation for a trace and a constant of the same type with the right referenced.
714         */
715        impl<T: Real + Primitive> $op<&T> for Trace<T>
716        where
717            for<'a> &'a T: RealRef<T>,
718        {
719            type Output = Trace<T>;
720            #[inline]
721            fn $method(self, rhs: &T) -> Self::Output {
722                (&self).$method(rhs)
723            }
724        }
725    };
726}
727
728macro_rules! trace_real_number_operator_impl_reference_value {
729    (impl $op:tt for Trace { fn $method:ident }) => {
730        /**
731         * Operation for a trace and a constant of the same type with the left referenced.
732         */
733        impl<T: Real + Primitive> $op<T> for &Trace<T>
734        where
735            for<'a> &'a T: RealRef<T>,
736        {
737            type Output = Trace<T>;
738            #[inline]
739            fn $method(self, rhs: T) -> Self::Output {
740                self.$method(&rhs)
741            }
742        }
743    };
744}
745
746trace_real_number_operator_impl_value_value!(impl Pow for Trace { fn pow });
747trace_real_number_operator_impl_reference_value!(impl Pow for Trace { fn pow });
748trace_real_number_operator_impl_value_reference!(impl Pow for Trace { fn pow });
749
750/**
751 * Power of a constant to a trace of the same type with both referenced.
752 */
753impl<T: Real + Primitive> Pow<&Trace<T>> for &T
754where
755    for<'a> &'a T: RealRef<T>,
756{
757    type Output = Trace<T>;
758    #[allow(clippy::double_parens)]
759    #[inline]
760    fn pow(self, rhs: &Trace<T>) -> Self::Output {
761        Trace {
762            number: self.clone().pow(rhs.number.clone()),
763            // (v' * d(u^v)/dv) == (v' * u^v * ln(u))
764            #[rustfmt::skip]
765            derivative:  (
766                (rhs.derivative.clone()
767                    * (self.clone().pow(rhs.number.clone())) * self.clone().ln())
768            ),
769        }
770    }
771}
772
773macro_rules! real_number_trace_operator_impl_value_value {
774    (impl $op:tt for Trace { fn $method:ident }) => {
775        /**
776         * Operation for a trace and a constant of the same type.
777         */
778        impl<T: Real + Primitive> $op<Trace<T>> for T
779        where
780            for<'a> &'a T: RealRef<T>,
781        {
782            type Output = Trace<T>;
783            #[inline]
784            fn $method(self, rhs: Trace<T>) -> Self::Output {
785                (&self).$method(&rhs)
786            }
787        }
788    };
789}
790
791macro_rules! real_number_trace_operator_impl_value_reference {
792    (impl $op:tt for Trace { fn $method:ident }) => {
793        /**
794         * Operation for a trace and a constant of the same type with the right referenced.
795         */
796        impl<T: Real + Primitive> $op<&Trace<T>> for T
797        where
798            for<'a> &'a T: RealRef<T>,
799        {
800            type Output = Trace<T>;
801            #[inline]
802            fn $method(self, rhs: &Trace<T>) -> Self::Output {
803                (&self).$method(rhs)
804            }
805        }
806    };
807}
808
809macro_rules! real_number_trace_operator_impl_reference_value {
810    (impl $op:tt for Trace { fn $method:ident }) => {
811        /**
812         * Operation for a trace and a constant of the same type with the left referenced.
813         */
814        impl<T: Real + Primitive> $op<Trace<T>> for &T
815        where
816            for<'a> &'a T: RealRef<T>,
817        {
818            type Output = Trace<T>;
819            #[inline]
820            fn $method(self, rhs: Trace<T>) -> Self::Output {
821                self.$method(&rhs)
822            }
823        }
824    };
825}
826
827real_number_trace_operator_impl_value_value!(impl Pow for Trace { fn pow });
828real_number_trace_operator_impl_reference_value!(impl Pow for Trace { fn pow });
829real_number_trace_operator_impl_value_reference!(impl Pow for Trace { fn pow });
830
831impl<T: Real + Primitive> Pi for Trace<T> {
832    #[inline]
833    fn pi() -> Trace<T> {
834        Trace::constant(T::pi())
835    }
836}