{-|
Module      : Math.Algebra.JackSymbolicPol
Description : Jack polynomials with symbolic Jack parameter.
Copyright   : (c) Stéphane Laurent, 2024
License     : GPL-3
Maintainer  : laurent_step@outlook.fr

Computation of Jack polynomials with a symbolic Jack parameter. 
See README for examples and references.
-}

{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Math.Algebra.JackSymbolicPol
  ( jackSymbolicPol, jackSymbolicPol' )
  where
import           Prelude 
  hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger, recip)
import           Algebra.Additive           ( (+), (-), sum )
import           Algebra.Ring               ( (*), product )
import           Algebra.Field              ( recip )
import qualified Algebra.Field              as AlgField
import           Control.Lens               ( (.~), element )
import           Data.Array                 ( Array, (!), (//), listArray )
import           Data.Maybe                 ( fromJust, isJust )
import           Math.Algebra.Jack.Internal ( _betaRatioOfSprays
                                            , jackSymbolicCoeffC
                                            , jackSymbolicCoeffPinv
                                            , jackSymbolicCoeffQinv
                                            , _N, _isPartition, Partition )
import           Math.Algebra.Hspray        ( FunctionLike (..), (.^)
                                            , lone, lone'
                                            , ParametricSpray, ParametricQSpray
                                            , Spray, asRatioOfSprays
                                            , RatioOfSprays, unitRatioOfSprays
                                            , zeroSpray, unitSpray )

-- | Jack polynomial with symbolic Jack parameter

jackSymbolicPol' 
  :: Int       -- ^ number of variables

  -> Partition -- ^ partition of integers

  -> Char      -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@

  -> ParametricQSpray
jackSymbolicPol' :: Int -> Partition -> Char -> ParametricQSpray
jackSymbolicPol' = Int -> Partition -> Char -> ParametricQSpray
forall a.
(Eq a, C a) =>
Int -> Partition -> Char -> ParametricSpray a
jackSymbolicPol

-- | Jack polynomial with symbolic Jack parameter

jackSymbolicPol :: forall a. (Eq a, AlgField.C a) 
  => Int       -- ^ number of variables

  -> Partition -- ^ partition of integers

  -> Char      -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@

  -> ParametricSpray a
jackSymbolicPol :: forall a.
(Eq a, C a) =>
Int -> Partition -> Char -> ParametricSpray a
jackSymbolicPol Int
n Partition
lambda Char
which =
  case Partition -> Bool
_isPartition Partition
lambda of
    Bool
False -> [Char] -> ParametricSpray a
forall a. HasCallStack => [Char] -> a
error [Char]
"jackSymbolicPol: invalid integer partition"
    Bool
True -> case Char
which of 
      Char
'J' -> ParametricSpray a
resultJ
      Char
'C' -> Partition -> RatioOfSprays a
forall a. (Eq a, C a) => Partition -> RatioOfSprays a
jackSymbolicCoeffC Partition
lambda BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ ParametricSpray a
resultJ
      Char
'P' -> RatioOfSprays a -> RatioOfSprays a
forall a. C a => a -> a
recip (Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays (Partition -> Spray a
forall a. (Eq a, C a) => Partition -> Spray a
jackSymbolicCoeffPinv Partition
lambda)) BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ ParametricSpray a
resultJ 
      Char
'Q' -> RatioOfSprays a -> RatioOfSprays a
forall a. C a => a -> a
recip (Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays (Partition -> Spray a
forall a. (Eq a, C a) => Partition -> Spray a
jackSymbolicCoeffQinv Partition
lambda)) BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ ParametricSpray a
resultJ
      Char
_   -> [Char] -> ParametricSpray a
forall a. HasCallStack => [Char] -> a
error 
        [Char]
"jackSymbolicPol: please use 'J', 'C', 'P' or 'Q' for last argument"
      where
      alpha :: Spray a
alpha = Int -> Spray a
forall a. C a => Int -> Spray a
lone Int
1 :: Spray a
      resultJ :: ParametricSpray a
resultJ = Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (ParametricSpray a))
-> RatioOfSprays a
-> ParametricSpray a
jac Int
n Int
0 Partition
lambda Partition
lambda Array (Int, Int) (Maybe (ParametricSpray a))
forall {a}. Array (Int, Int) (Maybe a)
arr0 RatioOfSprays a
forall a. (C a, Eq a) => RatioOfSprays a
unitRatioOfSprays
      nll :: Int
nll = Partition -> Partition -> Int
_N Partition
lambda Partition
lambda
      -- x = map lone [1 .. n] :: [ParametricSpray a]

      arr0 :: Array (Int, Int) (Maybe a)
arr0 = ((Int, Int), (Int, Int)) -> [Maybe a] -> Array (Int, Int) (Maybe a)
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray ((Int
1, Int
1), (Int
nll, Int
n)) (Int -> Maybe a -> [Maybe a]
forall a. Int -> a -> [a]
replicate (Int
nll Int -> Int -> Int
forall a. C a => a -> a -> a
* Int
n) Maybe a
forall a. Maybe a
Nothing)
      theproduct :: Int -> RatioOfSprays a
      theproduct :: Int -> RatioOfSprays a
theproduct Int
nu0 = if Int
nu0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
        then RatioOfSprays a
forall a. (C a, Eq a) => RatioOfSprays a
unitRatioOfSprays
        else Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays (Spray a -> RatioOfSprays a) -> Spray a -> RatioOfSprays a
forall a b. (a -> b) -> a -> b
$ [Spray a] -> Spray a
forall a. C a => [a] -> a
product ([Spray a] -> Spray a) -> [Spray a] -> Spray a
forall a b. (a -> b) -> a -> b
$ (Int -> Spray a) -> Partition -> [Spray a]
forall a b. (a -> b) -> [a] -> [b]
map 
              (\Int
i -> Int
i Int -> Spray a -> Spray a
forall a. (C a, Eq a) => Int -> a -> a
.^ Spray a
alpha Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ Spray a
forall a. C a => Spray a
unitSpray) 
              [Int
1 .. Int
nu0Int -> Int -> Int
forall a. C a => a -> a -> a
-Int
1]
      jac :: Int -> Int -> Partition -> Partition 
             -> Array (Int,Int) (Maybe (ParametricSpray a)) 
             -> RatioOfSprays a -> ParametricSpray a
      jac :: Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (ParametricSpray a))
-> RatioOfSprays a
-> ParametricSpray a
jac Int
m Int
k Partition
mu Partition
nu Array (Int, Int) (Maybe (ParametricSpray a))
arr RatioOfSprays a
beta
        | Partition -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Partition
nu Bool -> Bool -> Bool
|| Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
|| Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = ParametricSpray a
forall a. C a => Spray a
unitSpray
        | Partition -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Partition
nu Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
m Bool -> Bool -> Bool
&& Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
m Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0      = ParametricSpray a
forall a. (Eq a, C a) => Spray a
zeroSpray
        | Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1                            = 
            Int -> RatioOfSprays a
theproduct (Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
0) BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ (Int -> Int -> ParametricSpray a
forall a. C a => Int -> Int -> Spray a
lone' Int
1 (Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)) 
        | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& Maybe (ParametricSpray a) -> Bool
forall a. Maybe a -> Bool
isJust (Array (Int, Int) (Maybe (ParametricSpray a))
arr Array (Int, Int) (Maybe (ParametricSpray a))
-> (Int, Int) -> Maybe (ParametricSpray a)
forall i e. Ix i => Array i e -> i -> e
! (Partition -> Partition -> Int
_N Partition
lambda Partition
nu, Int
m)) =
                      Maybe (ParametricSpray a) -> ParametricSpray a
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (ParametricSpray a) -> ParametricSpray a)
-> Maybe (ParametricSpray a) -> ParametricSpray a
forall a b. (a -> b) -> a -> b
$ Array (Int, Int) (Maybe (ParametricSpray a))
arr Array (Int, Int) (Maybe (ParametricSpray a))
-> (Int, Int) -> Maybe (ParametricSpray a)
forall i e. Ix i => Array i e -> i -> e
! (Partition -> Partition -> Int
_N Partition
lambda Partition
nu, Int
m)
        | Bool
