Skip to main content

gam_models/transformation_normal/
error.rs

1// ---------------------------------------------------------------------------
2// Typed errors
3// ---------------------------------------------------------------------------
4
5/// Typed errors emitted by the transformation-normal family pipeline.
6///
7/// Each variant carries a pre-formatted `reason` so `Display` is
8/// byte-equivalent to the original `format!(...)` strings the module used
9/// before the typed-error migration. The category split lets callers
10/// pattern-match on the failure kind (e.g. distinguish a degenerate
11/// covariate design from a non-finite intermediate) without parsing text.
12///
13/// Public/trait boundaries (e.g. `CustomFamily::evaluate`) still return
14/// `Result<_, String>`; the `From<TransformationNormalError> for String`
15/// impl below provides the shim so every typed error flushes through `?`
16/// or `.into()` at the boundary without per-callsite `.map_err`.
17#[derive(Debug, Clone)]
18pub enum TransformationNormalError {
19    /// Shape/length/dimension/contract violations on inputs to a routine
20    /// (e.g. response/covariate row mismatch, beta length mismatch,
21    /// wrong number of blocks, malformed configuration parameters).
22    InvalidInput { reason: String },
23    /// A required covariate design or weight configuration cannot support
24    /// the routine — empty design, zero total weight, residual variance
25    /// not representable, warm-start coefficients all non-finite.
26    DesignDegenerate { reason: String },
27    /// A numeric intermediate (response transform, derivative,
28    /// log-likelihood, weight, offset, gradient component, calibration
29    /// quantity) came out non-finite or non-positive where positive
30    /// finite is required.
31    NonFinite { reason: String },
32    /// The fitted monotone transform's derivative dropped to or below
33    /// zero, or the response endpoint ordering required by the latent
34    /// score (lower < h < upper) was not satisfied at evaluation time.
35    MonotonicityViolated { reason: String },
36    /// A numerical step that maps through the standard-normal CDF
37    /// (endpoint mass, log-difference, PIT probability, derivative
38    /// ratio) underflowed or became non-representable at the requested
39    /// arguments.
40    NumericalFailure { reason: String },
41}
42
43impl_reason_error_boilerplate! {
44    TransformationNormalError {
45        InvalidInput,
46        DesignDegenerate,
47        NonFinite,
48        MonotonicityViolated,
49        NumericalFailure,
50    }
51}
52
53impl From<crate::block_layout::block_count::BlockCountMismatch>
54    for TransformationNormalError
55{
56    fn from(
57        err: crate::block_layout::block_count::BlockCountMismatch,
58    ) -> TransformationNormalError {
59        TransformationNormalError::InvalidInput {
60            reason: err.message(),
61        }
62    }
63}