{-# LANGUAGE BangPatterns, TypeApplications, ScopedTypeVariables, DataKinds #-}
module Math.Singular.Factory.Counting where
import Data.Proxy
import Math.Singular.Factory.Domains
import Math.Singular.Factory.Polynomial
import Math.Singular.Factory.GFTables
countAffineHypersurface :: FiniteDomain domain => Int -> Polynomial vars domain -> Int
countAffineHypersurface = go where
go !1 !p = countTrues [ polyIsZero (substitute1 1 (konst a) p) | a <- enumerateDomain ]
go !k !p = sum [ go (k-1) (substitute1 k (konst a) p) | a <- enumerateDomain ]
countProjectiveHypersurface :: FiniteDomain domain => Int -> Polynomial vars domain -> Int
countProjectiveHypersurface = go False where
go !isPos !1 !p = countTrues [ polyIsZero $ substitute1 1 (konst a) p | a <- projEnumerateDomain isPos , let b = isPos || not (isZero a) , b ]
go !isPos !k !p = sum [ go b (k-1) $ substitute1 k (konst a) p | a <- projEnumerateDomain isPos , let b = isPos || not (isZero a) ]
countAffineSolutions :: FiniteDomain domain => Int -> [Polynomial vars domain] -> Int
countAffineSolutions = go where
go !1 !ps = countTrues [ and $ map polyIsZero $ map (substitute1 1 (konst a)) ps | a <- enumerateDomain ]
go !k !ps = sum [ go (k-1) $ map (substitute1 k (konst a)) ps | a <- enumerateDomain ]
countProjectiveSolutions :: FiniteDomain domain => Int -> [Polynomial vars domain] -> Int
countProjectiveSolutions = go False where
go !isPos !1 !ps = countTrues [ and $ map polyIsZero $ map (substitute1 1 (konst a)) ps | a <- projEnumerateDomain isPos , let b = isPos || not (isZero a) , b ]
go !isPos !k !ps = sum [ go b (k-1) $ map (substitute1 k (konst a)) ps | a <- projEnumerateDomain isPos , let b = isPos || not (isZero a) ]
projEnumerateDomain :: FiniteDomain domain => Bool -> [domain]
projEnumerateDomain True = enumerateDomain
projEnumerateDomain False = [0,1]
countTrues :: [Bool] -> Int
countTrues = foldr f 0 where
f False !c = c
f True !c = c+1