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

Computation of Jack polynomials, skew Jack polynomials, zonal polynomials, 
skew zonal polynomials, Schur polynomials and skew Schur polynomials. 
See README for examples and references.
-}

{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Math.Algebra.JackPol
  ( 
  -- * Jack and skew Jack polynomials

    jackPol
  , jackPol'
  , skewJackPol
  , skewJackPol'
  -- * Zonal and skew zonal polynomials

  , zonalPol
  , zonalPol'
  , skewZonalPol
  , skewZonalPol'
  -- * Schur and skew Schur polynomials

  , schurPol
  , schurPol'
  , skewSchurPol 
  , skewSchurPol'
  )
  where
import           Prelude 
  hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger)
import           Algebra.Additive           ( (+), (-), sum, zero )
import qualified Algebra.Field              as AlgField
import           Algebra.Ring               ( (*), product, one, fromInteger )
import qualified Algebra.Ring               as AlgRing
import           Control.Lens               ( (.~), element )
import           Data.Array                 ( Array, (!), (//), listArray )
import qualified Data.HashMap.Strict        as HM
import qualified Data.Map.Strict            as DM
import           Data.Maybe                 ( fromJust, isJust )
import           Math.Algebra.Jack.Internal ( _betaratio, jackCoeffC
                                            , _N, _isPartition, Partition
                                            , jackCoeffP, jackCoeffQ
                                            , skewSchurLRCoefficients
                                            , isSkewPartition, _fromInt
                                            , skewJackInMSPbasis
                                            , jackJpol0
                                            )
import           Math.Algebra.Hspray        ( FunctionLike (..), (.^)
                                            , lone, lone', Spray, QSpray
                                            , zeroSpray, unitSpray
                                            , fromList )
import           Math.Combinat.Permutations ( permuteMultiset )

-- | Jack polynomial.

jackPol' 
  :: Int       -- ^ number of variables

  -> Partition -- ^ integer partition 

  -> Rational  -- ^ Jack parameter

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

  -> QSpray
jackPol' :: Int -> Partition -> Rational -> Char -> QSpray
jackPol' = Int -> Partition -> Rational -> Char -> QSpray
forall a. (Eq a, C a) => Int -> Partition -> a -> Char -> Spray a
jackPol

-- | Jack polynomial.

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

  -> Partition -- ^ integer partition 

  -> a         -- ^ Jack parameter

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

  -> Spray a
jackPol :: forall a. (Eq a, C a) => Int -> Partition -> a -> Char -> Spray a
jackPol Int
n Partition
lambda a
alpha Char
which 
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"jackPol: negative number of variables."
  | Bool -> Bool
not (Partition -> Bool
_isPartition Partition
lambda) = [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"jackPol: invalid integer partition."
  | Bool -> Bool
not (Char
which Char -> [Char] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'J', Char
'C', Char
'P', Char
'Q']) = 
      [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"jackPol: please use 'J', 'C', 'P' or 'Q' for last argument."
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = if Partition -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Partition
lambda
      then Spray a
forall a. C a => Spray a
unitSpray
      else Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  | Bool
otherwise =
    case Char
which of 
      Char
'J' -> Spray a
resultJ
      Char
'C' -> Partition -> a -> a
forall a. C a => Partition -> a -> a
jackCoeffC Partition
lambda a
alpha BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
resultJ
      Char
'P' -> Partition -> a -> a
forall a. C a => Partition -> a -> a
jackCoeffP Partition
lambda a
alpha BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
resultJ
      Char
_   -> Partition -> a -> a
forall a. C a => Partition -> a -> a
jackCoeffQ Partition
lambda a
alpha BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
resultJ
      where
      resultJ :: Spray a
resultJ = 
        if a
alpha a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
zero
          then Int -> Partition -> Spray a
forall a. (C a, Eq a) => Int -> Partition -> Spray a
jackJpol0 Int
n Partition
lambda
          else Int -> Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
jck Int
n Partition
lambda Array (Int, Int) (Maybe (Spray a))
forall {a}. Array (Int, Int) (Maybe a)
arr0 
      jck :: Int -> Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
jck Int
m Partition
kappa Array (Int, Int) (Maybe (Spray a))
arr = Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (Spray a))
-> Spray a
jac Int
m Int
0 Partition
kappa Partition
kappa Array (Int, Int) (Maybe (Spray a))
arr 
      nll :: Int
nll = Partition -> Partition -> Int
_N Partition
lambda Partition
lambda
      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)
      jac :: Int -> Int -> Partition -> Partition 
             -> Array (Int,Int) (Maybe (Spray a)) 
             -> Spray a
      jac :: Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (Spray a))
