packages feed

classify-frog-0.2.3: src/SpectralDistribution.hs

module SpectralDistribution where

import Control.Applicative (Applicative, liftA2, pure, (<*>), )
import Control.DeepSeq (NFData, rnf, )

import qualified Data.Traversable as Trav
import qualified Data.Foldable as Fold

import Foreign.Storable.Record as Store
import Foreign.Storable (Storable (..), )

import NumericPrelude.Numeric
import NumericPrelude.Base
import Prelude ()


data T a = Cons {centroid, spread :: a}
   deriving (Eq, Show)

instance (NFData a) => NFData (T a) where
   rnf (Cons c s) = rnf (c,s)

instance Functor T where
   fmap = Trav.fmapDefault

instance Applicative T where
   pure x = Cons x x
   Cons fc fs <*> Cons c s = Cons (fc c) (fs s)

instance Fold.Foldable T where
   foldMap = Trav.foldMapDefault

instance Trav.Traversable T where
   traverse f (Cons c s) = liftA2 Cons (f c) (f s)


store :: Storable a => Store.Dictionary (T a)
store =
   Store.run $
   liftA2 Cons
      (Store.element centroid)
      (Store.element spread)

instance Storable a => Storable (T a) where
   sizeOf = Store.sizeOf store
   alignment = Store.alignment store
   peek = Store.peek store
   poke = Store.poke store


mapSpread :: (a -> a) -> T a -> T a
mapSpread f (Cons c s) = Cons c (f s)


{-# INLINE spectralDistribution1 #-}
spectralDistribution1 :: Float -> Float -> Float -> T Float
spectralDistribution1 d0 d1 d2 =
   let r1 = d1/d0 in Cons r1 (d2/d0 - r1^2)


{-# INLINE signedSqrt #-}
signedSqrt :: Float -> Float
signedSqrt x = signum x * sqrt (abs x)

{-# INLINE spectralDistribution2 #-}
spectralDistribution2 :: Float -> Float -> Float -> T Float
spectralDistribution2 d0 d1 d2 =
   let r1 = d1/d0 in Cons (sqrt r1) (signedSqrt (d2/d0 - r1^2))