#lang racket/base
(struct statistics (time-dependant?
minimum
maximum
n
sum
sum-of-squares
dimension)
#:mutable)
(define (make-statistics time-dependant? time)
(statistics time-dependant? +inf.0 -inf.0 0 0.0 0.0 0))
(define (make-vector-statistics time-dependant? time dimension)
(statistics time-dependant?
(make-vector dimension +inf.0)
(make-vector dimension -inf.0)
0
(make-vector dimension 0.0)
(make-vector dimension 0.0)
dimension))
(define (statistics-accumulate! statistics value time)
(set-statistics-n!
statistics (+ (statistics-n statistics) time))
(if (= (statistics-dimension statistics) 0)
(begin
(when (< value (statistics-minimum statistics))
(set-statistics-minimum! statistics value))
(when (> value (statistics-maximum statistics))
(set-statistics-maximum! statistics value))
(let ((weighted-value (* value time))
(weighted-value-squared (* value value time)))
(set-statistics-sum!
statistics (+ (statistics-sum statistics) weighted-value))
(set-statistics-sum-of-squares!
statistics (+ (statistics-sum-of-squares statistics)
weighted-value-squared))))
(do ((i 0 (+ i 1)))
((> i (statistics-dimension statistics)) (void))
(when (< (vector-ref value i) (vector-ref (statistics-minimum statistics) i))
(vector-set! (statistics-minimum statistics) i (vector-ref value i)))
(when (> (vector-ref value i) (vector-ref (statistics-maximum statistics) i))
(vector-set! (statistics-maximum statistics) i (vector-ref value i)))
(let ((weighted-value (* (vector-ref value i) time))
(weighted-value-squared (* (vector-ref value i)
(vector-ref value i)
time)))
(vector-set! (statistics-sum statistics) i
(+ (vector-ref (statistics-sum statistics) i)
weighted-value))
(vector-set! (statistics-sum-of-squares statistics) i
(+ (vector-ref (statistics-sum-of-squares statistics) i)
weighted-value-squared))))))
(define (statistics-tally! statistics value)
(statistics-accumulate! statistics value 1))
(define (statistics-mean statistics)
(if (= (statistics-dimension statistics) 0)
(/ (statistics-sum statistics)
(statistics-n statistics))
(let ((n (statistics-n statistics))
(sum (statistics-sum statistics))
(mean (make-vector (statistics-dimension statistics))))
(do ((i 0 (+ i 1)))
((> i (statistics-dimension statistics)) (mean))
(vector-set! mean i
(/ (vector-ref sum i) n))))))
(define (statistics-mean-square statistics)
(if (= (statistics-dimension statistics) 0)
(/ (statistics-sum-of-squares statistics)
(statistics-n statistics))
(let ((n (statistics-n statistics))
(sum-of-squares (statistics-sum-of-squares statistics))
(mean-square (make-vector (statistics-dimension statistics))))
(do ((i 0 (+ i 1)))
((> i (statistics-dimension statistics)) (mean-square))
(vector-set! mean-square i
(/ (vector-ref sum-of-squares i) n))))))
(define (statistics-variance statistics)
(if (= (statistics-dimension statistics) 0)
(- (statistics-mean-square statistics)
(* (statistics-mean statistics)
(statistics-mean statistics)))
(let ((n (statistics-n statistics))
(mean (statistics-mean statistics))
(mean-square (statistics-mean-square statistics))
(variance (make-vector (statistics-dimension statistics))))
(do ((i 0 (+ i 1)))
((> i (statistics-dimension statistics)) (variance))
(vector-set! variance i
(- (vector-ref mean-square i)
(* (vector-ref mean i)
(vector-ref mean i))))))))
(define (statistics-standard-deviation statistics)
(if (= (statistics-dimension statistics) 0)
(sqrt (statistics-variance statistics))
(let ((variance (statistics-variance statistics))
(standard-deviation (make-vector (statistics-dimension statistics))))
(do ((i 0 (+ i 1)))
((> i (statistics-dimension statistics)) (standard-deviation))
(vector-set! standard-deviation i
(sqrt (vector-ref variance i)))))))
(provide (all-defined-out))