use crate::differentiation::functions::{
Addition, Cosine, Division, Exponential, FunctionDerivative, Multiplication, NaturalLogarithm,
Power, Sine, SquareRoot, Subtraction, UnaryFunctionDerivative,
};
use crate::differentiation::{Primitive, Record, WengertList};
use crate::numeric::extra::{Cos, Exp, Ln, Pi, Pow, Real, RealRef, Sin, Sqrt};
use crate::numeric::{FromUsize, Numeric, NumericRef, ZeroOne};
use std::cmp::Ordering;
use std::iter::Sum;
use std::ops::{Add, Div, Mul, Neg, Sub};
impl<'a, T: std::fmt::Display + Primitive> std::fmt::Display for Record<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.number)
}
}
impl<'a, T: Numeric + Primitive> ZeroOne for Record<'a, T> {
#[inline]
fn zero() -> Record<'a, T> {
Record::constant(T::zero())
}
#[inline]
fn one() -> Record<'a, T> {
Record::constant(T::one())
}
}
impl<'a, T: Numeric + Primitive> FromUsize for Record<'a, T> {
#[inline]
fn from_usize(n: usize) -> Option<Record<'a, T>> {
Some(Record::constant(T::from_usize(n)?))
}
}
impl<'a, T: Clone + Primitive> Clone for Record<'a, T> {
#[inline]
fn clone(&self) -> Self {
Record {
number: self.number.clone(),
history: self.history,
index: self.index,
}
}
}
impl<'a, T: Copy + Primitive> Copy for Record<'a, T> {}
pub(crate) fn same_list<T: Primitive>(a: &Record<T>, b: &Record<T>) -> bool {
match (a.history, b.history) {
(None, None) => true,
(Some(_), None) => true,
(None, Some(_)) => true,
(Some(list_a), Some(list_b)) => same_lists(list_a, list_b),
}
}
pub(crate) fn same_lists<T: Primitive>(list_a: &WengertList<T>, list_b: &WengertList<T>) -> bool {
std::ptr::eq(list_a, list_b)
}
pub(crate) fn are_same_list<T: Primitive>(
list_a: Option<&WengertList<T>>,
list_b: Option<&WengertList<T>>,
) -> bool {
match (list_a, list_b) {
(None, None) => true,
(Some(_), None) => true,
(None, Some(_)) => true,
(Some(list_a), Some(list_b)) => same_lists(list_a, list_b),
}
}
pub(crate) fn are_exact_same_list<T: Primitive>(
list_a: Option<&WengertList<T>>,
list_b: Option<&WengertList<T>>,
) -> bool {
match (list_a, list_b) {
(None, None) => true,
(Some(_), None) => false,
(None, Some(_)) => false,
(Some(list_a), Some(list_b)) => same_lists(list_a, list_b),
}
}
impl<'a, T: Numeric + Primitive> Add<&Record<'a, T>> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn add(self, rhs: &Record<'a, T>) -> Self::Output {
assert!(
same_list(self, rhs),
"Records must be using the same WengertList"
);
match (self.history, rhs.history) {
(None, None) => Record {
number: Addition::<T>::function(self.number.clone(), rhs.number.clone()),
history: None,
index: 0,
},
(Some(_), None) => self + &rhs.number,
(None, Some(_)) => rhs + &self.number,
(Some(history), Some(_)) => Record {
number: Addition::<T>::function(self.number.clone(), rhs.number.clone()),
history: Some(history),
index: history.append_binary(
self.index,
Addition::<T>::d_function_dx(self.number.clone(), rhs.number.clone()),
rhs.index,
Addition::<T>::d_function_dy(self.number.clone(), rhs.number.clone()),
),
},
}
}
}
impl<'a, T: Numeric + Primitive> Add<&T> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn add(self, rhs: &T) -> Self::Output {
match self.history {
None => Record {
number: Addition::<T>::function(self.number.clone(), rhs.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Addition::<T>::function(self.number.clone(), rhs.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Addition::<T>::d_function_dx(self.number.clone(), rhs.clone()),
),
},
}
}
}
macro_rules! record_operator_impl_value_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Numeric + Primitive> $op for Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn $method(self, rhs: Record<'a, T>) -> Self::Output {
(&self).$method(&rhs)
}
}
};
}
macro_rules! record_operator_impl_value_reference {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Numeric + Primitive> $op<&Record<'a, T>> for Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn $method(self, rhs: &Record<'a, T>) -> Self::Output {
(&self).$method(rhs)
}
}
};
}
macro_rules! record_operator_impl_reference_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Numeric + Primitive> $op<Record<'a, T>> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn $method(self, rhs: Record<'a, T>) -> Self::Output {
self.$method(&rhs)
}
}
};
}
record_operator_impl_value_value!(impl Add for Record { fn add });
record_operator_impl_reference_value!(impl Add for Record { fn add });
record_operator_impl_value_reference!(impl Add for Record { fn add });
macro_rules! record_number_operator_impl_value_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Numeric + Primitive> $op<T> for Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: T) -> Self::Output {
(&self).$method(&rhs)
}
}
};
}
macro_rules! record_number_operator_impl_value_reference {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Numeric + Primitive> $op<&T> for Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: &T) -> Self::Output {
(&self).$method(rhs)
}
}
};
}
macro_rules! record_number_operator_impl_reference_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Numeric + Primitive> $op<T> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: T) -> Self::Output {
self.$method(&rhs)
}
}
};
}
record_number_operator_impl_value_value!(impl Add for Record { fn add });
record_number_operator_impl_reference_value!(impl Add for Record { fn add });
record_number_operator_impl_value_reference!(impl Add for Record { fn add });
impl<'a, T: Numeric + Primitive> Mul<&Record<'a, T>> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn mul(self, rhs: &Record<'a, T>) -> Self::Output {
assert!(
same_list(self, rhs),
"Records must be using the same WengertList"
);
match (self.history, rhs.history) {
(None, None) => Record {
number: Multiplication::<T>::function(self.number.clone(), rhs.number.clone()),
history: None,
index: 0,
},
(Some(_), None) => self * &rhs.number,
(None, Some(_)) => rhs * &self.number,
(Some(history), Some(_)) => Record {
number: Multiplication::<T>::function(self.number.clone(), rhs.number.clone()),
history: Some(history),
index: history.append_binary(
self.index,
Multiplication::<T>::d_function_dx(self.number.clone(), rhs.number.clone()),
rhs.index,
Multiplication::<T>::d_function_dy(self.number.clone(), rhs.number.clone()),
),
},
}
}
}
record_operator_impl_value_value!(impl Mul for Record { fn mul });
record_operator_impl_reference_value!(impl Mul for Record { fn mul });
record_operator_impl_value_reference!(impl Mul for Record { fn mul });
impl<'a, T: Numeric + Primitive> Mul<&T> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn mul(self, rhs: &T) -> Self::Output {
match self.history {
None => Record {
number: Multiplication::<T>::function(self.number.clone(), rhs.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Multiplication::<T>::function(self.number.clone(), rhs.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Multiplication::<T>::d_function_dx(self.number.clone(), rhs.clone()),
),
},
}
}
}
record_number_operator_impl_value_value!(impl Mul for Record { fn mul });
record_number_operator_impl_reference_value!(impl Mul for Record { fn mul });
record_number_operator_impl_value_reference!(impl Mul for Record { fn mul });
impl<'a, T: Numeric + Primitive> Sub<&Record<'a, T>> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn sub(self, rhs: &Record<'a, T>) -> Self::Output {
assert!(
same_list(self, rhs),
"Records must be using the same WengertList"
);
match (self.history, rhs.history) {
(None, None) => Record {
number: Subtraction::<T>::function(self.number.clone(), rhs.number.clone()),
history: None,
index: 0,
},
(Some(_), None) => self - &rhs.number,
(None, Some(_)) => rhs.sub_swapped(self.number.clone()),
(Some(history), Some(_)) => Record {
number: Subtraction::<T>::function(self.number.clone(), rhs.number.clone()),
history: Some(history),
index: history.append_binary(
self.index,
Subtraction::<T>::d_function_dx(self.number.clone(), rhs.number.clone()),
rhs.index,
Subtraction::<T>::d_function_dy(self.number.clone(), rhs.number.clone()),
),
},
}
}
}
record_operator_impl_value_value!(impl Sub for Record { fn sub });
record_operator_impl_reference_value!(impl Sub for Record { fn sub });
record_operator_impl_value_reference!(impl Sub for Record { fn sub });
impl<'a, T: Numeric + Primitive> Sub<&T> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn sub(self, rhs: &T) -> Self::Output {
match self.history {
None => Record {
number: Subtraction::<T>::function(self.number.clone(), rhs.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Subtraction::<T>::function(self.number.clone(), rhs.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Subtraction::<T>::d_function_dx(self.number.clone(), rhs.clone()),
),
},
}
}
}
record_number_operator_impl_value_value!(impl Sub for Record { fn sub });
record_number_operator_impl_reference_value!(impl Sub for Record { fn sub });
record_number_operator_impl_value_reference!(impl Sub for Record { fn sub });
pub trait SwappedOperations<Lhs = Self> {
type Output;
fn sub_swapped(self, lhs: Lhs) -> Self::Output;
fn div_swapped(self, lhs: Lhs) -> Self::Output;
}
impl<'a, T: Numeric + Primitive> SwappedOperations<&T> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn sub_swapped(self, lhs: &T) -> Self::Output {
match self.history {
None => Record {
number: Subtraction::<T>::function(lhs.clone(), self.number.clone()),
history: None,
index: 0,
},
Some(history) => {
Record {
number: Subtraction::<T>::function(lhs.clone(), self.number.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Subtraction::<T>::d_function_dy(lhs.clone(), self.number.clone()),
),
}
}
}
}
#[inline]
fn div_swapped(self, lhs: &T) -> Self::Output {
match self.history {
None => Record {
number: Division::<T>::function(lhs.clone(), self.number.clone()),
history: None,
index: 0,
},
Some(history) => {
Record {
number: Division::<T>::function(lhs.clone(), self.number.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Division::<T>::d_function_dy(lhs.clone(), self.number.clone()),
),
}
}
}
}
}
impl<'a, T: Numeric + Primitive> SwappedOperations<T> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn sub_swapped(self, lhs: T) -> Self::Output {
self.sub_swapped(&lhs)
}
#[inline]
fn div_swapped(self, lhs: T) -> Self::Output {
self.div_swapped(&lhs)
}
}
impl<'a, T: Numeric + Primitive> SwappedOperations<T> for Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn sub_swapped(self, lhs: T) -> Self::Output {
(&self).sub_swapped(&lhs)
}
#[inline]
fn div_swapped(self, lhs: T) -> Self::Output {
(&self).div_swapped(&lhs)
}
}
impl<'a, T: Numeric + Primitive> SwappedOperations<&T> for Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn sub_swapped(self, lhs: &T) -> Self::Output {
(&self).sub_swapped(lhs)
}
#[inline]
fn div_swapped(self, lhs: &T) -> Self::Output {
(&self).div_swapped(lhs)
}
}
impl<'a, T: Numeric + Primitive> Div<&Record<'a, T>> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn div(self, rhs: &Record<'a, T>) -> Self::Output {
assert!(
same_list(self, rhs),
"Records must be using the same WengertList"
);
match (self.history, rhs.history) {
(None, None) => Record {
number: Division::<T>::function(self.number.clone(), rhs.number.clone()),
history: None,
index: 0,
},
(Some(_), None) => self / &rhs.number,
(None, Some(_)) => rhs.div_swapped(self.number.clone()),
(Some(history), Some(_)) => Record {
number: Division::<T>::function(self.number.clone(), rhs.number.clone()),
history: Some(history),
index: history.append_binary(
self.index,
Division::<T>::d_function_dx(self.number.clone(), rhs.number.clone()),
rhs.index,
Division::<T>::d_function_dy(self.number.clone(), rhs.number.clone()),
),
},
}
}
}
record_operator_impl_value_value!(impl Div for Record { fn div });
record_operator_impl_reference_value!(impl Div for Record { fn div });
record_operator_impl_value_reference!(impl Div for Record { fn div });
impl<'a, T: Numeric + Primitive> Div<&T> for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn div(self, rhs: &T) -> Self::Output {
match self.history {
None => Record {
number: Division::<T>::function(self.number.clone(), rhs.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Division::<T>::function(self.number.clone(), rhs.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Division::<T>::d_function_dx(self.number.clone(), rhs.clone()),
),
},
}
}
}
record_number_operator_impl_value_value!(impl Div for Record { fn div });
record_number_operator_impl_reference_value!(impl Div for Record { fn div });
record_number_operator_impl_value_reference!(impl Div for Record { fn div });
impl<'a, T: Numeric + Primitive> Neg for &Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn neg(self) -> Self::Output {
match self.history {
None => Record {
number: -self.number.clone(),
history: None,
index: 0,
},
Some(_) => Record::constant(T::zero()) - self,
}
}
}
impl<'a, T: Numeric + Primitive> Neg for Record<'a, T>
where
for<'t> &'t T: NumericRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn neg(self) -> Self::Output {
match self.history {
None => Record {
number: -self.number,
history: None,
index: 0,
},
Some(_) => Record::constant(T::zero()) - self,
}
}
}
impl<'a, T: PartialEq + Primitive> PartialEq for Record<'a, T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.number == other.number
}
}
impl<'a, T: PartialOrd + Primitive> PartialOrd for Record<'a, T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.number.partial_cmp(&other.number)
}
}
impl<'a, T: Numeric + Primitive> Sum for Record<'a, T> {
#[track_caller]
fn sum<I>(mut iter: I) -> Record<'a, T>
where
I: Iterator<Item = Record<'a, T>>,
{
let mut total = Record::<'a, T>::zero();
loop {
match iter.next() {
None => return total,
Some(next) => {
total = match (total.history, next.history) {
(None, None) => Record {
number: total.number.clone() + next.number.clone(),
history: None,
index: 0,
},
(Some(history), None) => {
Record {
number: total.number.clone() + next.number.clone(),
history: Some(history),
index: history.append_unary(
total.index,
T::one(),
),
}
}
(None, Some(history)) => {
Record {
number: total.number.clone() + next.number.clone(),
history: Some(history),
index: history.append_unary(
next.index,
T::one(),
),
}
}
(Some(history), Some(_)) => {
assert!(
same_list(&total, &next),
"Records must be using the same WengertList"
);
Record {
number: total.number.clone() + next.number.clone(),
history: Some(history),
index: history.append_binary(
total.index,
T::one(),
next.index,
T::one(),
),
}
}
}
}
}
}
}
}
impl<'a, T: Real + Primitive> Sin for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn sin(self) -> Self::Output {
match self.history {
None => Record {
number: Sine::<T>::function(self.number.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Sine::<T>::function(self.number.clone()),
history: Some(history),
index: history
.append_unary(self.index, Sine::<T>::d_function_dx(self.number.clone())),
},
}
}
}
macro_rules! record_real_operator_impl_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op for Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self) -> Self::Output {
(&self).$method()
}
}
};
}
record_real_operator_impl_value!(impl Sin for Record { fn sin });
impl<'a, T: Real + Primitive> Cos for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn cos(self) -> Self::Output {
match self.history {
None => Record {
number: Cosine::<T>::function(self.number.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Cosine::<T>::function(self.number.clone()),
history: Some(history),
index: history
.append_unary(self.index, Cosine::<T>::d_function_dx(self.number.clone())),
},
}
}
}
record_real_operator_impl_value!(impl Cos for Record { fn cos });
impl<'a, T: Real + Primitive> Exp for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn exp(self) -> Self::Output {
match self.history {
None => Record {
number: Exponential::<T>::function(self.number.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Exponential::<T>::function(self.number.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Exponential::<T>::d_function_dx(self.number.clone()),
),
},
}
}
}
record_real_operator_impl_value!(impl Exp for Record { fn exp });
impl<'a, T: Real + Primitive> Ln for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn ln(self) -> Self::Output {
match self.history {
None => Record {
number: NaturalLogarithm::<T>::function(self.number.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: NaturalLogarithm::<T>::function(self.number.clone()),
history: Some(history),
index: history.append_unary(
self.index,
NaturalLogarithm::<T>::d_function_dx(self.number.clone()),
),
},
}
}
}
record_real_operator_impl_value!(impl Ln for Record { fn ln });
impl<'a, T: Real + Primitive> Sqrt for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn sqrt(self) -> Self::Output {
match self.history {
None => Record {
number: SquareRoot::<T>::function(self.number.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: SquareRoot::<T>::function(self.number.clone()),
history: Some(history),
index: history.append_unary(
self.index,
SquareRoot::<T>::d_function_dx(self.number.clone()),
),
},
}
}
}
record_real_operator_impl_value!(impl Sqrt for Record { fn sqrt });
impl<'a, T: Real + Primitive> Pow<&Record<'a, T>> for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
#[track_caller]
fn pow(self, rhs: &Record<'a, T>) -> Self::Output {
assert!(
same_list(self, rhs),
"Records must be using the same WengertList"
);
match (self.history, rhs.history) {
(None, None) => Record {
number: Power::<T>::function(self.number.clone(), rhs.number.clone()),
history: None,
index: 0,
},
(Some(_), None) => self.pow(&rhs.number),
(None, Some(_)) => (&self.number).pow(rhs),
(Some(history), Some(_)) => Record {
number: Power::<T>::function(self.number.clone(), rhs.number.clone()),
history: Some(history),
index: history.append_binary(
self.index,
Power::<T>::d_function_dx(self.number.clone(), rhs.number.clone()),
rhs.index,
Power::<T>::d_function_dy(self.number.clone(), rhs.number.clone()),
),
},
}
}
}
macro_rules! record_real_operator_impl_value_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op for Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn $method(self, rhs: Record<'a, T>) -> Self::Output {
(&self).$method(&rhs)
}
}
};
}
macro_rules! record_real_operator_impl_value_reference {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<&Record<'a, T>> for Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn $method(self, rhs: &Record<'a, T>) -> Self::Output {
(&self).$method(rhs)
}
}
};
}
macro_rules! record_real_operator_impl_reference_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<Record<'a, T>> for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[track_caller]
#[inline]
fn $method(self, rhs: Record<'a, T>) -> Self::Output {
self.$method(&rhs)
}
}
};
}
record_real_operator_impl_value_value!(impl Pow for Record { fn pow });
record_real_operator_impl_reference_value!(impl Pow for Record { fn pow });
record_real_operator_impl_value_reference!(impl Pow for Record { fn pow });
impl<'a, T: Real + Primitive> Pow<&T> for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn pow(self, rhs: &T) -> Self::Output {
match self.history {
None => Record {
number: Power::<T>::function(self.number.clone(), rhs.clone()),
history: None,
index: 0,
},
Some(history) => Record {
number: Power::<T>::function(self.number.clone(), rhs.clone()),
history: Some(history),
index: history.append_unary(
self.index,
Power::<T>::d_function_dx(self.number.clone(), rhs.clone()),
),
},
}
}
}
impl<'a, T: Real + Primitive> Pow<&Record<'a, T>> for &T
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn pow(self, rhs: &Record<'a, T>) -> Self::Output {
match rhs.history {
None => Record {
number: Power::<T>::function(self.clone(), rhs.number.clone()),
history: None,
index: 0,
},
Some(history) => {
Record {
number: Power::<T>::function(self.clone(), rhs.number.clone()),
history: Some(history),
index: history.append_unary(
rhs.index,
Power::<T>::d_function_dy(self.clone(), rhs.number.clone()),
),
}
}
}
}
}
macro_rules! record_real_number_operator_impl_value_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<T> for Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: T) -> Self::Output {
(&self).$method(&rhs)
}
}
};
}
macro_rules! record_real_number_operator_impl_value_reference {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<&T> for Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: &T) -> Self::Output {
(&self).$method(rhs)
}
}
};
}
macro_rules! record_real_number_operator_impl_reference_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<T> for &Record<'a, T>
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: T) -> Self::Output {
self.$method(&rhs)
}
}
};
}
record_real_number_operator_impl_value_value!(impl Pow for Record { fn pow });
record_real_number_operator_impl_reference_value!(impl Pow for Record { fn pow });
record_real_number_operator_impl_value_reference!(impl Pow for Record { fn pow });
macro_rules! real_number_record_operator_impl_value_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<Record<'a, T>> for T
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: Record<'a, T>) -> Self::Output {
(&self).$method(&rhs)
}
}
};
}
macro_rules! real_number_record_operator_impl_value_reference {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<&Record<'a, T>> for T
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: &Record<'a, T>) -> Self::Output {
(&self).$method(rhs)
}
}
};
}
macro_rules! real_number_record_operator_impl_reference_value {
(impl $op:tt for Record { fn $method:ident }) => {
impl<'a, T: Real + Primitive> $op<Record<'a, T>> for &T
where
for<'t> &'t T: RealRef<T>,
{
type Output = Record<'a, T>;
#[inline]
fn $method(self, rhs: Record<'a, T>) -> Self::Output {
self.$method(&rhs)
}
}
};
}
real_number_record_operator_impl_value_value!(impl Pow for Record { fn pow });
real_number_record_operator_impl_reference_value!(impl Pow for Record { fn pow });
real_number_record_operator_impl_value_reference!(impl Pow for Record { fn pow });
impl<'a, T: Real + Primitive> Pi for Record<'a, T> {
#[inline]
fn pi() -> Record<'a, T> {
Record::constant(T::pi())
}
}