use crate::error::{RillError, ensure_finite_target};
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SquaredError;
impl SquaredError {
pub const fn new() -> Self {
Self
}
pub fn loss(prediction: f64, target: f64) -> f64 {
let diff = prediction - target;
0.5 * diff * diff
}
pub fn gradient(prediction: f64, target: f64) -> f64 {
prediction - target
}
pub fn validate(prediction: f64, target: f64) -> Result<(), RillError> {
crate::error::ensure_finite("prediction", prediction)?;
ensure_finite_target(target)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn loss_at_zero_residual_is_zero() {
assert_eq!(SquaredError::loss(5.0, 5.0), 0.0);
}
#[test]
fn loss_value() {
assert!((SquaredError::loss(3.0, 1.0) - 2.0).abs() < 1e-12);
}
#[test]
fn gradient_sign() {
assert!((SquaredError::gradient(3.0, 1.0) - 2.0).abs() < 1e-12);
assert!((SquaredError::gradient(1.0, 3.0) + 2.0).abs() < 1e-12);
}
}