use std::fmt;
use crate::freal::FReal;
use crate::math;
use crate::traits::Scalar;
#[derive(Clone)]
pub struct LabeledFReal<T: Scalar> {
pub(super) inner: FReal<T>,
#[cfg(debug_assertions)]
pub(super) gen_id: u64,
}
impl<T: Scalar> LabeledFReal<T> {
#[inline]
pub(crate) fn __from_inner(inner: FReal<T>) -> Self {
Self {
inner,
#[cfg(debug_assertions)]
gen_id: crate::labeled::forward_tape::current_gen(),
}
}
#[inline]
pub fn value(&self) -> T {
self.inner.value()
}
#[inline]
pub fn derivative(&self, _name: &str) -> T {
self.inner.derivative()
}
#[inline]
pub fn inner(&self) -> &FReal<T> {
&self.inner
}
#[inline]
pub fn exp(&self) -> Self {
Self {
inner: math::fwd::exp(&self.inner),
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
#[inline]
pub fn ln(&self) -> Self {
Self {
inner: math::fwd::ln(&self.inner),
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
#[inline]
pub fn sqrt(&self) -> Self {
Self {
inner: math::fwd::sqrt(&self.inner),
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
#[inline]
pub fn sin(&self) -> Self {
Self {
inner: math::fwd::sin(&self.inner),
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
#[inline]
pub fn cos(&self) -> Self {
Self {
inner: math::fwd::cos(&self.inner),
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
#[inline]
pub fn tan(&self) -> Self {
Self {
inner: math::fwd::tan(&self.inner),
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
impl<T: Scalar> fmt::Debug for LabeledFReal<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LabeledFReal")
.field("value", &self.inner.value())
.field("derivative", &self.inner.derivative())
.finish()
}
}
impl<T: Scalar> fmt::Display for LabeledFReal<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "LabeledFReal({})", self.inner.value())
}
}
macro_rules! __lbl_freal_binop {
($trait:ident, $method:ident, $op:tt) => {
impl<T: Scalar> ::core::ops::$trait<LabeledFReal<T>> for LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn $method(self, rhs: LabeledFReal<T>) -> LabeledFReal<T> {
#[cfg(debug_assertions)]
crate::labeled::forward_tape::check_gen(self.gen_id, rhs.gen_id);
LabeledFReal {
inner: self.inner $op rhs.inner,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
impl<T: Scalar> ::core::ops::$trait<&LabeledFReal<T>> for &LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn $method(self, rhs: &LabeledFReal<T>) -> LabeledFReal<T> {
#[cfg(debug_assertions)]
crate::labeled::forward_tape::check_gen(self.gen_id, rhs.gen_id);
LabeledFReal {
inner: &self.inner $op &rhs.inner,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
impl<T: Scalar> ::core::ops::$trait<&LabeledFReal<T>> for LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn $method(self, rhs: &LabeledFReal<T>) -> LabeledFReal<T> {
#[cfg(debug_assertions)]
crate::labeled::forward_tape::check_gen(self.gen_id, rhs.gen_id);
LabeledFReal {
inner: self.inner $op &rhs.inner,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
impl<T: Scalar> ::core::ops::$trait<LabeledFReal<T>> for &LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn $method(self, rhs: LabeledFReal<T>) -> LabeledFReal<T> {
#[cfg(debug_assertions)]
crate::labeled::forward_tape::check_gen(self.gen_id, rhs.gen_id);
LabeledFReal {
inner: &self.inner $op rhs.inner,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
impl<T: Scalar> ::core::ops::$trait<T> for LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn $method(self, rhs: T) -> LabeledFReal<T> {
LabeledFReal {
inner: self.inner $op rhs,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
impl<T: Scalar> ::core::ops::$trait<T> for &LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn $method(self, rhs: T) -> LabeledFReal<T> {
LabeledFReal {
inner: &self.inner $op rhs,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
};
}
__lbl_freal_binop!(Add, add, +);
__lbl_freal_binop!(Sub, sub, -);
__lbl_freal_binop!(Mul, mul, *);
__lbl_freal_binop!(Div, div, /);
impl<T: Scalar> ::core::ops::Neg for LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn neg(self) -> LabeledFReal<T> {
LabeledFReal {
inner: -self.inner,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
impl<T: Scalar> ::core::ops::Neg for &LabeledFReal<T> {
type Output = LabeledFReal<T>;
#[inline]
fn neg(self) -> LabeledFReal<T> {
LabeledFReal {
inner: -&self.inner,
#[cfg(debug_assertions)]
gen_id: self.gen_id,
}
}
}
macro_rules! __lblfreal_scalar_lhs {
($scalar:ty) => {
impl ::core::ops::Add<LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn add(self, rhs: LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self + rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
impl ::core::ops::Add<&LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn add(self, rhs: &LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self + &rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
impl ::core::ops::Sub<LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn sub(self, rhs: LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self - rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
impl ::core::ops::Sub<&LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn sub(self, rhs: &LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self - &rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
impl ::core::ops::Mul<LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn mul(self, rhs: LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self * rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
impl ::core::ops::Mul<&LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn mul(self, rhs: &LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self * &rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
impl ::core::ops::Div<LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn div(self, rhs: LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self / rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
impl ::core::ops::Div<&LabeledFReal<$scalar>> for $scalar {
type Output = LabeledFReal<$scalar>;
#[inline]
fn div(self, rhs: &LabeledFReal<$scalar>) -> LabeledFReal<$scalar> {
LabeledFReal {
inner: self / &rhs.inner,
#[cfg(debug_assertions)]
gen_id: rhs.gen_id,
}
}
}
};
}
__lblfreal_scalar_lhs!(f64);
__lblfreal_scalar_lhs!(f32);