use aegir::{Node, Identifier, Differentiable, ops::{Mul, OneSub, AddOne}};
use special_fun::FloatSpecial;
impl_unary!(
Gamma<F: FloatSpecial>, |x| { x.gamma() }, |self| {
use crate::fmt::{PreWrap, Expr::*};
match self.0.to_expr() {
Zero => Text(PreWrap {
text: "\u{221E}".to_string(),
needs_wrap: false,
}),
One => One,
Text(pw) => Text(PreWrap {
text: format!("\u{0393}({})", pw),
needs_wrap: false,
})
}
}
);
impl<N, I> Differentiable<I> for Gamma<N>
where
N: Clone + Differentiable<I>,
I: Identifier,
{
type Adjoint = Mul<Mul<N::Adjoint, DiGamma<N>>, Gamma<N>>;
fn adjoint(&self, target: I) -> Self::Adjoint {
self.0.adjoint(target).mul(DiGamma(self.0.clone())).mul(self.clone())
}
}
impl_unary!(
DiGamma<F: FloatSpecial>, |x| { x.digamma() }, |self| {
use crate::fmt::{PreWrap, Expr::*};
match self.0.to_expr() {
Zero => Text(PreWrap {
text: "\u{221E}".to_string(),
needs_wrap: false,
}),
One => One,
Text(pw) => Text(PreWrap {
text: format!("\u{03C8}({})", pw),
needs_wrap: false,
})
}
}
);
impl_unary!(
LogGamma<F: FloatSpecial>, |x| { x.loggamma() }, |self| {
use crate::fmt::{PreWrap, Expr::*};
match self.0.to_expr() {
Zero => Text(PreWrap {
text: "\u{221E}".to_string(),
needs_wrap: false,
}),
One => Zero,
Text(pw) => Text(PreWrap {
text: format!("ln\u{0393}({})", pw),
needs_wrap: false,
})
}
}
);
impl<N, I> Differentiable<I> for LogGamma<N>
where
N: Clone + Differentiable<I>,
I: Identifier,
{
type Adjoint = Mul<N::Adjoint, DiGamma<N>>;
fn adjoint(&self, target: I) -> Self::Adjoint {
self.0.adjoint(target).mul(DiGamma(self.0.clone()))
}
}
pub type Factorial<N> = Gamma<AddOne<N>>;
impl<N> Factorial<N> {
pub fn factorial(node: N) -> Self { Gamma(AddOne(node)) }
}
impl_unary!(
Erf<F: FloatSpecial>, |x| { x.erf() }, |self| {
use crate::fmt::{PreWrap, Expr::*};
match self.0.to_expr() {
Zero | One => One,
Text(pw) => Text(PreWrap {
text: format!("erf({})", pw),
needs_wrap: false,
})
}
}
);
impl<N> Erf<N> {
pub fn complement(self) -> OneSub<Self> { OneSub(self) }
}
pub type Erfc<N> = OneSub<Erf<N>>;
impl<N> Erfc<N> {
pub fn erfc(node: N) -> Erfc<N> { OneSub(Erf(node)) }
}