gamlss_transform/transforms/
identity_positive.rs1use crate::{TargetTransform, TransformError, map_slice_into, validate_positive};
2
3#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
5pub struct IdentityPositive;
6
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
9pub struct IdentityPositiveState;
10
11impl TargetTransform for IdentityPositive {
12 type State = IdentityPositiveState;
13
14 fn fit(y: &[f64]) -> Result<Self::State, TransformError> {
15 validate_positive(y)?;
16 Ok(IdentityPositiveState)
17 }
18
19 #[inline(always)]
20 fn transform(_: &Self::State, y: f64) -> f64 {
21 y
22 }
23
24 #[inline(always)]
25 fn inverse(_: &Self::State, value: f64) -> f64 {
26 value
27 }
28
29 #[inline]
30 fn transform_slice(state: &Self::State, y: &[f64]) -> Result<Vec<f64>, TransformError> {
31 let mut out = vec![0.0; y.len()];
32 Self::transform_into(state, y, &mut out)?;
33 Ok(out)
34 }
35
36 #[inline]
37 fn transform_into(
38 state: &Self::State,
39 y: &[f64],
40 out: &mut [f64],
41 ) -> Result<(), TransformError> {
42 map_slice_into(y, out, validate_positive, |value| {
43 Self::transform(state, value)
44 })
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use crate::{IdentityPositive, TargetTransform, TransformError};
51
52 #[test]
53 fn rejects_non_positive_values() {
54 assert_eq!(
55 IdentityPositive::fit(&[-1.0]).unwrap_err(),
56 TransformError::NonPositiveValue
57 );
58 }
59
60 #[test]
61 fn leaves_positive_values_unchanged() {
62 let y = [1.0, 2.0];
63 let (state, transformed) = IdentityPositive::fit_transform(&y).unwrap();
64
65 assert_eq!(transformed, y);
66 assert_eq!(
67 IdentityPositive::inverse_slice(&state, &transformed).unwrap(),
68 y
69 );
70 }
71}