rand_distr/multi/
mod.rs

1// Copyright 2025 Developers of the Rand project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Contains Multi-dimensional distributions.
10//!
11//! The trait [`MultiDistribution`] supports multi-dimensional sampling without
12//! allocating a [`Vec`](std::vec::Vec) for each sample.
13//! [`ConstMultiDistribution`] is an extension for distributions with constant
14//! dimension.
15//!
16//! Multi-dimensional distributions implement `MultiDistribution<T>` and (where
17//! the dimension is fixed) `ConstMultiDistribution<T>` for some scalar type
18//! `T`. They may also implement `Distribution<Vec<T>>` and (where the
19//! dimension, `N`, is fixed) `Distribution<[T; N]>`.
20
21use rand::Rng;
22
23/// A standard abstraction for distributions with multi-dimensional results
24///
25/// Implementations may also implement `Distribution<Vec<T>>`.
26pub trait MultiDistribution<T> {
27    /// The length of a sample (dimension of the distribution)
28    fn sample_len(&self) -> usize;
29
30    /// Sample a multi-dimensional result from the distribution
31    ///
32    /// The result is written to `output`. Implementations should assert that
33    /// `output.len()` equals the result of [`Self::sample_len`].
34    fn sample_to_slice<R: Rng + ?Sized>(&self, rng: &mut R, output: &mut [T]);
35}
36
37/// An extension of [`MultiDistribution`] for multi-dimensional distributions of fixed dimension
38///
39/// Implementations may also implement `Distribution<[T; SAMPLE_LEN]>`.
40pub trait ConstMultiDistribution<T>: MultiDistribution<T> {
41    /// Constant sample length (dimension of the distribution)
42    const SAMPLE_LEN: usize;
43}
44
45macro_rules! distribution_impl {
46    ($scalar:ident) => {
47        fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec<$scalar> {
48            use crate::multi::MultiDistribution;
49            let mut buf = vec![Default::default(); self.sample_len()];
50            self.sample_to_slice(rng, &mut buf);
51            buf
52        }
53    };
54}
55
56#[allow(unused)]
57macro_rules! const_distribution_impl {
58    ($scalar:ident) => {
59        fn sample<R: Rng + ?Sized>(
60            &self,
61            rng: &mut R,
62        ) -> [$scalar; <Self as crate::multi::MultiDistribution>::SAMPLE_LEN] {
63            use crate::multi::MultiDistribution;
64            let mut buf =
65                [Default::default(); <Self as crate::multi::MultiDistribution>::SAMPLE_LEN];
66            self.sample_to_slice(rng, &mut buf);
67            buf
68        }
69    };
70}
71
72pub use dirichlet::Dirichlet;
73
74mod dirichlet;