1 /** 2 * Normal Distribution 3 * 4 * Copyright: Based on the CEPHES math library, which is 5 * Copyright (C) 1994 Stephen L. Moshier (moshier@world.std.com). 6 * Authors: Stephen L. Moshier, ported to D by Don Clugston and David Nadlinger. Adopted to Mir by Ilya Yaroshenko. 7 */ 8 /++ 9 This module contains algorithms for the $(LINK2 https://en.wikipedia.org/wiki/Normal_distribution, Normal Distribution). 10 11 License: $(HTTP www.apache.org/licenses/LICENSE-2.0, Apache-2.0) 12 13 Authors: John Michael Hall 14 15 Copyright: 2022-3 Mir Stat Authors. 16 17 +/ 18 19 module mir.stat.distribution.normal; 20 21 /// 22 public import mir.math.func.normal: normalPDF, normalCDF, normalInvCDF; 23 24 import mir.internal.utility: isFloatingPoint; 25 26 /++ 27 Computes the normal complementary cumulative distribution function (CCDF) 28 29 Params: 30 x = value to evaluate CCDF 31 mean = mean 32 stdDev = standard deviation 33 34 See_also: 35 $(LINK2 https://en.wikipedia.org/wiki/Normal_distribution, Normal Distribution) 36 +/ 37 @safe pure nothrow @nogc 38 T normalCCDF(T)(const T x, const T mean, const T stdDev) 39 if (isFloatingPoint!T) 40 { 41 return normalCCDF((x - mean) / stdDev); 42 } 43 44 /// ditto 45 @safe pure nothrow @nogc 46 T normalCCDF(T)(const T a) 47 if (isFloatingPoint!T) 48 { 49 return normalCDF(-a); 50 } 51 52 /// 53 version(mir_stat_test) 54 @safe pure nothrow @nogc 55 unittest { 56 import mir.math.common: approxEqual; 57 58 assert(0.5.normalCCDF.approxEqual(1 - normalCDF(0.5))); 59 assert(0.5.normalCCDF(0, 1.5).approxEqual(1 - normalCDF(0.5, 0, 1.5))); 60 assert(1.5.normalCCDF(1, 3).approxEqual(1 - normalCDF(1.5, 1, 3))); 61 } 62 63 version(mir_stat_test) 64 @safe pure nothrow @nogc 65 unittest { 66 import mir.math.common: approxEqual; 67 68 assert((-3.0).normalCCDF.approxEqual(1 - normalCDF(-3.0))); 69 assert(3.0.normalCCDF.approxEqual(1 - normalCDF(3.0))); 70 assert((-7.0).normalCCDF(1, 4).approxEqual(1 - normalCDF(-7.0, 1, 4))); 71 assert(9.0.normalCCDF(1, 4).approxEqual(1 - normalCDF(9.0, 1, 4))); 72 } 73 74 version(mir_stat_test) 75 @safe pure nothrow @nogc 76 unittest { 77 import mir.math.common: approxEqual; 78 assert(normalCCDF(double.infinity).approxEqual(1 - normalCDF(double.infinity))); 79 assert(normalCCDF(-double.infinity).approxEqual(1 - normalCDF(-double.infinity))); 80 } 81 82 /++ 83 Computes the normal log probability density function (LPDF) 84 85 Params: 86 x = value to evaluate LPDF 87 mean = mean 88 stdDev = standard deviation 89 90 See_also: 91 $(LINK2 https://en.wikipedia.org/wiki/Normal_distribution, Normal Distribution) 92 +/ 93 @safe pure nothrow @nogc 94 T normalLPDF(T)(const T x, const T mean, const T stdDev) 95 if (isFloatingPoint!T) 96 { 97 import mir.math.common: log; 98 return normalLPDF((x - mean) / stdDev) - log(stdDev); 99 } 100 101 /// ditto 102 @safe pure nothrow @nogc 103 T normalLPDF(T)(const T x) 104 if (isFloatingPoint!T) 105 { 106 import mir.math.common: pow; 107 import mir.stat.constant: LOGSQRT2PI; 108 109 return -0.5 * pow(x, 2) - T(LOGSQRT2PI); 110 } 111 112 /// 113 version(mir_stat_test) 114 @safe pure nothrow @nogc 115 unittest { 116 import mir.math.common: approxEqual, log; 117 assert(0.5.normalLPDF.approxEqual(log(normalPDF(0.5)))); 118 assert(0.5.normalLPDF(0, 1.5).approxEqual(log(normalPDF(0.5, 0, 1.5)))); 119 assert(1.5.normalLPDF(1, 3).approxEqual(log(normalPDF(1.5, 1, 3)))); 120 }