-> Spray a
jac Int
m Int
k Partition
mu Partition
nu Array (Int, Int) (Maybe (Spray a))
arr 
        | Partition -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Partition
nu Bool -> Bool -> Bool
|| Int
nu0 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 = Spray a
forall a. C a => Spray a
unitSpray
        | Int
ellNu 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      = Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
        | Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1                        = 
            if Int
nu0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
              then 
                Int -> Spray a
forall a. C a => Int -> Spray a
lone Int
1
              else 
                let as :: [a]
as = [Int
i Int -> a -> a
forall a. (C a, Eq a) => Int -> a -> a
.^ a
alpha a -> a -> a
forall a. C a => a -> a -> a
+ a
forall a. C a => a
one | Int
i <- [Int
1 .. Int
nu0Int -> Int -> Int
forall a. C a => a -> a -> a
-Int
1]] in
                [a] -> a
forall a. C a => [a] -> a
product [a]
as BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Int -> Spray a
x Int
nu0
        | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& Maybe (Spray a) -> Bool
forall a. Maybe a -> Bool
isJust Maybe (Spray a)
maybe_spray =
            Maybe (Spray a) -> Spray a
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (Spray a) -> Spray a) -> Maybe (Spray a) -> Spray a
forall a b. (a -> b) -> a -> b
$ Maybe (Spray a)
maybe_spray
        | Bool
otherwise = Spray a
s
          where
            nu0 :: Int
nu0 = Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
0
            ellNu :: Int
ellNu = Partition -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Partition
nu
            x :: Int -> Spray a
x = Int -> Int -> Spray a
forall a. C a => Int -> Int -> Spray a
lone' Int
m
            _N_lambda_nu_m :: (Int, Int)
_N_lambda_nu_m = (Partition -> Partition -> Int
_N Partition
lambda Partition
nu, Int
m)
            maybe_spray :: Maybe (Spray a)
maybe_spray = Array (Int, Int) (Maybe (Spray a))
arr Array (Int, Int) (Maybe (Spray a)) -> (Int, Int) -> Maybe (Spray a)
forall i e. Ix i => Array i e -> i -> e
! (Int, Int)
_N_lambda_nu_m
            wMu :: Int
wMu = Partition -> Int
forall a. C a => [a] -> a
sum Partition
mu
            jck' :: Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
jck' Partition
kappa Array (Int, Int) (Maybe (Spray a))
array = Int -> Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
jck (Int
mInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) Partition
kappa Array (Int, Int) (Maybe (Spray a))
array Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Int -> Spray a
x (Int
wMu Int -> Int -> Int
forall a. C a => a -> a -> a
- Partition -> Int
forall a. C a => [a] -> a
sum Partition
kappa)
            s :: Spray a
s = Spray a -> Int -> Spray a
go (Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
jck' Partition
nu Array (Int, Int) (Maybe (Spray a))
arr) (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 Int
k)
            go :: Spray a -> Int -> Spray a
            go :: Spray a -> Int -> Spray a
go !Spray a
ss Int
ii
              | Int
ellNu Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
ii Bool -> Bool -> Bool
|| Int
u Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = 
                  Spray a
ss
              | Int
ellNu 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 = 
                  Spray a -> Int -> Spray a
go (Spray a
ss Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ Spray a
tt) (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)
              | Bool
otherwise = 
                  Spray a -> Int -> Spray a
go Spray a
ss (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)
                where
                  jj :: Int
jj = Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
- Int
1
                  u :: Int
u = Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
jj
                  nu' :: Partition
nu' = (Int -> IndexedTraversal' Int Partition Int
forall (t :: * -> *) a.
Traversable t =>
Int -> IndexedTraversal' Int (t a) a
element Int
jj ((Int -> Identity Int) -> Partition -> Identity Partition)
-> Int -> Partition -> Partition
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Int
u Int -> Int -> Int
forall a. C a => a -> a -> a
- Int
1) Partition
nu
                  gamma :: a
gamma = Partition -> Partition -> Int -> a -> a
forall a. C a => Partition -> Partition -> Int -> a -> a
_betaratio Partition
mu Partition
nu Int
ii a
alpha
                  tt :: Spray a
tt = a
BaseRing (Spray a)
gamma BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
spray
                    where
                      spray :: Spray a
spray
                        | Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 =
                            Int
-> Int
-> Partition
-> Partition
-> Array (Int, Int) (Maybe (Spray a))
-> Spray a
jac Int
m Int
ii Partition
mu Partition
nu' Array (Int, Int) (Maybe (Spray a))
arr 
                        | 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 =
                            Int -> Spray a
x Int
wMu
                        | Bool
