-- | We compute the open CSM classes directly, generalizing Aluffi's argument
-- to the equivariant case:
--
-- First we compute the CSM of set of the distinct /ordered/ points, then
-- push that forward first with @delta_*@ then with @pi_*@ to get the
-- CSM of the distinct unordered points with given multiplicities.
--
-- After that, we can get the closed CSM classes by summing over the
-- strata in the closure.
--
-- This is faster, especially since we have a (recursive) formula for the 
-- CSM of the distinct ordered points.

{-# LANGUAGE BangPatterns, TypeSynonymInstances, FlexibleInstances #-}
module Math.RootLoci.CSM.Equivariant.Direct 
  ( directOpenCSM
  , directClosedCSM
  )
  where

--------------------------------------------------------------------------------

import Math.Combinat.Partitions.Integer

import qualified Data.Set as Set

import Math.RootLoci.Algebra
import Math.RootLoci.Geometry
import Math.RootLoci.Misc

import qualified Math.Algebra.Polynomial.FreeModule as ZMod

import Math.RootLoci.CSM.Equivariant.PushForward
import qualified Math.RootLoci.CSM.Equivariant.Ordered as Ordered

--------------------------------------------------------------------------------

-- | CSM class of the open strata.
--  
-- We just push-forward first with Delta then down with Pi the conjectured 
-- (recursive) formula for the CSM of the set of distinct ordered points
-- 
directOpenCSM :: ChernBase base => Partition -> ZMod (Gam base)
directOpenCSM :: Partition -> ZMod (Gam base)
directOpenCSM = (forall base.
 ChernBase base =>
 Partition -> FreeMod Integer (Gam base))
-> forall base.
   ChernBase base =>
   Partition -> FreeMod Integer (Gam base)
forall key (f :: * -> *) (g :: * -> *).
CacheKey key =>
(forall base. ChernBase base => key -> f (g base))
-> forall base. ChernBase base => key -> f (g base)
polyCache2 forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
directCalcOpenCSM where

  directCalcOpenCSM :: ChernBase base => Partition -> ZMod (Gam base)
  directCalcOpenCSM :: Partition -> ZMod (Gam base)
directCalcOpenCSM part :: Partition
part@(Partition [Int]
xs) = ZMod (Gam base)
result where
    m :: Int
m = Partition -> Int
partitionWeight Partition
part
    result :: ZMod (Gam base)
result   = Integer -> ZMod (Gam base) -> ZMod (Gam base)
forall b c.
(Ord b, Eq c, Integral c, Show c) =>
c -> FreeMod c b -> FreeMod c b
ZMod.divideByConst (Partition -> Integer
aut Partition
part) (ZMod (Gam base) -> ZMod (Gam base))
-> ZMod (Gam base) -> ZMod (Gam base)
forall a b. (a -> b) -> a -> b
$ Int -> ZMod (Eta base) -> ZMod (Gam base)
forall base.
ChernBase base =>
Int -> ZMod (Eta base) -> ZMod (Gam base)
pi_star Int
m ZMod (Eta base)
middle
    middle :: ZMod (Eta base)
middle   = Partition -> ZMod (Omega base) -> ZMod (Eta base)
forall base.
ChernBase base =>
Partition -> ZMod (Omega base) -> ZMod (Eta base)
delta_star_ Partition
part ZMod (Omega base)
distinct
    distinct :: ZMod (Omega base)
distinct = Int -> ZMod (Omega base)
forall base. ChernBase base => Int -> ZMod (Omega base)
Ordered.formulaDistinctCSM ([Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
xs)

--------------------------------------------------------------------------------

-- | To compute the CSM of the closed loci, we just some over the open strata
-- in the closure 
directClosedCSM :: ChernBase base => Partition -> ZMod (Gam base)
directClosedCSM :: Partition -> ZMod (Gam base)
directClosedCSM = (forall base.
 ChernBase base =>
 Partition -> FreeMod Integer (Gam base))
-> forall base.
   ChernBase base =>
   Partition -> FreeMod Integer (Gam base)
forall key (f :: * -> *) (g :: * -> *).
CacheKey key =>
(forall base. ChernBase base => key -> f (g base))
-> forall base. ChernBase base => key -> f (g base)
polyCache2 forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
calc where
  
  calc :: ChernBase base => Partition -> ZMod (Gam base)
  calc :: Partition -> ZMod (Gam base)
calc Partition
part = [ZMod (Gam base)] -> ZMod (Gam base)
forall b c. (Ord b, Eq c, Num c) => [FreeMod c b] -> FreeMod c b
ZMod.sum [ Partition -> ZMod (Gam base)
forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
directOpenCSM Partition
q | Partition
q <- Set Partition -> [Partition]
forall a. Set a -> [a]
Set.toList (Partition -> Set Partition
closureSet Partition
part) ] 

--------------------------------------------------------------------------------