Correctness pass driven by a code review of the v0.3.0 release. No breaking changes to the public API.
loglik_binomial() and loglik_bernoulli() now use log1p(-p) instead of
log(val(1) - p). The old form broke hessian() through these likelihoods
because the intermediate -.value dispatch could not handle a dual-number
second operand. The new form dispatches cleanly through both value and
dual autodiff types and is more numerically stable as p approaches 1.loglik_negbinom() no longer silently strips the autodiff graph from the
r parameter. The old code called get_data(r) inside the binomial
coefficient sum, which meant dL/dr was wrong for any MLE over r.log_safe() now returns a gradient of 0 (rather than 1/eps) at elements
where the primal was clamped. Propagating a ~4.5e15 gradient from a region
where the primal is known to be wrong was actively misleading optimizers.lrt() now warns when the likelihood-ratio statistic is negative (which
happens when alt_ll < null_ll, typically due to reversed arguments or
failed optimization). Previously pchisq(negative, ...) silently returned
a p-value of 1.fit() gains an nobs argument. Passing it populates nobs(result) and
makes BIC(result) return a finite value instead of erroring on log(NULL).profile_loglik() now computes actual profile likelihood by re-optimizing
over the nuisance parameters at each grid value (warm-started from the MLE),
whenever the femtofit was produced by the current fit(). Previously it
silently returned a quadratic approximation based on the stored Hessian
(mathematically identical to the Wald interval in confint()). The
quadratic path remains as a fallback for legacy femtofit objects that
did not stash the wrapped objective.accumulate_grad(parent, grad_delta, sign) in R/value.R. The
scalar-broadcast gradient-reduction pattern that was copy-pasted through
+.value, -.value, *.value, /.value, and ^.value now lives in one
helper. About 60 lines of duplicated boilerplate removed with no change in
behavior (covered by existing tests).log1p_safe's three redundant S3 methods. It is now a one-line
alias for log1p(), which is already numerically stable and has autodiff
methods registered by femtograd. No deprecation warning emitted.loglik_weibull() that
documented an implementation path rejected during development.tests/testthat/test-fixes-v0_3_1.R with 13 regression tests, one per
fix, each documenting the exact pre-fix behavior it guards against.Initial statistical-inference release. See git history for details.