1#![allow(clippy::double_parens)]
2use 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
43impl<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
52impl<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
73impl<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
86impl<T: Copy + Primitive> Copy for Trace<T> {}
90
91impl<T: PartialEq + Primitive> PartialEq for Trace<T> {
103 #[inline]
104 fn eq(&self, other: &Self) -> bool {
105 self.number == other.number
106 }
107}
108
109impl<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
127impl<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
152impl<'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 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 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 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
227impl<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 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 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 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
302impl<'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 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
325impl<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
346impl<'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
367impl<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
388impl<'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 #[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
415impl<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
436impl<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
450impl<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
464impl<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 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 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
502impl<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 derivative: -self.derivative.clone() * self.number.clone().sin(),
516 }
517 }
518}
519
520trace_real_operator_impl_value!(impl Cos for Trace { fn cos });
521
522impl<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 derivative: self.derivative.clone() * self.number.clone().exp(),
536 }
537 }
538}
539
540trace_real_operator_impl_value!(impl Exp for Trace { fn exp });
541
542impl<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 derivative: self.derivative.clone() / self.number.clone(),
556 }
557 }
558}
559
560trace_real_operator_impl_value!(impl Ln for Trace { fn ln });
561
562impl<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 #[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
585impl<'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 #[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 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 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 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
669impl<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 #[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 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 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 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
750impl<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 #[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 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 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 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}