{-# LANGUAGE NoImplicitPrelude #-}

module Phladiprelio.General.Distance where

import GHC.Base
import GHC.Real (Fractional(..),Real(..),gcd,quot,(/),fromIntegral)
import GHC.Float (Floating(..),sqrt)
import GHC.List
import Data.List (replicate)
import GHC.Num ((*),(-))

-- | 'toEqLength' changes two given lists of non-negative 'Real' numbers into two lists of equal
-- minimal lengths and also returs its new length and initial lengths of the lists given.
toEqLength :: Real a => [a] -> [a] -> ([a],[a],Int,Int,Int)
toEqLength :: forall a. Real a => [a] -> [a] -> ([a], [a], Int, Int, Int)
toEqLength [a]
xs [a]
ys 
  | [a] -> Bool
forall a. [a] -> Bool
null [a]
xs = ([],[],Int
0,Int
0,Int
0)
  | [a] -> Bool
forall a. [a] -> Bool
null [a]
ys = ([],[],Int
0,Int
0,Int
0)
  | Bool
otherwise = ([a]
ts, [a]
vs, Int
lx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
ly Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
dc,Int
lx,Int
ly) 
       where lx :: Int
lx = [a] -> Int
forall a. [a] -> Int
length [a]
xs
             ly :: Int
ly = [a] -> Int
forall a. [a] -> Int
length [a]
ys
             dc :: Int
dc = Int -> Int -> Int
forall a. Integral a => a -> a -> a
gcd Int
lx Int
ly
             ts :: [a]
ts = (a -> [a]) -> [a] -> [a]
forall a b. (a -> [b]) -> [a] -> [b]
concatMap (Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
ly Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
dc)) ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ [a]
xs
             vs :: [a]
vs = (a -> [a]) -> [a] -> [a]
forall a b. (a -> [b]) -> [a] -> [b]
concatMap (Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
lx Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
dc)) ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ [a]
ys

-- | 'toEqLengthL' changes two given lists of non-negative 'Real' numbers into two lists of equal
-- minimal lengths and also returs its new length and initial lengths of the lists given. Is
-- intended to be used when the length of the lists are known and given as the first and the second parameters
-- here respectively.
toEqLengthL :: Real a => Int -> Int -> [a] -> [a] -> ([a],[a],Int,Int,Int)
toEqLengthL :: forall a.
Real a =>
Int -> Int -> [a] -> [a] -> ([a], [a], Int, Int, Int)
toEqLengthL Int
lx Int
ly [a]
xs [a]
ys 
  | Int
lx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = ([],[],Int
0,Int
0,Int
0)
  | Int
ly Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = ([],[],Int
0,Int
0,Int
0)
  | Bool
otherwise = ([a]
ts, [a]
vs, Int
lx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
ly Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
dc,Int
lx,Int
ly) 
       where dc :: Int
dc = Int -> Int -> Int
forall a. Integral a => a -> a -> a
gcd Int
lx Int
ly
             ts :: [a]
ts = (a -> [a]) -> [a] -> [a]
forall a b. (a -> [b]) -> [a] -> [b]
concatMap (Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
ly Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
dc)) ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ [a]
xs
             vs :: [a]
vs = (a -> [a]) -> [a] -> [a]
forall a b. (a -> [b]) -> [a] -> [b]
concatMap (Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
lx Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
dc)) ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ [a]
ys

sumSqrDistNorm :: (Real a, Fractional a) => [a] -> [a] -> a
sumSqrDistNorm :: forall a. (Real a, Fractional a) => [a] -> [a] -> a
sumSqrDistNorm [a]
xs [a]
ys 
 | Int
lc Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = a
0
 | Bool
otherwise = [a] -> a
forall a. Num a => [a] -> a
sum ((a -> a -> a) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\a
x a
y -> (a
x a -> a -> a
forall a. Num a => a -> a -> a
- a
y) a -> a -> a
forall a. Num a => a -> a -> a
* (a
x a -> a -> a
forall a. Num a => a -> a -> a
- a
y)) [a]
ts [a]
vs) a -> a -> a
forall a. Fractional a => a -> a -> a
/ Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
lc
     where ([a]
ts, [a]
vs, Int
lc, Int
lx, Int
ly) = [a] -> [a] -> ([a], [a], Int, Int, Int)
forall a. Real a => [a] -> [a] -> ([a], [a], Int, Int, Int)
toEqLength [a]
xs [a]
ys 

-- | 'distanceSqr' is applied on two lists of non-negative 'Real' numbers (preferably, of type
-- 'Double') and returns a special kind of distance that is similar to the statistical distance used
-- in the regression analysis. Is intended to be used e. g. for the PhLADiPreLiO approach. The less
-- is the resulting number, the more \'similar\' are the two lists of non-negative numbers in their
-- distributions. Here, in contrast to the more general 'distanceSqrG', the numbers must be normed
-- to 1.0, so that the largest ones in both listn must be 1.0.
distanceSqr :: (Real a, Floating a, Fractional a) => [a] -> [a] -> a
distanceSqr :: forall a. (Real a, Floating a, Fractional a) => [a] -> [a] -> a
distanceSqr [a]
xs [a]
ys = a -> a
forall a. Floating a => a -> a
sqrt a
s
   where s :: a
s = [a] -> [a] -> a
forall a. (Real a, Fractional a) => [a] -> [a] -> a
sumSqrDistNorm [a]
xs [a]
ys 
{-# INLINE distanceSqr #-}

-- | 'distanceSqrG' is applied on two lists of non-negative 'Real' numbers (preferably, of type
-- 'Double') and returns a special kind of distance that is similar to the statistical distance used
-- in the regression analysis. Is intended to be used e. g. for the PhLADiPreLiO approach. The less
-- is the resulting number, the more \'similar\' are the two lists of non-negative numbers in their
-- distributions.
distanceSqrG :: (Real a, Floating a, Fractional a) => [a] -> [a] -> a
distanceSqrG :: forall a. (Real a, Floating a, Fractional a) => [a] -> [a] -> a
distanceSqrG [a]
xs [a]
ys = [a] -> [a] -> a
forall a. (Real a, Floating a, Fractional a) => [a] -> [a] -> a
distanceSqr [a]
qs [a]
rs
   where mx :: a
mx = [a] -> a
forall a. (Ord a, HasCallStack) => [a] -> a
maximum [a]
xs
         my :: a
my = [a] -> a
forall a. (Ord a, HasCallStack) => [a] -> a
maximum [a]
ys
         qs :: [a]
qs = (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
mx) [a]
xs
         rs :: [a]
rs = (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
my) [a]
ys
{-# INLINE distanceSqrG #-}