///|
pub enum Distribution {
Uniform
Triangular
NormalApproximation
} derive(Debug, Eq)
///|
pub struct SamplingPolicy {
distribution : Distribution
sigma_factor : Double
seed : UInt
} derive(Debug)
///|
pub fn SamplingPolicy::new(
distribution? : Distribution = Uniform,
sigma_factor? : Double = 1.0,
seed? : UInt = 1U,
) -> SamplingPolicy {
if sigma_factor <= 0.0 {
abort("sigma_factor must be positive")
}
{ distribution, sigma_factor, seed }
}
///|
pub fn triangular_policy(seed? : UInt = 1U) -> SamplingPolicy {
SamplingPolicy::new(distribution=Triangular, seed~)
}
///|
pub fn normal_approximation_policy(seed? : UInt = 1U) -> SamplingPolicy {
SamplingPolicy::new(distribution=NormalApproximation, seed~)
}
///|
fn clamp_unit(value : Double) -> Double {
if value < 0.0 {
0.0
} else if value > 1.0 {
1.0
} else {
value
}
}
///|
pub fn sample_deviation(
policy : SamplingPolicy,
unit : Double,
tolerance : Double,
) -> Double {
if tolerance < 0.0 {
abort("tolerance must be non-negative")
}
let u = clamp_unit(unit)
match policy.distribution {
Uniform => (u * 2.0 - 1.0) * tolerance
Triangular =>
if u < 0.5 {
((2.0 * u).sqrt() - 1.0) * tolerance
} else {
(1.0 - (2.0 - 2.0 * u).sqrt()) * tolerance
}
NormalApproximation => {
// Twelve centered uniforms are a deterministic bounded normal proxy.
let centered = (u * 2.0 - 1.0) * 3.4641016151377544
centered * tolerance / policy.sigma_factor
}
}
}
///|
pub fn deterministic_uniform(seed : UInt) -> (UInt, Double) {
let next = seed * 1664525U + 1013904223U
(next, next.to_double() / 4294967295.0)
}
///|
pub struct ProcessCapability {
lower_spec : Double
upper_spec : Double
mean : Double
standard_deviation : Double
} derive(Debug)
///|
pub fn ProcessCapability::new(
lower_spec : Double,
upper_spec : Double,
mean : Double,
standard_deviation : Double,
) -> ProcessCapability {
if upper_spec < lower_spec {
abort("upper_spec must not be below lower_spec")
}
if standard_deviation <= 0.0 {
abort("standard_deviation must be positive")
}
{ lower_spec, upper_spec, mean, standard_deviation }
}
///|
pub fn ProcessCapability::cp(self : ProcessCapability) -> Double {
(self.upper_spec - self.lower_spec) / (6.0 * self.standard_deviation)
}
///|
pub fn ProcessCapability::cpu(self : ProcessCapability) -> Double {
(self.upper_spec - self.mean) / (3.0 * self.standard_deviation)
}
///|
pub fn ProcessCapability::cpl(self : ProcessCapability) -> Double {
(self.mean - self.lower_spec) / (3.0 * self.standard_deviation)
}
///|
pub fn ProcessCapability::cpk(self : ProcessCapability) -> Double {
let cpu = self.cpu()
let cpl = self.cpl()
if cpu < cpl {
cpu
} else {
cpl
}
}