The OpenD Programming Language

1 /++
2 This module contains algorithms for the continuous $(LINK2 https://en.wikipedia.org/wiki/Continuous_uniform_distribution, Uniform Distribution).
3 
4 License: $(HTTP www.apache.org/licenses/LICENSE-2.0, Apache-2.0)
5 
6 Authors: John Michael Hall
7 
8 Copyright: 2022-3 Mir Stat Authors.
9 
10 +/
11 
12 module mir.stat.distribution.uniform;
13 
14 import mir.internal.utility: isFloatingPoint;
15 
16 /++
17 Computes the uniform probability density function (PDF).
18 
19 Params:
20     x = value to evaluate PDF
21     lower = lower bound
22     upper = upper bound
23 
24 See_also:
25     $(LINK2 https://en.wikipedia.org/wiki/Continuous_uniform_distribution, Uniform Distribution)
26 +/
27 @safe pure nothrow @nogc
28 T uniformPDF(T)(const T x, const T lower = 0, const T upper = 1)
29     if (isFloatingPoint!T)
30     in (x >= lower, "x must be greater than or equal to lower bound")
31     in (x <= upper, "x must be less than or equal to upper bound")
32     in (lower < upper, "lower must be less than upper")
33 {
34     return 1.0L / (upper - lower);
35 }
36 
37 ///
38 version(mir_stat_test)
39 @safe pure nothrow @nogc
40 unittest {
41     import mir.math.common: approxEqual;
42     assert(0.5.uniformPDF == 1);
43     assert(0.5.uniformPDF(0.0, 1.5).approxEqual(2.0 / 3));
44     assert(2.5.uniformPDF(1.0, 3.0).approxEqual(0.5));
45 }
46 
47 /++
48 Computes the uniform cumulative distribution function (CDF).
49 
50 Params:
51     x = value to evaluate CDF
52     lower = lower bound
53     upper = upper bound
54 
55 See_also:
56     $(LINK2 https://en.wikipedia.org/wiki/Continuous_uniform_distribution, Uniform Distribution)
57 +/
58 @safe pure nothrow @nogc
59 T uniformCDF(T)(const T x, const T lower = 0, const T upper = 1)
60     if (isFloatingPoint!T)
61     in (x >= lower, "x must be greater than or equal to lower bound")
62     in (x <= upper, "x must be less than or equal to upper bound")
63     in (lower < upper, "lower must be less than upper")
64 {
65     return (x - lower) / (upper - lower);
66 }
67 
68 ///
69 version(mir_stat_test)
70 @safe pure nothrow @nogc
71 unittest {
72     import mir.math.common: approxEqual;
73     assert(0.5.uniformCDF == 0.5);
74     assert(0.5.uniformCDF(0.0, 1.5).approxEqual(1.0 / 3));
75     assert(2.5.uniformCDF(1.0, 3.0).approxEqual(3.0 / 4));
76 }
77 
78 /++
79 Computes the uniform complementary cumulative distribution function (CCDF).
80 
81 Params:
82     x = value to evaluate CCDF
83     lower = lower bound
84     upper = upper bound
85 
86 See_also:
87     $(LINK2 https://en.wikipedia.org/wiki/Continuous_uniform_distribution, Uniform Distribution)
88 +/
89 @safe pure nothrow @nogc
90 T uniformCCDF(T)(const T x, const T lower = 0, const T upper = 1)
91     if (isFloatingPoint!T)
92     in (x >= lower, "x must be greater than or equal to lower bound")
93     in (x <= upper, "x must be less than or equal to upper bound")
94     in (lower < upper, "lower must be less than upper")
95 {
96     return (upper - x) / (upper - lower);
97 }
98 
99 ///
100 version(mir_stat_test)
101 @safe pure nothrow @nogc
102 unittest {
103     import mir.math.common: approxEqual;
104     assert(0.5.uniformCCDF == 0.5);
105     assert(0.5.uniformCCDF(0.0, 1.5).approxEqual(2.0 / 3));
106     assert(2.5.uniformCCDF(1.0, 3.0).approxEqual(1.0 / 4));
107 }
108 
109 /++
110 Computes the uniform inverse cumulative distribution function (InvCDF)
111 
112 Params:
113     p = value to evaluate InvCDF
114     lower = lower bound
115     upper = upper bound
116 
117 See_also:
118     $(LINK2 https://en.wikipedia.org/wiki/Continuous_uniform_distribution, Uniform Distribution)
119 +/
120 @safe pure nothrow @nogc
121 T uniformInvCDF(T)(const T p, const T lower = 0, const T upper = 1)
122     if (isFloatingPoint!T)
123     in (p >= 0, "p must be greater than or equal to 0")
124     in (p <= 1, "p must be less than or equal to 1")
125     in (lower < upper, "lower must be less than upper")
126 {
127     return lower + p * (upper - lower);
128 }
129 
130 ///
131 version(mir_stat_test)
132 @safe pure nothrow @nogc
133 unittest {
134     import mir.math.common: approxEqual;
135     assert(0.5.uniformInvCDF == 0.5);
136     assert((1.0 / 3).uniformInvCDF(0.0, 1.5).approxEqual(0.5));
137     assert((3.0 / 4).uniformInvCDF(1.0, 3.0).approxEqual(2.5));
138 }
139 
140 /++
141 Computes the uniform log probability density function (LPDF)
142 
143 Params:
144     x = value to evaluate LPDF
145     lower = lower bound
146     upper = upper bound
147 
148 See_also:
149     $(LINK2 https://en.wikipedia.org/wiki/Continuous_uniform_distribution, Uniform Distribution)
150 +/
151 @safe pure nothrow @nogc
152 T uniformLPDF(T)(const T x, const T lower = 0, const T upper = 1)
153     if (isFloatingPoint!T)
154     in (x >= lower, "x must be greater than or equal to lower bound")
155     in (x <= upper, "x must be less than or equal to upper bound")
156     in (lower < upper, "lower must be less than upper")
157 {
158     import mir.math.common: log;
159 
160     return -log(upper - lower);
161 }
162 
163 ///
164 version(mir_stat_test)
165 @safe pure nothrow @nogc
166 unittest {
167     import mir.math.common: approxEqual, log;
168     assert(0.5.uniformLPDF == 0);
169     assert(0.5.uniformLPDF(0.0, 1.5).approxEqual(-log(1.5)));
170     assert(1.5.uniformLPDF(1.0, 3.0).approxEqual(-log(2.0)));
171 }