Skip to content

Commit d1cfde7

Browse files
authored
Provide alternate API for normal distribution functions, deprecate existing API (#397)
* Provide alternate API for normal distribution functions, deprecate existing API * Address review on deprecated, remove UT, change to alias
1 parent 1bcb9a5 commit d1cfde7

2 files changed

Lines changed: 63 additions & 26 deletions

File tree

source/mir/ediff.d

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ unittest
169169
f2.getDerivative!(["strike"]) * fc.getDerivative!(["strike", "barrier"]));
170170

171171
/// normalDistribution
172-
import mir.math.func.normal: constantNormalDistribution = normalDistribution, normalProbabilityDensity;
173-
assert(barrier.powi!2.normalDistribution.getFunctionValue == constantNormalDistribution(13.0 ^^ 2));
174-
assert(barrier.powi!2.normalDistribution.getDerivative!(["barrier"]) == normalProbabilityDensity(13.0 ^^ 2) * (2 * 13));
172+
import mir.math.func.normal: constantNormalCDF = normalCDF, normalPDF;
173+
assert(barrier.powi!2.normalCDF.getFunctionValue == constantNormalCDF(13.0 ^^ 2));
174+
assert(barrier.powi!2.normalCDF.getDerivative!(["barrier"]) == normalPDF(13.0 ^^ 2) * (2 * 13));
175175
}
176176

177177
import mir.algorithm.iteration: uniq;
@@ -897,10 +897,10 @@ auto sqrt(T)(const T value)
897897
return Sqrt!T(value);
898898
}
899899

