{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RecordWildCards #-}
module Numeric.Eproc.ConfSeq (
Config
, State
, ConfigError(..)
, config
, initial
, update
, interval
, samples
) where
import qualified Data.List as L
import GHC.Float (log1p)
import Numeric.Eproc.Common (ConfigError(..), finite)
data Config = Config {
Config -> Double
cfg_lo :: {-# UNPACK #-} !Double
, Config -> Double
cfg_hi :: {-# UNPACK #-} !Double
, Config -> Double
cfg_alpha :: {-# UNPACK #-} !Double
, Config -> Int
cfg_grid :: {-# UNPACK #-} !Int
, Config -> Double
cfg_log_thresh :: {-# UNPACK #-} !Double
, Config -> Double
cfg_bet_num :: {-# UNPACK #-} !Double
}
data Point = Point
{-# UNPACK #-} !Int
{-# UNPACK #-} !Double
{-# UNPACK #-} !Double
data State = State {
State -> Int
st_n :: {-# UNPACK #-} !Int
, State -> Double
st_sum_y :: {-# UNPACK #-} !Double
, State -> Double
st_sum_dev2 :: {-# UNPACK #-} !Double
, State -> [Point]
st_live :: ![Point]
}
trunc_c :: Double
trunc_c :: Double
trunc_c = Double
0.5
{-# INLINE trunc_c #-}
config
:: Double
-> Double
-> Double
-> Int
-> Either ConfigError Config
config :: Double -> Double -> Double -> Int -> Either ConfigError Config
config !Double
lo !Double
hi !Double
alpha !Int
g
| Bool -> Bool
not (Double -> Bool
finite Double
alpha Bool -> Bool -> Bool
&& Double
alpha Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 Bool -> Bool -> Bool
&& Double
alpha Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1) =
ConfigError -> Either ConfigError Config
forall a b. a -> Either a b
Left (Double -> ConfigError
InvalidAlpha Double
alpha)
| Bool -> Bool
not (Double -> Bool
finite Double
lo Bool -> Bool -> Bool
&& Double -> Bool
finite Double
hi Bool -> Bool -> Bool
&& Double
lo Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
hi) =
ConfigError -> Either ConfigError Config
forall a b. a -> Either a b
Left (Double -> Double -> ConfigError
InvalidBounds Double
lo Double
hi)
| Int
g Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1 =
ConfigError -> Either ConfigError Config
forall a b. a -> Either a b
Left (Int -> ConfigError
InvalidGridSize Int
g)
| Bool
otherwise = Config -> Either ConfigError Config
forall a b. b -> Either a b
Right Config {
cfg_lo :: Double
cfg_lo = Double
lo
, cfg_hi :: Double
cfg_hi = Double
hi
, cfg_alpha :: Double
cfg_alpha = Double
alpha
, cfg_grid :: Int
cfg_grid = Int
g
, cfg_log_thresh :: Double
cfg_log_thresh = Double -> Double
forall a. Floating a => a -> a
log (Double
2 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
alpha)
, cfg_bet_num :: Double
cfg_bet_num = Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
log (Double
2 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
alpha)
}
{-# INLINE config #-}
initial :: Config -> State
initial :: Config -> State
initial Config{Double
Int
cfg_lo :: Config -> Double
cfg_hi :: Config -> Double
cfg_alpha :: Config -> Double
cfg_grid :: Config -> Int
cfg_log_thresh :: Config -> Double
cfg_bet_num :: Config -> Double
cfg_lo :: Double
cfg_hi :: Double
cfg_alpha :: Double
cfg_grid :: Int
cfg_log_thresh :: Double
cfg_bet_num :: Double
..} = State {
st_n :: Int
st_n = Int
0
, st_sum_y :: Double
st_sum_y = Double
0
, st_sum_dev2 :: Double
st_sum_dev2 = Double
0
, st_live :: [Point]
st_live = Int -> [Point]
points Int
1
}
where
points :: Int -> [Point]
points !Int
j
| Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
cfg_grid = []
| Bool
otherwise =
let !p :: Point
p = Int -> Double -> Double -> Point
Point Int
j Double
0 Double
0
!rest :: [Point]
rest = Int -> [Point]
points (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
in Point
p Point -> [Point] -> [Point]
forall a. a -> [a] -> [a]
: [Point]
rest
{-# INLINE initial #-}
update :: Config -> State -> Double -> State
update :: Config -> State -> Double -> State
update Config{Double
Int
cfg_lo :: Config -> Double
cfg_hi :: Config -> Double
cfg_alpha :: Config -> Double
cfg_grid :: Config -> Int
cfg_log_thresh :: Config -> Double
cfg_bet_num :: Config -> Double
cfg_lo :: Double
cfg_hi :: Double
cfg_alpha :: Double
cfg_grid :: Int
cfg_log_thresh :: Double
cfg_bet_num :: Double
..} State{Double
Int
[Point]
st_n :: State -> Int
st_sum_y :: State -> Double
st_sum_dev2 :: State -> Double
st_live :: State -> [Point]
st_n :: Int
st_sum_y :: Double
st_sum_dev2 :: Double
st_live :: [Point]
..} !Double
x =
let !y :: Double
y = (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
cfg_lo) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
cfg_hi Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
cfg_lo)
!t :: Int
t = Int
st_n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
!td :: Double
td = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
t
!gp1 :: Double
gp1 = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
cfg_grid Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
!sig2 :: Double
sig2 = (Double
0.25 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
st_sum_dev2) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
td
!lam :: Double
lam = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
cfg_bet_num Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
sig2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
td Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
log1p Double
td))
go :: [Point] -> [Point]
go [] = []
go (Point Int
j Double
lp Double
ln : [Point]
ps) =
let !m :: Double
m = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
j Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
gp1
!d :: Double
d = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
m
!lp' :: Double
lp' = Double
lp Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Floating a => a -> a
log1p (Double -> Double -> Double
forall a. Ord a => a -> a -> a
min Double
lam (Double
trunc_c Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
m) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
d)
!ln' :: Double
ln' = Double
ln Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Floating a => a -> a
log1p (Double -> Double
forall a. Num a => a -> a
negate (Double -> Double -> Double
forall a. Ord a => a -> a -> a
min Double
lam (Double
trunc_c Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
m)))
Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
d)
!rest :: [Point]
rest = [Point] -> [Point]
go [Point]
ps
in if Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
lp' Double
ln' Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
cfg_log_thresh
then [Point]
rest
else Int -> Double -> Double -> Point
Point Int
j Double
lp' Double
ln' Point -> [Point] -> [Point]
forall a. a -> [a] -> [a]
: [Point]
rest
!live :: [Point]
live = [Point] -> [Point]
go [Point]
st_live
!sum_y' :: Double
sum_y' = Double
st_sum_y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
y
!mu :: Double
mu = (Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
sum_y') Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
td Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1)
!dev :: Double
dev = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
mu
!dev2' :: Double
dev2' = Double
st_sum_dev2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
dev Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
dev
in Int -> Double -> Double -> [Point] -> State
State Int
t Double
sum_y' Double
dev2' [Point]
live
{-# INLINE update #-}
interval :: Config -> State -> Maybe (Double, Double)
interval :: Config -> State -> Maybe (Double, Double)
interval Config{Double
Int
cfg_lo :: Config -> Double
cfg_hi :: Config -> Double
cfg_alpha :: Config -> Double
cfg_grid :: Config -> Int
cfg_log_thresh :: Config -> Double
cfg_bet_num :: Config -> Double
cfg_lo :: Double
cfg_hi :: Double
cfg_alpha :: Double
cfg_grid :: Int
cfg_log_thresh :: Double
cfg_bet_num :: Double
..} State{Double
Int
[Point]
st_n :: State -> Int
st_sum_y :: State -> Double
st_sum_dev2 :: State -> Double
st_live :: State -> [Point]
st_n :: Int
st_sum_y :: Double
st_sum_dev2 :: Double
st_live :: [Point]
..} = case [Point]
st_live of
[] -> Maybe (Double, Double)
forall a. Maybe a
Nothing
(Point Int
j0 Double
_ Double
_ : [Point]
ps) ->
let !jmin :: Int
jmin = (Int -> Point -> Int) -> Int -> [Point] -> Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.foldl' (\Int
acc (Point Int
j Double
_ Double
_) -> Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
acc Int
j) Int
j0 [Point]
ps
!jmax :: Int
jmax = (Int -> Point -> Int) -> Int -> [Point] -> Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.foldl' (\Int
acc (Point Int
j Double
_ Double
_) -> Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
acc Int
j) Int
j0 [Point]
ps
!gp1 :: Double
gp1 = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
cfg_grid Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
!w :: Double
w = Double
cfg_hi Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
cfg_lo
!l :: Double
l | Int
jmin Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = Double
cfg_lo
| Bool
otherwise =
Double
cfg_lo Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
jmin Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
gp1 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
w
!u :: Double
u | Int
jmax Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
cfg_grid = Double
cfg_hi
| Bool
otherwise =
Double
cfg_lo Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
jmax Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
gp1 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
w
in (Double, Double) -> Maybe (Double, Double)
forall a. a -> Maybe a
Just (Double
l, Double
u)
{-# INLINE interval #-}
samples :: State -> Int
samples :: State -> Int
samples = State -> Int
st_n
{-# INLINE samples #-}