packages feed

phonetic-languages-rhythmicity-0.2.0.0: Languages/Rhythmicity/Factor.hs

{-# LANGUAGE BangPatterns #-}
{-# OPTIONS_HADDOCK show-extensions #-}
{-# OPTIONS_GHC -funbox-strict-fields #-}

-- |
-- Module      :  Languages.Rhythmicity.Factor
-- Copyright   :  (c) OleksandrZhabenko 2020
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  olexandr543@yahoo.com
--
-- Allows to evaluate (approximately, so better to say, to estimate) the
-- rhythmicity properties for the text (usually, the poetic one). Tries to use
-- somewhat \'improved\' versions of the functions similar to the ones in the
-- Languages.Rhythmicity module.

module Languages.Rhythmicity.Factor where

import GHC.Int

-- | The first argument must be greater than 1, though it is not checked.
maxPosition2F :: (RealFrac a) => a -> [a] -> a
maxPosition2F !k xs
 | null xs = 0.0
 | mx2 == 0.0 = 2.0 * abs (maxP21 k xs 0)
 | abs mx2 == 1 = 1.6 * abs (maxP21 k xs 0)
 | otherwise = abs (maxP21 k xs 0 / mx2)
     where maxP21 k (x:y:ys) !acc1 = maxP21 k ys (f k x y acc1)
           maxP21 k _ !acc1 = fromIntegral acc1
           maxP22 k (x:y:ys) !acc1 = maxP22 k (y:ys) (f k x y acc1)
           maxP22 k _ !acc1 = fromIntegral acc1
           !mx2 = maxP22 k xs (0::Int16)
           f !k !z !t !acc
             | z < t = (acc + 1)::Int16
             | z > k * t = (acc - 1)::Int16
             | otherwise = acc::Int16

data Pos3F = P !Int8 !Int16

posMaxIn3F
  :: (Ord a, Num a) => a
  -> a
  -> a
  -> Pos3F
posMaxIn3F x y z 
 | x < y && y < z =
    case 3 * (x + y) > 5 * z of
     True -> P 3 0
     _ -> case 2 * (x + y) > 3 * z of
           True -> P 3 1
           _ -> P 3 2
 | x < y =
    case 3 * (x + z) > 5 * y of
     True -> P 2 0
     _ -> case 2 * (x + z) > 3 * y of
           True -> P 2 1
           _ -> P 2 2
 | x < z =
    case 3 * (x + y) > 5 * z of
     True -> P 3 0
     _ -> case 2 * (x + y) > 3 * z of
           True -> P 3 1
           _ -> P 3 2
 | otherwise =
    case 3 * (y + z) > 5 * x of
     True -> P 1 0
     _ -> case 2 * (y + z) > 3 * x of
           True -> P 1 1
           _ -> P 1 2

maxPosition3F :: RealFrac a => [a] -> a
maxPosition3F xs
  | null xs = 0.0
  | length xs `rem` 3 == 0 = 3.0 * fromIntegral (go (h xs) ((0, 0, 0)::(Int16,Int16,Int16)))
  | otherwise = fromIntegral (go (h xs) ((0, 0, 0)::(Int16,Int16,Int16)))
      where h (x:y:z:ys) = posMaxIn3F x y z:h ys
            h _ = []
            go (x:zs) (!acc21,!acc22,!acc23) = go zs (h1 x (acc21,acc22,acc23))
            go _ (!acc21,!acc22,!acc23)
              | acc21 > acc22 = if acc21 > acc23 then acc21 else acc23
              | acc22 > acc23 = acc22
              | otherwise = acc23
            h1 (P !x !y) (!t,!u,!w)
              | x == 1 = (t + y, u, w)
              | x == 2 = (t, u + y, w)
              | otherwise = (t,u,w + y)

evalRhythmicity23F :: (RealFrac a, Floating a) => a -> [a] -> a
evalRhythmicity23F k xs = maxPosition2F k xs * maxPosition2F k xs + maxPosition3F xs * maxPosition3F xs

evalRhythmicity23KF
  :: (RealFrac a, Floating a) => a
  -> a
  -> a
  -> [a]
  -> a
evalRhythmicity23KF k k2 k3 xs = k2 * maxPosition2F k xs * maxPosition2F k xs + k3 * maxPosition3F xs * maxPosition3F xs