1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//! Shared low-level numeric primitives used across estimators and metrics
//!
//! - [`matmul`](crate::math::matmul) provides `gemmkit`-backed matrix products with automatic
//! parallelism
//! - [`reduction`](crate::math::reduction) provides deterministic blocked parallel reductions
//! - [`distance`](crate::math::distance) holds the pairwise distance primitives and the
//! [`DistanceCalculationMetric`](crate::math::DistanceCalculationMetric) dispatcher
//!
//! It also hosts the tunable exp-reduction parallel gate used by the logistic-regression
//! log-loss.
//!
//! # What belongs here
//!
//! A function lives in `math` only if it meets 3 conditions. It is pure and stateless. It is
//! model-agnostic, so it encodes no single algorithm's policy. It is, or plausibly could be,
//! shared by more than one caller. Per-algorithm solvers live next to their model. Post-hoc
//! evaluation metrics live in [`crate::metrics`] and call these primitives. Trainable,
//! gradient-aware losses live in `neural_network::losses`.
//!
//! # Examples
//!
//! ```rust
//! use rustyml::math::{DistanceCalculationMetric, squared_euclidean_distance_row};
//! use ndarray::array;
//!
//! // Distance primitive plus the configurable metric dispatcher.
//! let v1 = array![1.0, 2.0];
//! let v2 = array![4.0, 6.0];
//! let sq = squared_euclidean_distance_row(&v1, &v2);
//! let d = DistanceCalculationMetric::Euclidean.distance(v1.view(), v2.view());
//! ```
/// `gemmkit`-backed matrix products with automatic parallelism.
/// Deterministic blocked parallel reductions.
/// Pairwise distance primitives and the [`DistanceCalculationMetric`] dispatcher.
pub use ;
/// Parallel gate for exp-heavy `f64` reductions (the logistic-regression log-loss). Below this
/// element count, the deterministic blocked fold cannot beat the serial sum.
///
/// Sits below the cheap-sum gate because each element costs an `exp` plus an `ln`.
///
/// The fold splits the range into [`reduction::DET_REDUCE_BLOCK`]-sized blocks, so a value below
/// 2 blocks gives 1 task and no parallelism at all. That floor is what fixes this constant, so it
/// is not runtime-tunable.
pub const EXP_REDUCE_MIN_ELEMS: usize = 32_768;