otherwise =
                            Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
jck' Partition
nu' (Array (Int, Int) (Maybe (Spray a))
arr Array (Int, Int) (Maybe (Spray a))
-> [((Int, Int), Maybe (Spray a))]
-> Array (Int, Int) (Maybe (Spray a))
forall i e. Ix i => Array i e -> [(i, e)] -> Array i e
// [((Int, Int)
_N_lambda_nu_m, Spray a -> Maybe (Spray a)
forall a. a -> Maybe a
Just Spray a
ss)]) 

-- | Skew Jack polynomial.

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

  -> Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> a         -- ^ Jack parameter

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

  -> Spray a
skewJackPol :: forall a.
(Eq a, C a) =>
Int -> Partition -> Partition -> a -> Char -> Spray a
skewJackPol Int
n Partition
lambda Partition
mu a
alpha Char
which 
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = 
      [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"skewJackPol: negative number of variables."
  | Bool -> Bool
not (Partition -> Partition -> Bool
isSkewPartition Partition
lambda Partition
mu) = 
      [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"skewJackPol: invalid skew partition."
  | Bool -> Bool
not (Char
which Char -> [Char] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'J', Char
'C', Char
'P', Char
'Q']) = 
      [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"skewJackPol: please use 'J', 'C', 'P' or 'Q' for last argument."
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = 
      if Partition
lambda Partition -> Partition -> Bool
forall a. Eq a => a -> a -> Bool
== Partition
mu then Spray a
forall a. C a => Spray a
unitSpray else Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  | Bool
otherwise =
      [Spray a] -> Spray a
forall k v. Eq k => [HashMap k v] -> HashMap k v
HM.unions [Spray a]
sprays
  where
    msCombo :: Map Partition (Int, a)
msCombo = 
      ((Int, a) -> Bool)
-> Map Partition (Int, a) -> Map Partition (Int, a)
forall a k. (a -> Bool) -> Map k a -> Map k a
DM.filter
        ((Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n) (Int -> Bool) -> ((Int, a) -> Int) -> (Int, a) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, a) -> Int
forall a b. (a, b) -> a
fst)
          (a -> Char -> Partition -> Partition -> Map Partition (Int, a)
forall a.
(Eq a, C a) =>
a -> Char -> Partition -> Partition -> Map Partition (Int, a)
skewJackInMSPbasis a
alpha Char
which Partition
lambda Partition
mu)
    sprays :: [Spray a]
sprays = 
      ((Partition, (Int, a)) -> Spray a)
-> [(Partition, (Int, a))] -> [Spray a]
forall a b. (a -> b) -> [a] -> [b]
map (
        \(Partition
kappa, (Int
l, a
coeff)) -> 
            [(Partition, a)] -> Spray a
forall a. (C a, Eq a) => [(Partition, a)] -> Spray a
fromList
              ([Partition] -> [a] -> [(Partition, a)]
forall a b. [a] -> [b] -> [(a, b)]
zip 
                (Partition -> [Partition]
forall a. (Eq a, Ord a) => [a] -> [[a]]
permuteMultiset (Partition
kappa Partition -> Partition -> Partition
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Partition
forall a. Int -> a -> [a]
replicate (Int
n Int -> Int -> Int
forall a. C a => a -> a -> a
- Int
l) Int
0)) 
                (a -> [a]
forall a. a -> [a]
repeat a
coeff))
        ) (Map Partition (Int, a) -> [(Partition, (Int, a))]
forall k a. Map k a -> [(k, a)]
DM.assocs Map Partition (Int, a)
msCombo)

-- | Skew Jack polynomial.

skewJackPol' :: 
     Int       -- ^ number of variables

  -> Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> Rational  -- ^ Jack parameter

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

  -> QSpray
skewJackPol' :: Int -> Partition -> Partition -> Rational -> Char -> QSpray
skewJackPol' = Int -> Partition -> Partition -> Rational -> Char -> QSpray
forall a.
(Eq a, C a) =>
Int -> Partition -> Partition -> a -> Char -> Spray a
skewJackPol

-- | Zonal polynomial. The zonal polynomials are the 

-- Jack \(C\)-polynomials with Jack parameter \(\alpha=2\).

zonalPol' 
  :: Int       -- ^ number of variables

  -> Partition -- ^ partition of integers

  -> QSpray
zonalPol' :: Int -> Partition -> QSpray
zonalPol' = Int -> Partition -> QSpray
forall a. (Eq a, C a) => Int -> Partition -> Spray a
zonalPol

-- | Zonal polynomial. The zonal polynomials are the 

-- Jack \(C\)-polynomials with Jack parameter \(\alpha=2\).

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

  -> Partition -- ^ partition of integers

  -> Spray a
zonalPol :: forall a. (Eq a, C a) => Int -> Partition -> Spray a
zonalPol Int
n Partition
lambda = 
  Int -> Partition -> a -> Char -> Spray a
forall a. (Eq a, C a) => Int -> Partition -> a -> Char -> Spray a
jackPol Int
n Partition
lambda (Integer -> a
forall a. C a => Integer -> a
fromInteger Integer
2) Char
'C'

-- | Skew zonal polynomial.

skewZonalPol' 
  :: Int       -- ^ number of variables

  -> Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> QSpray
skewZonalPol' :: Int -> Partition -> Partition -> QSpray
skewZonalPol' = Int -> Partition -> Partition -> QSpray
forall a. (Eq a, C a) => Int -> Partition -> Partition -> Spray a
skewZonalPol

-- | Skew zonal polynomial.

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

  -> Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> Spray a
skewZonalPol :: forall a. (Eq a, C a) => Int -> Partition -> Partition -> Spray a
skewZonalPol Int
n Partition
lambda Partition
mu = 
  Int -> Partition -> Partition -> a -> Char -> Spray a
forall a.
(Eq a, C a) =>
Int -> Partition -> Partition -> a -> Char -> Spray a
skewJackPol Int
n Partition
lambda Partition
mu (Integer -> a
forall a. C a => Integer -> a
fromInteger Integer
2) Char
'C'

-- | Schur polynomial. The Schur polynomials are the 

-- Jack \(P\)-polynomials with Jack parameter \(\alpha=1\).

schurPol' 
  :: Int       -- ^ number of variables

  -> Partition -- ^ partition of integers

  -> QSpray 
schurPol' :: Int -> Partition -> QSpray
schurPol' = Int -> Partition -> QSpray
forall a. (Eq a, C a) => Int -> Partition -> Spray a
schurPol

-- | Schur polynomial. The Schur polynomials are the 

-- Jack \(P\)-polynomials with Jack parameter \(\alpha=1\).

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

  -> Partition -- ^ partition of integers

  -> Spray a
schurPol :: forall a. (Eq a, C a) => Int -> Partition -> Spray a
schurPol Int
n Partition
lambda 
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"schurPol: negative number of variables."
  | Bool -> Bool
not (Partition -> Bool
_isPartition Partition
lambda) = 
      [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"schurPol: invalid integer partition."
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = if Partition -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Partition
lambda then Spray a
forall a. C a => Spray a
unitSpray else Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  | Bool
otherwise = Int
-> Int
-> Partition
-> Array (Int, Int) (Maybe (Spray a))
-> Spray a
sch Int
n Int
1 Partition
lambda Array (Int, Int) (Maybe (Spray a))
forall {a}. Array (Int, Int) (Maybe a)
arr0
      where
        nll :: Int
nll = Partition -> Partition -> Int
_N Partition
lambda Partition
lambda
        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)
        sch :: 
          Int -> Int -> [Int] -> Array (Int,Int) (Maybe (Spray a)) -> Spray a
        sch :: Int
-> Int
-> Partition
-> Array (Int, Int) (Maybe (Spray a))
-> Spray a
sch Int
m Int
k Partition
nu Array (Int, Int) (Maybe (Spray a))
arr
          | Partition -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Partition
nu Bool -> Bool -> Bool
|| Int
nu0 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 = Spray a
forall a. C a => Spray a
unitSpray
          | Int
ellNu 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 = Spray 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 -> Int -> Spray a
forall a. C a => Int -> Int -> Spray a
lone' Int
1 Int
nu0
          | Maybe (Spray a) -> Bool
forall a. Maybe a -> Bool
isJust Maybe (Spray a)
maybe_spray = 
              Maybe (Spray a) -> Spray a
forall a. HasCallStack => Maybe a -> a
fromJust Maybe (Spray a)
maybe_spray
          | Bool
otherwise = Spray a
s
            where
              nu0 :: Int
nu0 = Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
0
              ellNu :: Int
ellNu = Partition -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Partition
nu
              x :: Spray a
x = Int -> Spray a
forall a. C a => Int -> Spray a
lone Int
m
              _N_lambda_nu_m :: (Int, Int)
_N_lambda_nu_m = (Partition -> Partition -> Int
_N Partition
lambda Partition
nu, Int
m)
              maybe_spray :: Maybe (Spray a)
maybe_spray = Array (Int, Int) (Maybe (Spray a))
arr Array (Int, Int) (Maybe (Spray a)) -> (Int, Int) -> Maybe (Spray a)
forall i e. Ix i => Array i e -> i -> e
! (Int, Int)
_N_lambda_nu_m
              sch' :: Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
sch' Partition
kappa Array (Int, Int) (Maybe (Spray a))
array = Int
-> Int
-> Partition
-> Array (Int, Int) (Maybe (Spray a))
-> Spray a
sch (Int
mInt -> Int -> Int
forall a. C a => a -> a -> a
-Int
1) Int
1 Partition
kappa Array (Int, Int) (Maybe (Spray a))
array 
              s :: Spray a
s = Spray a -> Int -> Spray a
go (Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
sch' Partition
nu Array (Int, Int) (Maybe (Spray a))
arr) Int
k
              go :: Spray a -> Int -> Spray a
              go :: Spray a -> Int -> Spray a
go !Spray a
ss Int
ii
                | Int
ellNu Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
ii Bool -> Bool -> Bool
|| Int
u Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = 
                    Spray a
ss
                | Int
ellNu 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 = 
                    Spray a -> Int -> Spray a
go (Spray a
ss Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ Spray a
tt) (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)
                | Bool
otherwise = 
                    Spray a -> Int -> Spray a
go Spray a
ss (Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
+ Int
1)
                  where
                    jj :: Int
jj = Int
ii Int -> Int -> Int
forall a. C a => a -> a -> a
- Int
1
                    u :: Int
u = Partition
nu Partition -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
jj
                    nu' :: Partition
nu' = (Int -> IndexedTraversal' Int Partition Int
forall (t :: * -> *) a.
Traversable t =>
Int -> IndexedTraversal' Int (t a) a
element Int
jj ((Int -> Identity Int) -> Partition -> Identity Partition)
-> Int -> Partition -> Partition
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Int
u Int -> Int -> Int
forall a. C a => a -> a -> a
- Int
1) Partition
nu
                    tt :: Spray a