otherwise = ParametricSpray a
s
          where
            s :: ParametricSpray a
s = ParametricSpray a -> Int -> ParametricSpray a
go (RatioOfSprays a
BaseRing (ParametricSpray a)
beta BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ (Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (ParametricSpray a))
-> RatioOfSprays a
-> ParametricSpray a
jac (Int
mInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) Int
0 Partition
nu Partition
nu Array (Int, Int) (Maybe (ParametricSpray a))
arr RatioOfSprays a
forall a. (C a, Eq a) => RatioOfSprays a
unitRatioOfSprays ParametricSpray a -> ParametricSpray a -> ParametricSpray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ 
                  (Int -> Int -> ParametricSpray a
forall a. C a => Int -> Int -> Spray a
lone' Int
m (Partition -> Int
forall a. C a => [a] -> a
sum Partition
mu Int -> Int -> Int
forall a. C a => a -> a -> a
- Partition -> Int
forall a. C a => [a] -> a
sum Partition
nu)))) (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 Int
k)
            go :: ParametricSpray a -> Int -> ParametricSpray a
            go :: ParametricSpray a -> Int -> ParametricSpray a
go !ParametricSpray a
ss Int
ii
              | Partition -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Partition
nu Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
ii Bool -> Bool -> Bool
|| Partition
nuPartition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!!(Int
iiInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = ParametricSpray a
ss
              | Bool
otherwise =
                let u :: Int
u = Partition
nuPartition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!!(Int
iiInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) in
                if Partition -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Partition
nu Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
ii Bool -> Bool -> Bool
&& Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
|| Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
ii
                  then
                    let nu' :: Partition
nu'   = (Int -> IndexedTraversal' Int Partition Int
forall (t :: * -> *) a.
Traversable t =>
Int -> IndexedTraversal' Int (t a) a
element (Int
iiInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) ((Int -> Identity Int) -> Partition -> Identity Partition)
-> Int -> Partition -> Partition
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Int
uInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) Partition
nu in
                    let gamma :: RatioOfSprays a
