C++ · Probability Metrics

Probability Metrics

#include <numkong/probability.hpp> 8.0.0-rc.1 · b1f866ab

Probability kernels target divergences directly instead of making you rebuild them from scalar loops.

nk_f32_t p[] = {0.2f, 0.3f, 0.5f}, q[] = {0.1f, 0.3f, 0.6f};
nk_f64_t kl_forward = 0, kl_reverse = 0, js_forward = 0, js_reverse = 0;

nk_kld_f32_best(p, q, 3, &kl_forward, capabilities, NULL);
nk_kld_f32_best(q, p, 3, &kl_reverse, capabilities, NULL);
assert(kl_forward != kl_reverse && "KLD is asymmetric");

nk_jsd_f32_best(p, q, 3, &js_forward, capabilities, NULL);
nk_jsd_f32_best(q, p, 3, &js_reverse, capabilities, NULL);
assert(js_forward == js_reverse && "JSD is symmetric");

These paths are useful once you move below f64. Naive implementations are usually dominated by repeated scalar transcendental calls and weak accumulation policy.

API

Functions

kldKullback-Leibler divergence: Σ pᵢ × log(pᵢ / qᵢ).
probability.hpp:32 ↗
template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::probability_result_t>
status_t kld(
    in_type_ const *p,
    in_type_ const *q,
    std::size_t d,
    result_type_ *r,
    nk_capability_t capabilities = default_capabilities(),
    nk_stream_t stream = nullptr) noexcept;
template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::probability_result_t, vector_of<in_type_> a_type_, vector_of<in_type_> b_type_>
expected<result_type_> kld(
    a_type_ const & a,
    b_type_ const & b,
    nk_capability_t capabilities = default_capabilities()) noexcept;

Kullback-Leibler divergence of two distributions with equal dimensions; unexpected_dimensions_k when they differ or either run is strided or ends mid-value.

Parameters

pinFirst probability distribution
qinSecond probability distribution
dinNumber of dimensions in input vectors
routPointer to output divergence value
capabilitiesinCapabilities to pick from, or zero for the C++ template
streaminNull on the CPU, or the stream of the device capabilities describes
jsdJensen-Shannon distance: √(½ × (KL(p‖m) + KL(q‖m))), where m = (p + q) / 2.
probability.hpp:68 ↗
template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::probability_result_t>
status_t jsd(
    in_type_ const *p,
    in_type_ const *q,
    std::size_t d,
    result_type_ *r,
    nk_capability_t capabilities = default_capabilities(),
    nk_stream_t stream = nullptr) noexcept;
template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::probability_result_t, vector_of<in_type_> a_type_, vector_of<in_type_> b_type_>
expected<result_type_> jsd(
    a_type_ const & a,
    b_type_ const & b,
    nk_capability_t capabilities = default_capabilities()) noexcept;

Jensen-Shannon divergence of two distributions, failing like the concept kld.

Parameters

pinFirst probability distribution
qinSecond probability distribution
dinNumber of dimensions in input vectors
routPointer to output distance value
capabilitiesinCapabilities to pick from, or zero for the C++ template
streaminNull on the CPU, or the stream of the device capabilities describes