tt 
                      | Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 =
                          Spray a
x Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Int
-> Int
-> Partition
-> Array (Int, Int) (Maybe (Spray a))
-> Spray a
sch Int
m Int
ii Partition
nu' Array (Int, Int) (Maybe (Spray a))
arr
                      | 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 =
                          Spray a
x 
                      | Bool
otherwise =
                          Spray a
x Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Partition -> Array (Int, Int) (Maybe (Spray a)) -> Spray a
sch' Partition
nu' (Array (Int, Int) (Maybe (Spray a))
arr Array (Int, Int) (Maybe (Spray a))
-> [((Int, Int), Maybe (Spray a))]
-> Array (Int, Int) (Maybe (Spray a))
forall i e. Ix i => Array i e -> [(i, e)] -> Array i e
// [((Int, Int)
_N_lambda_nu_m, Spray a -> Maybe (Spray a)
forall a. a -> Maybe a
Just Spray a
ss)]) 

-- | Skew Schur polynomial

skewSchurPol' 
  :: Int       -- ^ number of variables

  -> Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> QSpray
skewSchurPol' :: Int -> Partition -> Partition -> QSpray
skewSchurPol' = Int -> Partition -> Partition -> QSpray
forall a. (Eq a, C a) => Int -> Partition -> Partition -> Spray a
skewSchurPol

