Numerical contracts
All core calculations use IEEE 754 f64. Results are finite unless a function explicitly represents an infinite loss or an endpoint log-odds transform. Computation is not arbitrary precision, and extreme values can saturate to endpoint probabilities.
Domain checks
| Quantity | Accepted domain |
|---|---|
| Probability | Finite closed interval [0,1] |
| Logit input | Strictly interior probability |
| Log-odds sigmoid input | Any value except NaN; infinities map to endpoints |
| Likelihood ratio | Finite and strictly positive |
| Beta parameters | Positive finite alpha/beta with a finite sum |
| Pool weights | Finite nonnegative values with positive total weight |
| Alpha / calibration slope | Finite and nonnegative |
| Utility | Finite; research cost also nonnegative |
| Samples | Nonempty and finite |
| Scenario/category sum | One within 1e-12 |
Accepted category-sum roundoff is normalized at construction. Mixture weights are normalized by their accepted total. Probability inputs themselves are not silently clipped. A positive-weight zero/one input to logit pooling is an error rather than an invented epsilon.
Stable paths
Bayesian updates use log odds for nondegenerate cases and handle zero likelihoods explicitly. An observation impossible under both weighted hypotheses is rejected. A stable sigmoid avoids overflowing exp by choosing a branch according to the sign of its input.
Poisson event probability uses expm1 to retain precision for a very small rate-duration product. Empirical CRPS sorts the data and evaluates adjacent gaps; it scales before subtraction when opposite-sign extremes would overflow an intermediate distance. Truly unrepresentable scores still return errors.
extern crate supercast;
use supercast::score::{brier_skill, empirical_crps};
let mut extremes = [-f64::MAX, f64::MAX];
assert_eq!(empirical_crps(&mut extremes, 0.0)?, f64::MAX / 2.0);
assert!(brier_skill(1.0, f64::from_bits(1)).is_err());
Ok::<(), supercast::Error>(())
Score conventions
Binary Brier is one-component and ranges from zero to one. Categorical Brier sums over categories and ranges from zero to two. Ranked probability score is unnormalized and ranges from zero to K-1. CRPS has the outcome’s units. Log loss uses natural logs and permits positive infinity for a confidently wrong endpoint.
brier_skill rejects a zero baseline and an unrepresentable ratio. A database evaluation with a zero baseline returns null relative skill while preserving absolute means and their difference. Nonfinite JSON loss is tagged, not silently replaced by null.
Precision limits
Counts above 2^53 cannot retain unit precision when converted to f64. Very small probabilities may underflow, and extreme sigmoid results can round to zero or one. Sequence and source IDs are not floating-point values. The data model uses integer UTC seconds for timestamps.
Numerical tolerance is not a modeling tolerance. A sum differing by 1e-13 from one may be accepted as roundoff; two overlapping scenarios remain invalid even if their weights numerically sum to one. The caller is responsible for that semantic distinction.
Tests cover analytic cases, symmetry and proper-score properties, independent quadratic CRPS comparison, extreme finite values, endpoint behavior, binning decomposition, and seeded bootstrap behavior. Passing them establishes specified numerical behavior within these contracts, not real-world forecast validity.