diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim index e46dff2127..58014e503b 100644 --- a/lib/pure/stats.nim +++ b/lib/pure/stats.nim @@ -42,7 +42,7 @@ runnableExamples: template `~=`(a, b: float): bool = almostEqual(a, b) - var statistics: RunningStat ## Must be var + var statistics: RunningStat # must be var statistics.push(@[1.0, 2.0, 1.0, 4.0, 1.0, 4.0, 1.0, 2.0]) doAssert statistics.n == 8 doAssert statistics.mean() ~= 2.0 @@ -76,7 +76,7 @@ type proc clear*(s: var RunningStat) = ## Resets `s`. s.n = 0 - s.min = toBiggestFloat(int.high) + s.min = 0.0 s.max = 0.0 s.sum = 0.0 s.mom1 = 0.0 @@ -86,11 +86,14 @@ proc clear*(s: var RunningStat) = proc push*(s: var RunningStat, x: float) = ## Pushes a value `x` for processing. - if s.n == 0: s.min = x + if s.n == 0: + s.min = x + s.max = x + else: + if s.min > x: s.min = x + if s.max < x: s.max = x inc(s.n) # See Knuth TAOCP vol 2, 3rd edition, page 232 - if s.min > x: s.min = x - if s.max < x: s.max = x s.sum += x let n = toFloat(s.n) let delta = x - s.mom1 diff --git a/tests/stdlib/tstats.nim b/tests/stdlib/tstats.nim index 37240c8848..92a2ed8b80 100644 --- a/tests/stdlib/tstats.nim +++ b/tests/stdlib/tstats.nim @@ -1,46 +1,55 @@ -include stats +import std/stats -proc clean(x: float): float = - result = round(1.0e8*x).float * 1.0e-8 +proc `~=`(x, y: float): bool = + abs(x - y) < 10e-8 -var rs: RunningStat -rs.push(@[1.0, 2.0, 1.0, 4.0, 1.0, 4.0, 1.0, 2.0]) -doAssert(rs.n == 8) -doAssert(clean(rs.mean) == 2.0) -doAssert(clean(rs.variance()) == 1.5) -doAssert(clean(rs.varianceS()) == 1.71428571) -doAssert(clean(rs.skewness()) == 0.81649658) -doAssert(clean(rs.skewnessS()) == 1.01835015) -doAssert(clean(rs.kurtosis()) == -1.0) -doAssert(clean(rs.kurtosisS()) == -0.7000000000000001) +template main() = + var rs: RunningStat + rs.push(@[1.0, 2.0, 1.0, 4.0, 1.0, 4.0, 1.0, 2.0]) + doAssert(rs.n == 8) + doAssert rs.mean ~= 2.0 + doAssert rs.variance() ~= 1.5 + doAssert rs.varianceS() ~= 1.71428571 + doAssert rs.skewness() ~= 0.81649658 + doAssert rs.skewnessS() ~= 1.01835015 + doAssert rs.kurtosis() ~= -1.0 + doAssert rs.kurtosisS() ~= -0.7000000000000001 -var rs1, rs2: RunningStat -rs1.push(@[1.0, 2.0, 1.0, 4.0]) -rs2.push(@[1.0, 4.0, 1.0, 2.0]) -let rs3 = rs1 + rs2 -doAssert(clean(rs3.mom2) == clean(rs.mom2)) -doAssert(clean(rs3.mom3) == clean(rs.mom3)) -doAssert(clean(rs3.mom4) == clean(rs.mom4)) -rs1 += rs2 -doAssert(clean(rs1.mom2) == clean(rs.mom2)) -doAssert(clean(rs1.mom3) == clean(rs.mom3)) -doAssert(clean(rs1.mom4) == clean(rs.mom4)) -rs1.clear() -rs1.push(@[1.0, 2.2, 1.4, 4.9]) -doAssert(rs1.sum == 9.5) -doAssert(rs1.mean() == 2.375) + var rs1, rs2: RunningStat + rs1.push(@[1.0, 2.0, 1.0, 4.0]) + rs2.push(@[1.0, 4.0, 1.0, 2.0]) + let rs3 = rs1 + rs2 + doAssert rs3.variance ~= rs.variance + doAssert rs3.skewness ~= rs.skewness + doAssert rs3.kurtosis ~= rs.kurtosis + rs1 += rs2 + doAssert rs1.variance ~= rs.variance + doAssert rs1.skewness ~= rs.skewness + doAssert rs1.kurtosis ~= rs.kurtosis + rs1.clear() + rs1.push(@[1.0, 2.2, 1.4, 4.9]) + doAssert(rs1.sum == 9.5) + doAssert(rs1.mean() == 2.375) -when not defined(cpu32): - # XXX For some reason on 32bit CPUs these results differ - var rr: RunningRegress - rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0]) - doAssert(rr.slope() == 0.9695585996955861) - doAssert(rr.intercept() == -0.03424657534246611) - doAssert(rr.correlation() == 0.9905100362239381) - var rr1, rr2: RunningRegress - rr1.push(@[0.0, 1.0], @[0.0, 1.0]) - rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0]) - let rr3 = rr1 + rr2 - doAssert(rr3.correlation() == rr.correlation()) - doAssert(clean(rr3.slope()) == clean(rr.slope())) - doAssert(clean(rr3.intercept()) == clean(rr.intercept())) \ No newline at end of file + when not defined(cpu32): + # XXX For some reason on 32bit CPUs these results differ + var rr: RunningRegress + rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0]) + doAssert(rr.slope() == 0.9695585996955861) + doAssert(rr.intercept() == -0.03424657534246611) + doAssert(rr.correlation() == 0.9905100362239381) + var rr1, rr2: RunningRegress + rr1.push(@[0.0, 1.0], @[0.0, 1.0]) + rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0]) + let rr3 = rr1 + rr2 + doAssert(rr3.correlation() == rr.correlation()) + doAssert rr3.slope() ~= rr.slope() + doAssert rr3.intercept() ~= rr.intercept() + + block: # bug #18718 + var rs: RunningStat + rs.push(-1.0) + doAssert rs.max == -1.0 + +static: main() +main()