stat/distuv: fix Weibull LogProb and test function absEq
MODIFY
stat/distuv/general_test.go
stat/distuv/general_test.go
@@ -29,9 +29,17 @@ type UniProbDist interface {
}
func absEq(a, b float64) bool {
+ return absEqTol(a, b, 1e-14)
+}
+
+func absEqTol(a, b, tol float64) bool {
+ if math.IsNaN(a) || math.IsNaN(b) {
+ // NaN is not equal to anything.
+ return false
+ }
// This is expressed as the inverse to catch the
// case a = Inf and b = Inf of the same sign.
- return !(math.Abs(a-b) > 1e-14)
+ return !(math.Abs(a-b) > tol)
}
// TODO: Implement a better test for Quantile
@@ -39,11 +47,11 @@ func testDistributionProbs(t *testing.T, dist UniProbDist, name string, pts []un
for _, pt := range pts {
logProb := dist.LogProb(pt.loc)
if !absEq(logProb, pt.logProb) {
- t.Errorf("Log probability doesnt match for "+name+". Expected %v. Found %v", pt.logProb, logProb)
+ t.Errorf("Log probability doesnt match for "+name+" at %v. Expected %v. Found %v", pt.loc, pt.logProb, logProb)
}
prob := dist.Prob(pt.loc)
if !absEq(prob, pt.prob) {
- t.Errorf("Probability doesn't match for "+name+". Expected %v. Found %v", pt.prob, prob)
+ t.Errorf("Probability doesn't match for "+name+" at %v. Expected %v. Found %v", pt.loc, pt.prob, prob)
}
cumProb := dist.CDF(pt.loc)
if !absEq(cumProb, pt.cumProb) {

MODIFY
stat/distuv/weibull.go
stat/distuv/weibull.go
@@ -55,7 +55,7 @@ func (w Weibull) LogCDF(x float64) complex128 {
}
// LogProb computes the natural logarithm of the value of the probability
-// density function at x. Zero is returned if x is less than zero.
+// density function at x. -Inf is returned if x is less than zero.
//
// Special cases occur when x == 0, and the result depends on the shape
// parameter as follows:
@@ -64,6 +64,9 @@ func (w Weibull) LogCDF(x float64) complex128 {
// If K > 1, LogProb returns -Inf.
func (w Weibull) LogProb(x float64) float64 {
if x < 0 {
+ return math.Inf(-1)
+ }
+ if x == 0 && w.K == 1 {
return 0
}
return math.Log(w.K) - math.Log(w.Lambda) + (w.K-1)*(math.Log(x)-math.Log(w.Lambda)) - math.Pow(x/w.Lambda, w.K)

MODIFY
stat/distuv/weibull_test.go
stat/distuv/weibull_test.go
@@ -25,7 +25,7 @@ func TestHalfKStandardWeibullProb(t *testing.T) {
loc: -1,
prob: 0,
cumProb: 0,
- logProb: 0,
+ logProb: math.Inf(-1),
},
{
loc: 1,
@@ -50,13 +50,13 @@ func TestExponentialStandardWeibullProb(t *testing.T) {
loc: 0,
prob: 1,
cumProb: 0,
- logProb: math.Inf(1),
+ logProb: 0,
},
{
loc: -1,
prob: 0,
cumProb: 0,
- logProb: 0,
+ logProb: math.Inf(-1),
},
{
loc: 1,
@@ -87,7 +87,7 @@ func TestRayleighStandardWeibullProb(t *testing.T) {
loc: -1,
prob: 0,
cumProb: 0,
- logProb: 0,
+ logProb: math.Inf(-1),
},
{
loc: 1,
@@ -118,7 +118,7 @@ func TestFiveKStandardWeibullProb(t *testing.T) {
loc: -1,
prob: 0,
cumProb: 0,
- logProb: 0,
+ logProb: math.Inf(-1),
},
{
loc: 1,
@@ -149,7 +149,7 @@ func TestScaledUpHalfKStandardWeibullProb(t *testing.T) {
loc: -1,
prob: 0,
cumProb: 0,
- logProb: 0,
+ logProb: math.Inf(-1),
},
{
loc: 1,
@@ -180,7 +180,7 @@ func TestScaledDownHalfKStandardWeibullProb(t *testing.T) {
loc: -1,
prob: 0,
cumProb: 0,
- logProb: 0,
+ logProb: math.Inf(-1),
},
{
loc: 1,

stat/distuv: fix Weibull LogProb and test function absEq