gamma = Partition -> Partition -> Int -> RatioOfSprays a
forall a.
(Eq a, C a) =>
Partition -> Partition -> Int -> RatioOfSprays a
_betaRatioOfSprays Partition
mu Partition
nu Int
ii RatioOfSprays a -> RatioOfSprays a -> RatioOfSprays a
forall a. C a => a -> a -> a
* RatioOfSprays a
beta in
                    if Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
                      then
                        ParametricSpray a -> Int -> ParametricSpray a
go (ParametricSpray a
ss ParametricSpray a -> ParametricSpray a -> ParametricSpray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (ParametricSpray a))
-> RatioOfSprays a
-> ParametricSpray a
jac Int
m Int
ii Partition
mu Partition
nu' Array (Int, Int) (Maybe (ParametricSpray a))
arr RatioOfSprays a
gamma) (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)
                      else
                        if Partition
nu' Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
                          then
                            ParametricSpray a -> Int -> ParametricSpray a
go (ParametricSpray a
ss ParametricSpray a -> ParametricSpray a -> ParametricSpray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ (RatioOfSprays a
BaseRing (ParametricSpray a)
gamma BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ (Int -> Int -> ParametricSpray a
forall a. C a => Int -> Int -> Spray a
lone' Int
m (Partition -> Int
forall a. C a => [a] -> a
sum Partition
mu)))) 
                                (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)
                          else
                            let arr' :: Array (Int, Int) (Maybe (ParametricSpray a))
arr' = Array (Int, Int) (Maybe (ParametricSpray a))
arr Array (Int, Int) (Maybe (ParametricSpray a))
-> [((Int, Int), Maybe (ParametricSpray a))]
-> Array (Int, Int) (Maybe (ParametricSpray a))
forall i e. Ix i => Array i e -> [(i, e)] -> Array i e
// [((Partition -> Partition -> Int
_N Partition
lambda Partition
nu, Int
m), ParametricSpray a -> Maybe (ParametricSpray a)
forall a. a -> Maybe a
Just ParametricSpray a
ss)] in
                            let jck :: ParametricSpray a
jck = 
                                  Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (ParametricSpray a))
-> RatioOfSprays a
-> ParametricSpray a
jac (Int
mInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) Int
0 Partition
nu' Partition
nu' Array (Int, Int) (Maybe (ParametricSpray a))
arr' RatioOfSprays a
forall a. (C a, Eq a) => RatioOfSprays a
unitRatioOfSprays in
                            let jck' :: ParametricSpray a
jck' = RatioOfSprays a
BaseRing (ParametricSpray a)
gamma BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ (ParametricSpray a
jck ParametricSpray a -> ParametricSpray a -> ParametricSpray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ 
                                        (Int -> Int -> ParametricSpray a
forall a. C a => Int -> Int -> Spray a
lone' Int
m (Partition -> Int
forall a. C a => [a] -> a
sum Partition
mu Int -> Int -> Int
forall a. C a => a -> a -> a
- Partition -> Int
forall a. C a => [a] -> a
sum Partition
nu'))) in
                            ParametricSpray a -> Int -> ParametricSpray a
go (ParametricSpray a
ss ParametricSpray a -> ParametricSpray a -> ParametricSpray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ ParametricSpray a
jck') (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)
                  else
                    ParametricSpray a -> Int -> ParametricSpray a
go ParametricSpray a
ss (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)