module TimeSeries.Window where
import Data.Array.Unboxed
import Data.List (intersperse)
import Data.Word
import Text.Printf (printf)
import Prelude hiding (length)
import qualified Prelude
import TimeSeries.PRG64
newtype Window = Window (UArray Word64 Double) deriving (Eq, Show)
type Size = Word64
data RandomVector = RandomVector
{
unitRV :: Window
, controlRV :: Window
} deriving (Eq, Show)
fromList :: [Double] -> Window
fromList xs = Window $ array (0,sz) $ zip [0..] xs where
sz = fromIntegral (Prelude.length xs 1)
toList :: Window -> [Double]
toList (Window xs) = elems xs
empty :: Size -> Window
empty sz = Window $ array (0,sz1) [(i,0)|i <- [0..sz1]]
push :: Double -> Window -> Window
push v (Window arr) = Window (arr' // [(0,v)]) where
arr' = ixmap (bounds arr) f arr
f idx | idx == 0 = 0
| otherwise = idx 1
singleton :: Double -> Window
singleton v = Window $ array (0,0) [(0,v)]
norm :: Window -> Window -> Double
norm (Window x) (Window y) =
sqrt $ sum [(xiyi)^(2::Int)|(xi,yi)<-zip (elems x) (elems y)]
append :: Window -> Window -> Window
append w@(Window wina) (Window winb) = Window (winc // assocs wina) where
winc = ixmap (bounds winb) f winb
f idx | idx < lengthA = 0
| otherwise = idx lengthA
lengthA = fromIntegral $ length w
sumWindow :: Window -> Double
sumWindow (Window arr) = sum $ elems arr
sumSqWindow :: Window -> Double
sumSqWindow (Window arr) = sum $ [x^(2::Int)|x<-elems arr]
dotp :: Window -> Window -> Double
dotp (Window wx) (Window wy) = sum $ zipWith (*) (elems wx) (elems wy)
dotps :: [Window] -> Window -> Window
dotps xss ys = fromList [dotp xs ys|xs <- xss]
copyContents ::
Window
-> Window
-> Window
copyContents (Window to) (Window from) =
Window $ ixmap (bounds to) id from
randomVector ::
Integer
-> Size
-> Size
-> RandomVector
randomVector seed bw nb = RandomVector (fromList r) (fromList b) where
(r,b) = rnd bw nb (fromIntegral seed)
wholeRandomVector ::
RandomVector
-> Window
wholeRandomVector (RandomVector (Window u) (Window c)) =
let bw = rangeSize $ bounds u
nb = rangeSize $ bounds c
u' = concat $ replicate (fromIntegral nb) (elems u)
c' = concatMap (replicate (fromIntegral bw)) (elems c)
in fromList $ zipWith (*) u' c'
pretty :: Window -> String
pretty (Window w) =
concat . intersperse ", " $ map (printf "%.12f") (elems w)
average :: Window -> Double
average win@(Window w) = sum w' / fromIntegral (length win) where
w' = elems w
variance :: Window -> Double
variance win@(Window w) = sqrt (mean [sq wi|wi<-w'] sq (mean w')) where
w' = elems w
mean xs = sum xs / fromIntegral (length win)
sq x = x ^ (2::Int)
length :: Window -> Int
length (Window w) = rangeSize $ bounds w