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}