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
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) 2020-2022  David Sorokin <david.sorokin@gmail.com>, based in Yoshkar-Ola, Russia
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use std::rc::Rc;

use crate::simulation::parameter::*;

/// Computation that generates a new random number distributed uniformly.
#[inline]
pub fn random_uniform_parameter(min: f64, max: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_uniform(min, max))
    })
}

/// Computation that generates a new integer random number distributed uniformly.
#[inline]
pub fn random_int_uniform_parameter(min: isize, max: isize) -> impl Parameter<Item = isize> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_int_uniform(min, max))
    })
}

/// Computation that generates a new random number from the triangular distribution.
#[inline]
pub fn random_triangular_parameter(min: f64, median: f64, max: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_triangular(min, median, max))
    })
}

/// Computation that generates a new random number distributed normally.
#[inline]
pub fn random_normal_parameter(mu: f64, nu: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_normal(mu, nu))
    })
}

/// Computation that generates a new random number distributed lognormally.
#[inline]
pub fn random_log_normal_parameter(mu: f64, nu: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_log_normal(mu, nu))
    })
}

/// Computation that returns a new exponential random number with the specified mean
/// (the reciprocal of the rate).
#[inline]
pub fn random_exponential_parameter(mu: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_exponential(mu))
    })
}

/// Computation that returns a new Erlang random number with the specified scale
/// (the reciprocal of the rate) and integer shape.
#[inline]
pub fn random_erlang_parameter(scale: f64, shape: isize) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_erlang(scale, shape))
    })
}

/// Computation that returns a new Poisson random number with the specified mean.
#[inline]
pub fn random_poisson_parameter(mu: f64) -> impl Parameter<Item = isize> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_poisson(mu))
    })
}

/// Computation that returns a new binomial random number with the specified
/// probability and trials.
#[inline]
pub fn random_binomial_parameter(prob: f64, trials: isize) -> impl Parameter<Item = isize> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_binomial(prob, trials))
    })
}

/// Computation that returns `true` in case of success.
#[inline]
pub fn random_true_parameter(prob: f64) -> impl Parameter<Item = bool> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        let x = gen.random_uniform(0.0, 1.0);
        Result::Ok(x <= prob)
    })
}

/// Computation that returns `false` in case of success.
#[inline]
pub fn random_false_parameter(prob: f64) -> impl Parameter<Item = bool> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        let x = gen.random_uniform(0.0, 1.0);
        Result::Ok(x > prob)
    })
}

/// Computation that returns a new random number from the Gamma distribution.
#[inline]
pub fn random_gamma_parameter(kappa: f64, theta: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_gamma(kappa, theta))
    })
}

/// Computation that returns a new random number from the Beta distribution.
#[inline]
pub fn random_beta_parameter(alpha: f64, beta: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_beta(alpha, beta))
    })
}

/// Computation that returns a new random number from the Weibull distribution.
#[inline]
pub fn random_weibull_parameter(alpha: f64, beta: f64) -> impl Parameter<Item = f64> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_weibull(alpha, beta))
    })
}

/// Computation that returns a new random value from the specified discrete distribution.
#[inline]
pub fn random_discrete_parameter<T: Clone>(dpdf: Rc<Vec<(T, f64)>>) -> impl Parameter<Item = T> + Clone {
    cons_parameter(move |r| {
        let gen = &r.generator;
        Result::Ok(gen.random_discrete(&dpdf).clone())
    })
}