{-# LANGUAGE Strict #-}
{-# LANGUAGE NoImplicitPrelude #-}

{- |
Module      :  Aftovolio.PermutationsArrMini2
Copyright   :  (c) OleksandrZhabenko 2024
License     :  MIT
Stability   :  Experimental
Maintainer  :  oleksandr.zhabenko@yahoo.com

Special permutations functions for the AFTOVolio. This
module uses no vectors, but instead uses arrays.
-}
module Aftovolio.PermutationsArrMini2 (
    genDoublePermutations2,
    pairsSwapP2,
    genDoublePermutationsArrN2,
    genDoublePermutationsArr2,
    genDoublePermutationsLN2,
    genDoublePermutationsL2,
    genDoublePermutationsArrLN2,
    genDoublePermutationsArrL2,
) where

import GHC.Arr
import GHC.Base
import GHC.Enum
import GHC.List
import Data.List ((\\),nub)
import GHC.Num (Num, abs, (+), (-), (*))

genDoublePermutations2 :: Int -> Array Int [Int]
genDoublePermutations2 :: Int -> Array Int [Int]
genDoublePermutations2 Int
n = (Int, Int) -> [[Int]] -> Array Int [Int]
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [[Int]]
xs
  where
    xs :: [[Int]]
xs = [Int] -> [[Int]]
pairsSwapP2 ([Int] -> [[Int]]) -> ([Int] -> [Int]) -> [Int] -> [[Int]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
take Int
n ([Int] -> [[Int]]) -> [Int] -> [[Int]]
forall a b. (a -> b) -> a -> b
$ [Int
0 ..]
    l :: Int
l = [[Int]] -> Int
forall a. [a] -> Int
length [[Int]]
xs
{-# INLINE genDoublePermutations2 #-}
--{-# SPECIALIZE genDoublePermutations2 :: Int -> Array Int [Int] #-}

pairsSwapP2 :: [Int] -> [[Int]]
pairsSwapP2 :: [Int] -> [[Int]]
pairsSwapP2 [Int]
xs = [[Int]] -> [[Int]]
forall a. Eq a => [a] -> [a]
nub ([[Int]] -> [[Int]]) -> [[Int]] -> [[Int]]
forall a b. (a -> b) -> a -> b
$
    [Int]
xs
        [Int] -> [[Int]] -> [[Int]]
forall a. a -> [a] -> [a]
: [[Int]]
cuts
              where l :: Int
l = [Int] -> Int
forall a. [a] -> Int
length [Int]
xs
                    indices :: [(Int, Int)]
indices = [(Int
i,Int
j) | Int
i <- [Int]
xs, Int
j <- [Int]
xs, Int
j Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
i]
                    cuts :: [[Int]]
cuts = ((Int, Int) -> [[Int]]) -> [(Int, Int)] -> [[Int]]
forall a b. (a -> [b]) -> [a] -> [b]
concatMap (\(Int
i, Int
j) -> 
                               let idxs :: [Int]
idxs = (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Int
x -> Int
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
i Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
j) [Int]
xs
                                   in ((Int, Int) -> [Int]) -> [(Int, Int)] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map (\(Int
i', Int
j') -> 
                                          let (Int
mn, Int
mx) = if Int
j' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
i' then (Int
i', Int
j') else (Int
j', Int
i')
                                              ([Int]
ks, [Int]
us) = Int -> [Int] -> ([Int], [Int])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
mn [Int]
idxs 
                                              idx1 :: [Int]
idx1 = [Int]
ks [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ (Int
i Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
us) 
                                              ([Int]
rs, [Int]
qs) = Int -> [Int] -> ([Int], [Int])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
mx [Int]
idx1
                                              in [Int]
rs [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ (Int
j Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
qs)) ([(Int, Int)] -> [[Int]])
-> ([(Int, Int)] -> [(Int, Int)]) -> [(Int, Int)] -> [[Int]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int) -> Bool) -> [(Int, Int)] -> [(Int, Int)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Int, Int) -> (Int, Int) -> Bool
forall a. Eq a => a -> a -> Bool
/= (Int
i, Int
j)) ([(Int, Int)] -> [[Int]]) -> [(Int, Int)] -> [[Int]]
forall a b. (a -> b) -> a -> b
$ [(Int, Int)]
indices) [(Int, Int)]
indices
--{-# SPECIALIZE pairsSwapP2 :: [Int] -> [[Int]] #-}

-- | The second argument is greater than the first, the third is not equal to the first, the fourth is not equal to the second, and all five of the arguments are considered greater or equal to 0, though it is not checked.
swap2ns2 :: (Ord a, Num a) => a -> a -> a -> a -> a -> a
swap2ns2 :: forall a. (Ord a, Num a) => a -> a -> a -> a -> a -> a
swap2ns2 a
k a
n a
m a
j a
i
    | a
q a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 Bool -> Bool -> Bool
&& a
p a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 = a
i
    | a
i a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
j = a
n
    | a
i a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
m = a
k --
    | a
q a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 Bool -> Bool -> Bool
&& a
p a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = if a
j a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
n then a
i a -> a -> a
forall a. Num a => a -> a -> a
+ a
1 else a
i a -> a -> a
forall a. Num a => a -> a -> a
- a
1
    | a
q a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
&& a
p a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 = if a
m a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
k then a
i a -> a -> a
forall a. Num a => a -> a -> a
+ a
1 else a
i a -> a -> a
forall a. Num a => a -> a -> a
- a
1
    | a
q a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
&& a
p a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = if (a
k a -> a -> a
forall a. Num a => a -> a -> a
- a
m)a -> a -> a
forall a. Num a => a -> a -> a
*(a
n a -> a -> a
forall a. Num a => a -> a -> a
- a
j) a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 
                           then if a
m a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
k then a
i a -> a -> a
forall a. Num a => a -> a -> a
+ a
2 else a
i a -> a -> a
forall a. Num a => a -> a -> a
- a
2
                           else a
i
    | a
i a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
n = if a
m a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
n then a
k else if a
j a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
n then a
n a -> a -> a
forall a. Num a => a -> a -> a
+ a
1 else a
n a -> a -> a
forall a. Num a => a -> a -> a
- a
1
    | a
i a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
k = if a
j a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
k then a
n else if a
m a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
k then a
k a -> a -> a
forall a. Num a => a -> a -> a
+ a
1 else a
k a -> a -> a
forall a. Num a => a -> a -> a
- a
1
       where  q :: a
q = (a
i a -> a -> a
forall a. Num a => a -> a -> a
- a
k)a -> a -> a
forall a. Num a => a -> a -> a
*(a
i a -> a -> a
forall a. Num a => a -> a -> a
- a
m)
              p :: a
p = (a
i a -> a -> a
forall a. Num a => a -> a -> a
- a
n)a -> a -> a
forall a. Num a => a -> a -> a
*(a
i a -> a -> a
forall a. Num a => a -> a -> a
- a
j)
{-# INLINE swap2ns2 #-}
{-# SPECIALIZE swap2ns2 :: Int -> Int -> Int -> Int -> Int -> Int #-}

swap2Ls2 :: (Ord a, Num a) => a -> a -> a -> a -> [a] -> [a]
swap2Ls2 :: forall a. (Ord a, Num a) => a -> a -> a -> a -> [a] -> [a]
swap2Ls2 a
k a
n a
m a
j = (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> a -> a -> a -> a
forall a. (Ord a, Num a) => a -> a -> a -> a -> a -> a
swap2ns2 a
k a
n a
m a
j)
{-# INLINE swap2Ls2 #-}
{-# SPECIALIZE swap2Ls2 :: Int -> Int -> Int -> Int -> [Int] -> [Int] #-}

genDoublePermutationsArrN2 ::
    Int -> Array Int (Array Int [Int])
genDoublePermutationsArrN2 :: Int -> Array Int (Array Int [Int])
genDoublePermutationsArrN2 Int
n = (Int -> Array Int [Int])
-> Array Int Int -> Array Int (Array Int [Int])
forall a b i. (a -> b) -> Array i a -> Array i b
amap Int -> Array Int [Int]
genDoublePermutations2 (Array Int Int -> Array Int (Array Int [Int]))
-> ([Int] -> Array Int Int) -> [Int] -> Array Int (Array Int [Int])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> [Int] -> Array Int Int
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) ([Int] -> Array Int (Array Int [Int]))
-> [Int] -> Array Int (Array Int [Int])
forall a b. (a -> b) -> a -> b
$ [Int
2 .. Int
n]
{-# INLINE genDoublePermutationsArrN2 #-}
--{-# SPECIALIZE genDoublePermutationsArrN2 ::
--    Int -> Array Int (Array Int [Int])
--    #-}

genDoublePermutationsArr2 ::
    Array Int (Array Int [Int])
genDoublePermutationsArr2 :: Array Int (Array Int [Int])
genDoublePermutationsArr2 = Int -> Array Int (Array Int [Int])
genDoublePermutationsArrN2 Int
10
{-# INLINE genDoublePermutationsArr2 #-}
--{-# SPECIALIZE genDoublePermutationsArr2 :: Array Int (Array Int [Int]) #-}

genDoublePermutationsLN2 :: Int -> [Array Int Int]
genDoublePermutationsLN2 :: Int -> [Array Int Int]
genDoublePermutationsLN2 Int
n = ([Int] -> Array Int Int) -> [[Int]] -> [Array Int Int]
forall a b. (a -> b) -> [a] -> [b]
map (\[Int]
xs -> (Int, Int) -> [Int] -> Array Int Int
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Int]
xs) ([[Int]] -> [Array Int Int])
-> ([Int] -> [[Int]]) -> [Int] -> [Array Int Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [[Int]]
pairsSwapP2 ([Int] -> [[Int]]) -> ([Int] -> [Int]) -> [Int] -> [[Int]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
take Int
n ([Int] -> [Array Int Int]) -> [Int] -> [Array Int Int]
forall a b. (a -> b) -> a -> b
$ [Int
0 ..]
{-# INLINE genDoublePermutationsLN2 #-}
--{-# SPECIALIZE genDoublePermutationsLN2 :: Int -> [Array Int Int] #-}

genDoublePermutationsL2 :: [Array Int Int]
genDoublePermutationsL2 :: [Array Int Int]
genDoublePermutationsL2 = Int -> [Array Int Int]
genDoublePermutationsLN2 Int
10
{-# INLINE genDoublePermutationsL2 #-}
--{-# SPECIALIZE genDoublePermutationsL2 :: [Array Int Int] #-}

genDoublePermutationsArrLN2 ::
    Int -> Array Int [Array Int Int]
genDoublePermutationsArrLN2 :: Int -> Array Int [Array Int Int]
genDoublePermutationsArrLN2 Int
n = (Int -> [Array Int Int])
-> Array Int Int -> Array Int [Array Int Int]
forall a b i. (a -> b) -> Array i a -> Array i b
amap Int -> [Array Int Int]
genDoublePermutationsLN2 (Array Int Int -> Array Int [Array Int Int])
-> ([Int] -> Array Int Int) -> [Int] -> Array Int [Array Int Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> [Int] -> Array Int Int
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) ([Int] -> Array Int [Array Int Int])
-> [Int] -> Array Int [Array Int Int]
forall a b. (a -> b) -> a -> b
$ [Int
2 .. Int
n]
{-# INLINE genDoublePermutationsArrLN2 #-}
--{-# SPECIALIZE genDoublePermutationsArrLN2 ::
--    Int -> Array Int [Array Int Int]
--    #-}

genDoublePermutationsArrL2 ::
    Array Int [Array Int Int]
genDoublePermutationsArrL2 :: Array Int [Array Int Int]
genDoublePermutationsArrL2 = Int -> Array Int [Array Int Int]
genDoublePermutationsArrLN2 Int
10
{-# INLINE genDoublePermutationsArrL2 #-}
--{-# SPECIALIZE genDoublePermutationsArrL2 :: Array Int [Array Int Int] #-}