libm3/src/statistics/Stat.m3


 Copyright (C) 1989, Digital Equipment Corporation           
 All rights reserved.                                        
 See the file COPYRIGHT for a full description.              

Last modified on Thu Nov 7 08:43:45 PST 1991 by kalsow modified on Wed Jun 20 01:46:13 1990 by muller

modified on Mon Nov 23 09:38:21 1987 by stolfi

MODULE Stat;

IMPORT Wr, Fmt, Math, Thread;

PROCEDURE Init (VAR s: T) =
  BEGIN
    WITH z = s DO
      z.num      := 0.0d+0;
      z.maximum  := 0.0;
      z.minimum  := 0.0;
      z.mean     := 0.0d+0;
      z.variance := 0.0d+0;
    END
  END Init;

PROCEDURE Accum (VAR s: T;  x: REAL) =
  VAR oldnum, tmp: LONGREAL;
  BEGIN
    WITH z = s DO
      IF z.num = 0.0d+0 THEN
        z.maximum := x;
        z.minimum := x
      ELSIF x > z.maximum THEN
        z.maximum := x
      ELSIF x < z.minimum THEN
        z.minimum := x
      END;
      oldnum := z.num;
      z.num := z.num + 1.0d+0;
      tmp := FLOAT (x, LONGREAL) - z.mean;
      z.mean := z.mean + tmp / z.num;
      z.variance := (z.variance + tmp * tmp / z.num) * oldnum / z.num;
    END;
  END Accum;

PROCEDURE Combine (READONLY r, s: T): T =
  VAR tmp: LONGREAL; t: T;
  BEGIN
    WITH z = t DO
      z.maximum := MAX (r.maximum, s.maximum);
      z.minimum := MIN (r.minimum, s.minimum);
      z.num := r.num + s.num;
      z.mean := (r.mean * r.num + s.mean * s.num) / z.num;
      tmp := r.mean - s.mean;
      z.variance := (r.variance * r.num + s.variance * s.num
                       + tmp * tmp * r.num * s.num / z.num) / z.num;
    END;
    RETURN t
  END Combine;

PROCEDURE Num (READONLY s: T): REAL =
  BEGIN
    RETURN FLOAT (s.num)
  END Num;

PROCEDURE Max (READONLY s: T): REAL =
  BEGIN
    RETURN s.maximum
  END Max;

PROCEDURE Min (READONLY s: T): REAL =
  BEGIN
    RETURN s.minimum
  END Min;

PROCEDURE Mean (READONLY s: T): REAL =
  BEGIN
    RETURN FLOAT (s.mean)
  END Mean;

PROCEDURE Var (READONLY s: T): REAL =
  BEGIN
    RETURN FLOAT (s.variance)
  END Var;

PROCEDURE SDev (READONLY s: T): REAL =
  BEGIN
    IF s.num = 0.0d+0 THEN RETURN 0.0 END;
    RETURN FLOAT (Math.sqrt (s.variance * s.num / (s.num - 1.0d+0)))
  END SDev;

PROCEDURE RMS (READONLY s: T): REAL =
  BEGIN
    IF s.num = 0.0d+0 THEN
      RETURN 0.0
    ELSE
      RETURN FLOAT (Math.sqrt (s.variance + s.mean * s.mean))
    END
  END RMS;

PROCEDURE Print (wr: Wr.T;  READONLY s: T) RAISES {Wr.Failure, Thread.Alerted}=
  BEGIN
    WITH z = s DO
      Wr.PutText (wr, "num = " & Fmt.Int (TRUNC (z.num)));
      IF z.num > 0.0d+0 THEN
        Wr.PutText (wr, " [ " & Fmt.Real (Min (s)) & " _ "
                       & Fmt.Real (Max (s)) & " ] mean = "
                       & Fmt.Real (Mean (s)));
        IF z.num >= 2.0d+0 THEN
          Wr.PutText (wr, "  dev = " & Fmt.Real (SDev (s)))
        END;
      END;
    END;
  END Print;

BEGIN
END Stat.