-- | Skew Schur polynomial

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

  -> Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> Spray a
skewSchurPol :: forall a. (Eq a, C a) => Int -> Partition -> Partition -> Spray a
skewSchurPol Int
n Partition
lambda Partition
mu =
  case Partition -> Partition -> Bool
isSkewPartition Partition
lambda Partition
mu of
    Bool
False -> [Char] -> Spray a
forall a. HasCallStack => [Char] -> a
error [Char]
"skewSchurPol: invalid skew partition."
    Bool
True  -> (Spray a -> Partition -> Int -> Spray a)
-> Spray a -> Map Partition Int -> Spray a
forall a k b. (a -> k -> b -> a) -> a -> Map k b -> a
DM.foldlWithKey' Spray a -> Partition -> Int -> Spray a
f Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray Map Partition Int
lrCoefficients
  where
    lrCoefficients :: Map Partition Int
lrCoefficients = Partition -> Partition -> Map Partition Int
skewSchurLRCoefficients Partition
lambda Partition
mu
    f :: Spray a -> Partition -> Int -> Spray a
    f :: Spray a -> Partition -> Int -> Spray a
f Spray a
spray Partition
nu Int
k = Spray a
spray Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ (Int -> a
forall a. (C a, Eq a) => Int -> a
_fromInt Int
k) BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ (Int -> Partition -> Spray a
forall a. (Eq a, C a) => Int -> Partition -> Spray a
schurPol Int
n Partition
nu)