%% $Id: moments.mercury,v 1.1 2001/07/29 15:25:39 doug Exp $
%% http://www.bagley.org/~doug/shootout/
%% from Fergus Henderson
:- module mytest.
:- interface.
:- import_module io.
:- pred main(io__state, io__state).
:- mode main(di, uo) is det.
:- implementation.
:- import_module array, string, float, math, int, list, require.
main -->
io__read_file_as_string(_Res, Contents),
{ Lines = string__words((pred('\n'::in) is semidet), Contents) },
{ Count = length(Lines) },
{ array__init(Count, 0.0, Array0) },
{ count_and_sum(Lines, 0, 0.0, Array0, _Count2, Sum, Array) },
{ Mean = Sum / float(Count) },
process(0, Count, Mean, 0.0, 0.0, 0.0, 0.0, Array).
:- pred count_and_sum(list(string), int, float, array(float),
int, float, array(float)).
:- mode count_and_sum(in, in, in, array_di, out, out, array_uo) is det.
count_and_sum([], Count, Sum, Array, Count, Sum, Array).
count_and_sum([L|Ls], Count0, Sum0, Array0, Count, Sum, Array) :-
(if string__to_float(L, V) then Val = V else error("float conversion")),
count_and_sum(Ls, Count0 + 1, Sum0 + Val, Array0^elem(Count0) := Val,
Count, Sum, Array).
:- pred process(int, int, float, float, float, float, float, array(float),
io__state, io__state).
:- mode process(in, in, in, in, in, in, in, array_di, di, uo) is det.
process(I, Count, Mean,
SumAbsDeviations, SumVariance, SumSkew, SumKurtosis, Array0) -->
(if { I < Count } then
{ Val = Array0 ^ elem(I) },
{ Dev = Val - Mean },
{ Dev2 = Dev * Dev },
{ Dev3 = Dev2 * Dev },
{ Dev4 = Dev2 * Dev2 },
process(I + 1, Count, Mean, SumAbsDeviations + abs(Dev),
SumVariance + Dev2, SumSkew + Dev3,
SumKurtosis + Dev4, Array0)
else
{
AverageDeviation = SumAbsDeviations / float(Count),
Variance = SumVariance / float(Count - 1),
StandardDeviation = sqrt(Variance),
(if Variance \= 0.0 then
Skew = SumSkew / (float(Count) * Variance *
StandardDeviation),
Kurtosis = (SumKurtosis / (float(Count) *
Variance * Variance)) - 3.0
else
Skew = 0.0,
Kurtosis = 0.0
),
Array = sort(Array0),
Mid = (Count//2),
Median = (if Count rem 2 = 1 then Array^elem(Mid)
else (Array^elem(Mid) + Array^elem(Mid - 1)) / 2.0)
},
format("n: %d\n", [i(Count)]),
format("median: %f\n", [f(Median)]),
format("mean: %f\n", [f(Mean)]),
format("average_deviation: %f\n", [f(AverageDeviation)]),
format("standard_deviation: %f\n", [f(StandardDeviation)]),
format("variance: %f\n", [f(Variance)]),
format("skew: %f\n", [f(Skew)]),
format("kurtosis: %f\n", [f(Kurtosis)])
).