packages feed

datafix-0.0.0.1: exprs/kahan.hs

{-# LANGUAGE FlexibleContexts #-}
-- Inferred type for 'inner' has a constraint (MArray (STUArray s) Double m)
-- An alternative fix (better, but less faithful to backward perf comparison)
-- would be MonoLocalBinds

-- | Implementation of Kahan summation algorithm that tests
-- performance of tight loops involving unboxed arrays and floating
-- point arithmetic.
module Expr where

import           Control.Monad.ST
import           Data.Array.Base
import           Data.Array.ST
import           Data.Bits
import           Data.Word
import           System.Environment

type Vec s = STUArray s Int Double

expr :: Int -> Vec s -> Vec s -> ST s ()
expr a b c = kahan a b c
  where
    vdim :: Int
    vdim = 100

    prng :: Word -> Word
    prng w = w'
      where
        w1 = w `xor` (w `shiftL` 13)
        w2 = w1 `xor` (w1 `shiftR` 7)
        w' = w2 `xor` (w2 `shiftL` 17)

    kahan :: Int -> Vec s -> Vec s -> ST s ()
    kahan vnum s c = do
        let inner w j
                | j < vdim  = do
                    cj <- unsafeRead c j
                    sj <- unsafeRead s j
                    let y = fromIntegral w - cj
                        t = sj + y
                        w' = prng w
                    unsafeWrite c j ((t-sj)-y)
                    unsafeWrite s j t
                    inner w' (j+1)
                | otherwise = return ()

            outer i | i <= vnum = inner (fromIntegral i) 0 >> outer (i+1)
                    | otherwise = return ()
        outer 1

    calc :: Int -> ST s (Vec s)
    calc vnum = do
        s <- newArray (0,vdim-1) 0
        c <- newArray (0,vdim-1) 0
        kahan vnum s c
        return s