packages feed

quantizer-0.1.0.0: TwoQuantizer.hs

module TwoQuantizer where

import Data.Maybe
import Numeric.Stats (meanD)

round2 
  :: Bool -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
  -> Double 
  -> Double 
  -> Double 
  -> Maybe Double -- ^ The numeric value (in 'Just' case) can be equal just to the one of the two first arguments.
round2 bool x y z 
 | x <= 0 || y <= 0 || z <= 0 = Nothing
 | (x - z) * (y - z) <= 0 = Just (case compare (z*z) (x*y) of { GT -> max x y; LT -> min x y; EQ -> (if bool then max else min) x y })
 | otherwise = Nothing

round2L 
 :: Bool  -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> [Double] 
 -> Double 
 -> Double
round2L ctrl ts x 
 | null ts = x
 | null ks = y
 | null us = y0
 | x < y = fromJust . round2 ctrl y0 y $ x
 | otherwise = y
  where (ks, us) = span (<x) ts
        y = head us
        y0 = last ks

twoQuantizer 
 :: Bool  -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> [Double] 
 -> [Double] 
 -> [Double]
twoQuantizer ctrl needs xs = map (round2L ctrl needs) ys
  where k = meanD needs / meanD xs
        ys = map (*k) xs

round2G 
 :: (Ord a) => Bool -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> (a -> a -> a -> Ordering) 
 -> a 
 -> a 
 -> a 
 -> Maybe a -- ^ The @a@ value (in 'Just' case) can be equal just to the one of the two first @a@ arguments.
round2G bool f x y z 
 | z == x = Just x
 | z == y = Just y
 | (x < z && y > z) || (x > z && y < z) = Just (case f x y z of { GT -> max x y; LT -> min x y; EQ -> (if bool then max else min) x y })
 | otherwise = Nothing

round2GL 
 :: (Ord a) => Bool -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> (a -> a -> a -> Ordering) 
 -> [a] 
 -> a 
 -> a
round2GL ctrl f ts x 
 | null ts = x
 | null ks = y
 | null us = y0
 | x < y = fromJust . round2G ctrl f y0 y $ x
 | otherwise = y
  where (ks, us) = span (<x) ts
        y = head us
        y0 = last ks

twoQuantizerG 
 :: (Ord a, Floating a, Integral a) => Bool -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> (a -> a -> a -> Ordering) 
 -> [a] 
 -> [a] 
 -> [a]
twoQuantizerG ctrl f needs xs = map (round2GL ctrl f needs) ys
  where k = meanF2 needs 0 0 / meanF2 xs 0 0
        ys = map (*k) xs

round2GM 
 :: (Ord a, Monad m) => Bool -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> (a -> a -> a -> m Ordering) 
 -> a 
 -> a 
 -> a 
 -> m (Maybe a)
round2GM bool f x y z 
 | z == x = return . Just $ x
 | z == y = return . Just $ y
 | (x < z && y > z) || (x > z && y < z) = do
     t <- f x y z
     case t of { GT -> return . Just . max x $ y; LT -> return . Just . min x $ y; EQ -> return. Just $ (if bool then max else min) x y }
 | otherwise = return Nothing

round2GLM 
 :: (Ord a, Monad m) => Bool -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> (a -> a -> a -> m Ordering) 
 -> [a] 
 -> a 
 -> m a
round2GLM ctrl f ts x 
 | null ts = return x
 | null ks = return y
 | null us = return y0
 | x < y = fmap fromJust . round2GM ctrl f y0 y $ x 
 | otherwise = return y
  where (ks, us) = span (<x) ts
        y = head us
        y0 = last ks

meanF2 
 :: (Floating a, Integral a) => [a] 
 -> a 
 -> a 
 -> a
meanF2 (t:ts) s l = meanF2 ts (s + t) (l + 1) 
meanF2 _ s l = s / fromIntegral l

twoQuantizerGM 
 :: (Ord a, Floating a, Integral a, Monad m) => Bool -- ^ If 'True' then the function rounds the result in the ambiguous situation to the greater value. 
 -> (a -> a -> a -> m Ordering) 
 -> [a] 
 -> [a] 
 -> m [a]
twoQuantizerGM ctrl f needs xs = mapM (round2GLM ctrl f needs) ys
  where k = meanF2 needs 0 0  / meanF2 xs 0 0
        ys = map (*k) xs