    -- |
    -- 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 :: forall a. (Typed a, Num a, Eq a) => 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 :: forall a. (Typed a, Ord a) => 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 :: forall a. (Typed a, Ord a) => 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 :: forall a.
    (Typed a, Eq a, Fractional a) =>
    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 :: forall a. (Typed a, Integral a) => [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 a. (a -> a -> a) -> [a] -> 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 a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [Stream a]
    ls )