I found this neat trick of calculating the mean and the standard deviation in one pass over the data. I wanted to have this working for float32
and float
. Again, I'm struggling to get this right with generic numbers.
module Seq =
let inline private avgVarianceReducer toFloat (count, oldM, oldS) x =
if count = 1 then
2, x, LanguagePrimitives.GenericZero
else
let meanFree = x - oldM
let newM = oldM + meanFree / (toFloat count)
count + 1, newM, oldS + meanFree * (x - newM)
let inline private avgVarianceWith toFloat source =
match source |> Seq.fold (avgVarianceReducer toFloat) (1, LanguagePrimitives.GenericZero, LanguagePrimitives.GenericZero) with
| 0, _, _ -> LanguagePrimitives.GenericZero, LanguagePrimitives.GenericZero
| 1, mean, _ -> mean, LanguagePrimitives.GenericZero
| n, mean, var -> mean, var / (n - 2 |> toFloat)
let avgVariance source = source |> avgVarianceWith float
let avgVariancef source = source |> avgVarianceWith float32
This works for both types, but I have the additional avgVariancef
plus I have to choose the right one when calling.
To me the central problem is the conversion to the right kind of float in avgVarianceReducer
which I solved by passing in the correct conversion funtion. I tried my way with op_Explicit
but failed.
Anybody have an idea for a more elegant solution?