Skip to main content

gam_models/gamlss/gaussian/
binomial_locscale_decl.rs

1// Real concern-organized submodule of the gamlss family stack.
2// Cross-module items are re-exported flat through the parent (`gamlss.rs`),
3// so `use super::*;` makes the sibling-concern symbols this module references
4// resolve through the parent namespace.
5use super::*;
6
7#[derive(Clone)]
8pub struct BinomialLocationScaleFamily {
9    pub y: Array1<f64>,
10    pub weights: Array1<f64>,
11    pub link_kind: InverseLink,
12    pub threshold_design: Option<DesignMatrix>,
13    pub log_sigma_design: Option<DesignMatrix>,
14    /// Resource policy threaded into PsiDesignMap construction (and any other
15    /// per-call materialization decision) made during exact-Newton joint psi
16    /// derivative evaluation. Defaults to `ResourcePolicy::default_library()`
17    /// when the family is built without an explicit policy.
18    pub policy: gam_runtime::resource::ResourcePolicy,
19}
20
21/// Both Binomial location-scale families plug into the unified
22/// [`LocationScaleJointPsiFamily`] trait with byte-identical thin delegations
23/// to inherent methods, differing only in the implementing type and its
24/// `LABEL` fragment; generate them from one template. The Binomial families do
25/// not thread the outer-row subsample (they run the full-data exact ψ path), so
26/// the trait's `subsample` argument is accepted and ignored here.
27macro_rules! impl_binomial_location_scale_joint_psi_family {
28    ($family:ty, $label:literal, $n_blocks:literal) => {
29        impl LocationScaleJointPsiFamily for $family {
30            const LABEL: &'static str = $label;
31            const PRIMARY_LABEL: &'static str = "threshold";
32            const PRIMARY_BLOCK: usize = Self::BLOCK_T;
33            const N_BLOCKS: usize = $n_blocks;
34
35            fn ws_n_obs(&self) -> usize {
36                self.y.len()
37            }
38
39            fn ws_policy(&self) -> &gam_runtime::resource::ResourcePolicy {
40                &self.policy
41            }
42
43            fn ws_exact_joint_dense_block_designs<'a>(
44                &'a self,
45                specs: Option<&'a [ParameterBlockSpec]>,
46            ) -> Result<Option<(Cow<'a, Array2<f64>>, Cow<'a, Array2<f64>>)>, String> {
47                self.exact_joint_dense_block_designs(specs)
48            }
49
50            fn ws_psi_direction(
51                &self,
52                block_states: &[ParameterBlockState],
53                derivative_blocks: &[Vec<crate::custom_family::CustomFamilyBlockPsiDerivative>],
54                psi_index: usize,
55                design_loc: &Array2<f64>,
56                design_scale: &Array2<f64>,
57                policy: &gam_runtime::resource::ResourcePolicy,
58            ) -> Result<Option<LocationScaleJointPsiDirection>, String> {
59                self.exact_newton_joint_psi_direction(
60                    block_states,
61                    derivative_blocks,
62                    psi_index,
63                    design_loc,
64                    design_scale,
65                    policy,
66                )
67            }
68
69            fn ws_psi_second_order_terms_from_parts(
70                &self,
71                block_states: &[ParameterBlockState],
72                derivative_blocks: &[Vec<crate::custom_family::CustomFamilyBlockPsiDerivative>],
73                psi_a: &LocationScaleJointPsiDirection,
74                psi_b: &LocationScaleJointPsiDirection,
75                design_loc: &Array2<f64>,
76                design_scale: &Array2<f64>,
77                subsample: Option<&[crate::outer_subsample::WeightedOuterRow]>,
78            ) -> Result<ExactNewtonJointPsiSecondOrderTerms, String> {
79                assert!(subsample.is_none());
80                self.exact_newton_joint_psisecond_order_terms_from_parts(
81                    block_states,
82                    derivative_blocks,
83                    psi_a,
84                    psi_b,
85                    design_loc,
86                    design_scale,
87                )
88            }
89
90            fn ws_psi_hessian_directional_from_parts(
91                &self,
92                block_states: &[ParameterBlockState],
93                psi_dir: &LocationScaleJointPsiDirection,
94                d_beta_flat: &Array1<f64>,
95                design_loc: &Array2<f64>,
96                design_scale: &Array2<f64>,
97                subsample: Option<&[crate::outer_subsample::WeightedOuterRow]>,
98            ) -> Result<Array2<f64>, String> {
99                assert!(subsample.is_none());
100                self.exact_newton_joint_psihessian_directional_derivative_from_parts(
101                    block_states,
102                    psi_dir,
103                    d_beta_flat,
104                    design_loc,
105                    design_scale,
106                )
107            }
108        }
109    };
110}
111
112impl_binomial_location_scale_joint_psi_family!(
113    BinomialLocationScaleFamily,
114    "BinomialLocationScaleFamily",
115    2
116);
117
118impl_binomial_location_scale_joint_psi_family!(
119    BinomialLocationScaleWiggleFamily,
120    "BinomialLocationScaleWiggleFamily",
121    3
122);
123
124pub(crate) type BinomialLocationScaleExactNewtonJointPsiWorkspace =
125    LocationScaleJointPsiWorkspace<BinomialLocationScaleFamily>;
126
127pub(crate) type BinomialLocationScaleWiggleExactNewtonJointPsiWorkspace =
128    LocationScaleJointPsiWorkspace<BinomialLocationScaleWiggleFamily>;