900-
private template NormalDistribution(T)
900+
private template NormalCDF(T)
901901
{
902902
@Dependencies!T
903-
struct NormalDistribution
903+
struct NormalCDF
904904
{
905905
/// Square root argument function
906906
T value;
@@ -911,9 +911,9 @@ private template NormalDistribution(T)
911911
static if (Dependencies!(typeof(this)).containsAll(variables))
912912
auto getDerivative() const @property
913913
{
914-
import mir.math.func.normal: normalDistribution, SQRT2PIINV;
914+
import mir.math.func.normal: normalCDF, SQRT2PIINV;
915915
static if (variables.length == 0)
916-
return normalDistribution(value.getFunctionValue!strict);
916+
return normalCDF(value.getFunctionValue!strict);
917917
else
918918
return (SQRT2PIINV.Const * Powi!(2, T)(value, -0.5).exp * value.derivativeOf!(variables[0])).getDerivative!(variables[1 .. $], strict);
919919
}
@@ -931,8 +931,17 @@ Constructs the cumulative normal distribution function of the expression
931931
Params:
932932
value = expression
933933
+/
934-
auto normalDistribution(T)(const T value)
934+
deprecated("normalDistribution renamed, use normalCDF instead")
935+
alias normalDistribution = normalCDF;
936+
937+
/++
938+
Constructs the cumulative normal distribution function of the expression
939+
940+
Params:
941+
value = expression
942+
+/
943+
auto normalCDF(T)(const T value)
935944
if (is(T == struct))
936945
{
937-
return NormalDistribution!T(value);
946+
return NormalCDF!T(value);
938947
}

source/mir/math/func/normal.d

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,22 @@ import mir.math.common;
2525
@safe pure nothrow @nogc:
2626

2727
///
28-
T normalProbabilityDensity(T)(const T z)
28+
deprecated("normalProbabilityDensity renamed, use normalPDF instead")
29+
alias normalProbabilityDensity = normalPDF;
30+
31+
///
32+
T normalPDF(T)(const T z)
2933
if (isFloatingPoint!T)
3034
{
3135
import mir.math.common: sqrt, exp;
3236
return T(SQRT2PIINV) * exp(z * z * -0.5);
3337
}
3438

3539
/// ditto
36-
T normalProbabilityDensity(T)(const T x, const T mean, const T stdDev)
40+
T normalPDF(T)(const T x, const T mean, const T stdDev)
3741
if (isFloatingPoint!T)
3842
{
39-
return normalProbabilityDensity((x - mean) / stdDev) / stdDev;
43+
return normalPDF((x - mean) / stdDev) / stdDev;
4044
}
4145

4246
/++
@@ -56,7 +60,27 @@ $(LINK http://www.netlib.org/cephes/ldoubdoc.html),
5660
G. Marsaglia, "Evaluating the Normal Distribution",
5761
Journal of Statistical Software <b>11</b>, (July 2004).
5862
+/
59-
T normalDistribution(T)(const T a)
63+
deprecated("normalDistribution renamed, use normalCDF instead")
64+
alias normalDistribution = normalCDF;
65+
66+
/++
67+
Computes the normal distribution cumulative distribution function (CDF).
68+
The normal (or Gaussian, or bell-shaped) distribution is
69+
defined as:
70+
normalDist(x) = 1/$(SQRT) &pi; $(INTEGRAL -$(INFINITY), x) exp( - $(POWER t, 2)/2) dt
71+
= 0.5 + 0.5 * erf(x/sqrt(2))
72+
= 0.5 * erfc(- x/sqrt(2))
73+
To maintain accuracy at high values of x, use
74+
normalCDF(x) = 1 - normalCDF(-x).
75+
Accuracy:
76+
Within a few bits of machine resolution over the entire
77+
range.
78+
References:
79+
$(LINK http://www.netlib.org/cephes/ldoubdoc.html),
80+
G. Marsaglia, "Evaluating the Normal Distribution",
81+
Journal of Statistical Software <b>11</b>, (July 2004).
82+
+/
83+
T normalCDF(T)(const T a)
6084
if (isFloatingPoint!T)
6185
{
6286
pragma(inline, false);
@@ -82,20 +106,24 @@ T normalDistribution(T)(const T a)
82106
}
83107

84108
/// ditto
85-
T normalDistribution(T)(const T x, const T mean, const T stdDev)
109+
T normalCDF(T)(const T x, const T mean, const T stdDev)
86110
if (isFloatingPoint!T)
87111
{
88-
return normalDistribution((x - mean) / stdDev);
112+
return normalCDF((x - mean) / stdDev);
89113
}
90114

91115
version(mir_test)
92116
@safe unittest
93117
{
94-
assert(fabs(normalDistribution(1.0L) - (0.841344746068543))< 0.0000000000000005);
118+
assert(fabs(normalCDF(1.0L) - (0.841344746068543))< 0.0000000000000005);
95119
}
96120

97121
///
98-
T normalDistributionInverse(T)(const T p)
122+
deprecated("normalDistributionInverse renamed, use normalInvCDF instead")
123+
alias normalDistributionInverse = normalInvCDF;
124+
125+
///
126+
T normalInvCDF(T)(const T p)
99127
in {
100128
assert(p >= 0 && p <= 1, "Domain error");
101129
}
@@ -152,10 +180,10 @@ do
152180
}
153181

154182
/// ditto
155-
T normalDistributionInverse(T)(const T p, const T mean, const T stdDev)
183+
T normalInvCDF(T)(const T p, const T mean, const T stdDev)
156184
if (isFloatingPoint!T)
157185
{
158-
return normalDistributionInverse(p) * stdDev + mean;
186+
return normalInvCDF(p) * stdDev + mean;
159187
}
160188

161189
///
@@ -165,17 +193,17 @@ version(mir_test)
165193
import std.math: feqrel;
166194
// TODO: Use verified test points.
167195
// The values below are from Excel 2003.
168-
assert(fabs(normalDistributionInverse(0.001) - (-3.09023230616779))< 0.00000000000005);
169-
assert(fabs(normalDistributionInverse(1e-50) - (-14.9333375347885))< 0.00000000000005);
170-
assert(feqrel(normalDistributionInverse(0.999L), -normalDistributionInverse(0.001L)) > real.mant_dig-6);
196+
assert(fabs(normalInvCDF(0.001) - (-3.09023230616779))< 0.00000000000005);
197+
assert(fabs(normalInvCDF(1e-50) - (-14.9333375347885))< 0.00000000000005);
198+
assert(feqrel(normalInvCDF(0.999L), -normalInvCDF(0.001L)) > real.mant_dig-6);
171199

172200
// Excel 2003 gets all the following values wrong!
173-
assert(normalDistributionInverse(0.0) == -real.infinity);
174-
assert(normalDistributionInverse(1.0) == real.infinity);
175-
assert(normalDistributionInverse(0.5) == 0);
201+
assert(normalInvCDF(0.0) == -real.infinity);
202+
assert(normalInvCDF(1.0) == real.infinity);
203+
assert(normalInvCDF(0.5) == 0);
176204
// (Excel 2003 returns norminv(p) = -30 for all p < 1e-200).
177205
// The value tested here is the one the function returned in Jan 2006.
178-
real unknown1 = normalDistributionInverse(1e-250L);
206+
real unknown1 = normalInvCDF(1e-250L);
179207
assert( fabs(unknown1 -(-33.79958617269L) ) < 0.00000005);
180208
}
181209

0 commit comments

Comments
 (0)