-- | 
-- Module: Statistics
-- Description: Basic bounded statistics
-- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc.
--
-- Basic bounded statistics.  In the following, a bound @n@ is given stating
-- the number of periods over which to compute the statistic (@n == 1@ computes
-- it only over the current period).

{-# LANGUAGE NoImplicitPrelude #-}

module Copilot.Library.Statistics
    ( max, min, sum, mean, meanNow ) where

import Copilot.Language
import Copilot.Library.Utils

-- | Summation.
sum :: ( Typed a, Num a, Eq a ) => Int -> Stream a -> Stream a
sum :: Int -> Stream a -> Stream a
sum Int
n Stream a
s = Int -> (Stream a -> Stream a -> Stream a) -> Stream a -> Stream a
forall a.
Typed a =>
Int -> (Stream a -> Stream a -> Stream a) -> Stream a -> Stream a
nfoldl1 Int
n Stream a -> Stream a -> Stream a
forall a. Num a => a -> a -> a
(+) Stream a
s

-- | Maximum value.
max :: ( Typed a, Ord a ) => Int -> Stream a -> Stream a
max :: Int -> Stream a -> Stream a
max Int
n Stream a
s = Int -> (Stream a -> Stream a -> Stream a) -> Stream a -> Stream a
forall a.
Typed a =>
Int -> (Stream a -> Stream a -> Stream a) -> Stream a -> Stream a
nfoldl1 Int
n Stream a -> Stream a -> Stream a
largest Stream a
s
    where largest :: Stream a -> Stream a -> Stream a
largest  = \ Stream a
x Stream a
y -> Stream Bool -> Stream a -> Stream a -> Stream a
forall a.
Typed a =>
Stream Bool -> Stream a -> Stream a -> Stream a
mux ( Stream a
x Stream a -> Stream a -> Stream Bool
forall a. (Ord a, Typed a) => Stream a -> Stream a -> Stream Bool
>= Stream a
y ) Stream a
x Stream a
y

-- | Minimum value.
min :: ( Typed a, Ord a ) => Int -> Stream a -> Stream a
min :: Int -> Stream a -> Stream a
min Int
n Stream a
s = Int -> (Stream a -> Stream a -> Stream a) -> Stream a -> Stream a
forall a.
Typed a =>
Int -> (Stream a -> Stream a -> Stream a) -> Stream a -> Stream a
nfoldl1 Int
n Stream a -> Stream a -> Stream a
smallest Stream a
s
    where smallest :: Stream a -> Stream a -> Stream a
smallest = \ Stream a
x Stream a
y -> Stream Bool -> Stream a -> Stream a -> Stream a
forall a.
Typed a =>
Stream Bool -> Stream a -> Stream a -> Stream a
mux ( Stream a
x Stream a -> Stream a -> Stream Bool
forall a. (Ord a, Typed a) => Stream a -> Stream a -> Stream Bool
<= Stream a
y ) Stream a
x Stream a
y

-- | Mean value.  @n@ must not overflow
-- for word size @a@ for streams over which computation is peformed.
mean :: ( Typed a, Eq a, Fractional a ) => Int -> Stream a -> Stream a
mean :: Int -> Stream a -> Stream a
mean Int
n Stream a
s = ( Int -> Stream a -> Stream a
forall a. (Typed a, Num a, Eq a) => Int -> Stream a -> Stream a
sum Int
n Stream a
s ) Stream a -> Stream a -> Stream a
forall a. Fractional a => a -> a -> a
/ ( Int -> Stream a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n )

-- | Mean value over the current set of streams passed in.
meanNow :: ( Typed a, Integral a ) => [ Stream a ] -> Stream a
meanNow :: [Stream a] -> Stream a
meanNow [] = 
  String -> Stream a
forall a. String -> a
badUsage String
"list of arguments to meanNow must be nonempty"
meanNow [Stream a]
ls = ( (Stream a -> Stream a -> Stream a) -> [Stream a] -> Stream a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Stream a -> Stream a -> Stream a
forall a. Num a => a -> a -> a
(+) [Stream a]
ls ) Stream a -> Stream a -> Stream a
forall a. (Typed a, Integral a) => Stream a -> Stream a -> Stream a
`div` ( Int -> Stream a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Stream a) -> Int -> Stream a
forall a b. (a -> b) -> a -> b
$ [Stream a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Stream a]
ls )