use crate::traits::Scalar;
use std::fmt;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
#[derive(Clone)]
pub struct FReal<T: Scalar> {
value: T,
derivative: T,
}
impl<T: Scalar> FReal<T> {
pub fn new(value: T, derivative: T) -> Self {
FReal { value, derivative }
}
pub fn constant(value: T) -> Self {
FReal {
value,
derivative: T::zero(),
}
}
#[inline]
pub fn value(&self) -> T {
self.value
}
#[inline]
pub fn set_value(&mut self, v: T) {
self.value = v;
}
#[inline]
pub fn derivative(&self) -> T {
self.derivative
}
#[inline]
pub fn set_derivative(&mut self, d: T) {
self.derivative = d;
}
}
impl<T: Scalar> From<T> for FReal<T> {
fn from(value: T) -> Self {
FReal::constant(value)
}
}
impl From<i32> for FReal<f64> {
fn from(value: i32) -> Self {
FReal::constant(value as f64)
}
}
impl From<i32> for FReal<f32> {
fn from(value: i32) -> Self {
FReal::constant(value as f32)
}
}
impl<T: Scalar> Add for FReal<T> {
type Output = FReal<T>;
#[inline]
fn add(self, rhs: FReal<T>) -> FReal<T> {
FReal {
value: self.value + rhs.value,
derivative: self.derivative + rhs.derivative,
}
}
}
impl<T: Scalar> Add for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn add(self, rhs: &FReal<T>) -> FReal<T> {
FReal {
value: self.value + rhs.value,
derivative: self.derivative + rhs.derivative,
}
}
}
impl<T: Scalar> Add<&FReal<T>> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn add(self, rhs: &FReal<T>) -> FReal<T> {
FReal {
value: self.value + rhs.value,
derivative: self.derivative + rhs.derivative,
}
}
}
impl<T: Scalar> Add<FReal<T>> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn add(self, rhs: FReal<T>) -> FReal<T> {
FReal {
value: self.value + rhs.value,
derivative: self.derivative + rhs.derivative,
}
}
}
impl<T: Scalar> Add<T> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn add(self, rhs: T) -> FReal<T> {
FReal {
value: self.value + rhs,
derivative: self.derivative,
}
}
}
impl<T: Scalar> Add<T> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn add(self, rhs: T) -> FReal<T> {
FReal {
value: self.value + rhs,
derivative: self.derivative,
}
}
}
impl Add<FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn add(self, rhs: FReal<f64>) -> FReal<f64> {
FReal {
value: self + rhs.value,
derivative: rhs.derivative,
}
}
}
impl Add<&FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn add(self, rhs: &FReal<f64>) -> FReal<f64> {
FReal {
value: self + rhs.value,
derivative: rhs.derivative,
}
}
}
impl Add<FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn add(self, rhs: FReal<f32>) -> FReal<f32> {
FReal {
value: self + rhs.value,
derivative: rhs.derivative,
}
}
}
impl Add<&FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn add(self, rhs: &FReal<f32>) -> FReal<f32> {
FReal {
value: self + rhs.value,
derivative: rhs.derivative,
}
}
}
impl<T: Scalar> Sub for FReal<T> {
type Output = FReal<T>;
#[inline]
fn sub(self, rhs: FReal<T>) -> FReal<T> {
FReal {
value: self.value - rhs.value,
derivative: self.derivative - rhs.derivative,
}
}
}
impl<T: Scalar> Sub for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn sub(self, rhs: &FReal<T>) -> FReal<T> {
FReal {
value: self.value - rhs.value,
derivative: self.derivative - rhs.derivative,
}
}
}
impl<T: Scalar> Sub<&FReal<T>> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn sub(self, rhs: &FReal<T>) -> FReal<T> {
FReal {
value: self.value - rhs.value,
derivative: self.derivative - rhs.derivative,
}
}
}
impl<T: Scalar> Sub<FReal<T>> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn sub(self, rhs: FReal<T>) -> FReal<T> {
FReal {
value: self.value - rhs.value,
derivative: self.derivative - rhs.derivative,
}
}
}
impl<T: Scalar> Sub<T> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn sub(self, rhs: T) -> FReal<T> {
FReal {
value: self.value - rhs,
derivative: self.derivative,
}
}
}
impl<T: Scalar> Sub<T> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn sub(self, rhs: T) -> FReal<T> {
FReal {
value: self.value - rhs,
derivative: self.derivative,
}
}
}
impl Sub<FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn sub(self, rhs: FReal<f64>) -> FReal<f64> {
FReal {
value: self - rhs.value,
derivative: -rhs.derivative,
}
}
}
impl Sub<&FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn sub(self, rhs: &FReal<f64>) -> FReal<f64> {
FReal {
value: self - rhs.value,
derivative: -rhs.derivative,
}
}
}
impl Sub<FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn sub(self, rhs: FReal<f32>) -> FReal<f32> {
FReal {
value: self - rhs.value,
derivative: -rhs.derivative,
}
}
}
impl Sub<&FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn sub(self, rhs: &FReal<f32>) -> FReal<f32> {
FReal {
value: self - rhs.value,
derivative: -rhs.derivative,
}
}
}
impl<T: Scalar> Mul for FReal<T> {
type Output = FReal<T>;
#[inline]
fn mul(self, rhs: FReal<T>) -> FReal<T> {
FReal {
value: self.value * rhs.value,
derivative: self.derivative * rhs.value + self.value * rhs.derivative,
}
}
}
impl<T: Scalar> Mul for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn mul(self, rhs: &FReal<T>) -> FReal<T> {
FReal {
value: self.value * rhs.value,
derivative: self.derivative * rhs.value + self.value * rhs.derivative,
}
}
}
impl<T: Scalar> Mul<&FReal<T>> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn mul(self, rhs: &FReal<T>) -> FReal<T> {
FReal {
value: self.value * rhs.value,
derivative: self.derivative * rhs.value + self.value * rhs.derivative,
}
}
}
impl<T: Scalar> Mul<FReal<T>> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn mul(self, rhs: FReal<T>) -> FReal<T> {
FReal {
value: self.value * rhs.value,
derivative: self.derivative * rhs.value + self.value * rhs.derivative,
}
}
}
impl<T: Scalar> Mul<T> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn mul(self, rhs: T) -> FReal<T> {
FReal {
value: self.value * rhs,
derivative: self.derivative * rhs,
}
}
}
impl<T: Scalar> Mul<T> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn mul(self, rhs: T) -> FReal<T> {
FReal {
value: self.value * rhs,
derivative: self.derivative * rhs,
}
}
}
impl Mul<FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn mul(self, rhs: FReal<f64>) -> FReal<f64> {
FReal {
value: self * rhs.value,
derivative: self * rhs.derivative,
}
}
}
impl Mul<&FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn mul(self, rhs: &FReal<f64>) -> FReal<f64> {
FReal {
value: self * rhs.value,
derivative: self * rhs.derivative,
}
}
}
impl Mul<FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn mul(self, rhs: FReal<f32>) -> FReal<f32> {
FReal {
value: self * rhs.value,
derivative: self * rhs.derivative,
}
}
}
impl Mul<&FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn mul(self, rhs: &FReal<f32>) -> FReal<f32> {
FReal {
value: self * rhs.value,
derivative: self * rhs.derivative,
}
}
}
impl<T: Scalar> Div for FReal<T> {
type Output = FReal<T>;
#[inline]
fn div(self, rhs: FReal<T>) -> FReal<T> {
let inv_b = T::one() / rhs.value;
FReal {
value: self.value * inv_b,
derivative: (self.derivative * rhs.value - self.value * rhs.derivative) * inv_b * inv_b,
}
}
}
impl<T: Scalar> Div for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn div(self, rhs: &FReal<T>) -> FReal<T> {
let inv_b = T::one() / rhs.value;
FReal {
value: self.value * inv_b,
derivative: (self.derivative * rhs.value - self.value * rhs.derivative) * inv_b * inv_b,
}
}
}
impl<T: Scalar> Div<&FReal<T>> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn div(self, rhs: &FReal<T>) -> FReal<T> {
let inv_b = T::one() / rhs.value;
FReal {
value: self.value * inv_b,
derivative: (self.derivative * rhs.value - self.value * rhs.derivative) * inv_b * inv_b,
}
}
}
impl<T: Scalar> Div<FReal<T>> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn div(self, rhs: FReal<T>) -> FReal<T> {
let inv_b = T::one() / rhs.value;
FReal {
value: self.value * inv_b,
derivative: (self.derivative * rhs.value - self.value * rhs.derivative) * inv_b * inv_b,
}
}
}
impl<T: Scalar> Div<T> for FReal<T> {
type Output = FReal<T>;
#[inline]
fn div(self, rhs: T) -> FReal<T> {
let inv = T::one() / rhs;
FReal {
value: self.value * inv,
derivative: self.derivative * inv,
}
}
}
impl<T: Scalar> Div<T> for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn div(self, rhs: T) -> FReal<T> {
let inv = T::one() / rhs;
FReal {
value: self.value * inv,
derivative: self.derivative * inv,
}
}
}
impl Div<FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn div(self, rhs: FReal<f64>) -> FReal<f64> {
let inv = 1.0 / rhs.value;
FReal {
value: self * inv,
derivative: -self * rhs.derivative * inv * inv,
}
}
}
impl Div<&FReal<f64>> for f64 {
type Output = FReal<f64>;
#[inline]
fn div(self, rhs: &FReal<f64>) -> FReal<f64> {
let inv = 1.0 / rhs.value;
FReal {
value: self * inv,
derivative: -self * rhs.derivative * inv * inv,
}
}
}
impl Div<FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn div(self, rhs: FReal<f32>) -> FReal<f32> {
let inv = 1.0 / rhs.value;
FReal {
value: self * inv,
derivative: -self * rhs.derivative * inv * inv,
}
}
}
impl Div<&FReal<f32>> for f32 {
type Output = FReal<f32>;
#[inline]
fn div(self, rhs: &FReal<f32>) -> FReal<f32> {
let inv = 1.0 / rhs.value;
FReal {
value: self * inv,
derivative: -self * rhs.derivative * inv * inv,
}
}
}
impl<T: Scalar> Neg for FReal<T> {
type Output = FReal<T>;
#[inline]
fn neg(self) -> FReal<T> {
FReal {
value: -self.value,
derivative: -self.derivative,
}
}
}
impl<T: Scalar> Neg for &FReal<T> {
type Output = FReal<T>;
#[inline]
fn neg(self) -> FReal<T> {
FReal {
value: -self.value,
derivative: -self.derivative,
}
}
}
impl<T: Scalar> AddAssign for FReal<T> {
fn add_assign(&mut self, rhs: FReal<T>) {
self.value = self.value + rhs.value;
self.derivative = self.derivative + rhs.derivative;
}
}
impl<T: Scalar> AddAssign<&FReal<T>> for FReal<T> {
fn add_assign(&mut self, rhs: &FReal<T>) {
self.value = self.value + rhs.value;
self.derivative = self.derivative + rhs.derivative;
}
}
impl<T: Scalar> AddAssign<T> for FReal<T> {
fn add_assign(&mut self, rhs: T) {
self.value = self.value + rhs;
}
}
impl<T: Scalar> SubAssign for FReal<T> {
fn sub_assign(&mut self, rhs: FReal<T>) {
self.value = self.value - rhs.value;
self.derivative = self.derivative - rhs.derivative;
}
}
impl<T: Scalar> SubAssign<&FReal<T>> for FReal<T> {
fn sub_assign(&mut self, rhs: &FReal<T>) {
self.value = self.value - rhs.value;
self.derivative = self.derivative - rhs.derivative;
}
}
impl<T: Scalar> SubAssign<T> for FReal<T> {
fn sub_assign(&mut self, rhs: T) {
self.value = self.value - rhs;
}
}
impl<T: Scalar> MulAssign for FReal<T> {
fn mul_assign(&mut self, rhs: FReal<T>) {
let new_deriv = self.derivative * rhs.value + self.value * rhs.derivative;
self.value = self.value * rhs.value;
self.derivative = new_deriv;
}
}
impl<T: Scalar> MulAssign<&FReal<T>> for FReal<T> {
fn mul_assign(&mut self, rhs: &FReal<T>) {
let new_deriv = self.derivative * rhs.value + self.value * rhs.derivative;
self.value = self.value * rhs.value;
self.derivative = new_deriv;
}
}
impl<T: Scalar> MulAssign<T> for FReal<T> {
fn mul_assign(&mut self, rhs: T) {
self.value = self.value * rhs;
self.derivative = self.derivative * rhs;
}
}
impl<T: Scalar> DivAssign for FReal<T> {
fn div_assign(&mut self, rhs: FReal<T>) {
let inv_b = T::one() / rhs.value;
self.derivative =
(self.derivative * rhs.value - self.value * rhs.derivative) * inv_b * inv_b;
self.value *= inv_b;
}
}
impl<T: Scalar> DivAssign<&FReal<T>> for FReal<T> {
fn div_assign(&mut self, rhs: &FReal<T>) {
let inv_b = T::one() / rhs.value;
self.derivative =
(self.derivative * rhs.value - self.value * rhs.derivative) * inv_b * inv_b;
self.value *= inv_b;
}
}
impl<T: Scalar> DivAssign<T> for FReal<T> {
fn div_assign(&mut self, rhs: T) {
let inv = T::one() / rhs;
self.value *= inv;
self.derivative *= inv;
}
}
impl<T: Scalar> PartialEq for FReal<T> {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl<T: Scalar> PartialEq<T> for FReal<T> {
fn eq(&self, other: &T) -> bool {
self.value == *other
}
}
impl<T: Scalar> PartialOrd for FReal<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl<T: Scalar> PartialOrd<T> for FReal<T> {
fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
self.value.partial_cmp(other)
}
}
impl<T: Scalar> fmt::Display for FReal<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value)
}
}
impl<T: Scalar> fmt::Debug for FReal<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "FReal({}, deriv={})", self.value, self.derivative)
}
}
impl<T: Scalar> Default for FReal<T> {
fn default() -> Self {
FReal::constant(T::zero())
}
}