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;