-- | Low-level bindings to singular-factory {-# LANGUAGE BangPatterns, EmptyDataDecls, ForeignFunctionInterface #-} module Math.Singular.Factory.Internal.CanonicalForm where -------------------------------------------------------------------------------- import Data.Word import Data.Ratio import Foreign.C import Foreign.Ptr import Foreign.ForeignPtr import Foreign.Marshal.Array import Numeric.GMP.Types import qualified Numeric.GMP.Utils as GMP -------------------------------------------------------------------------------- -- * types data Variable data CanonicalForm data Factor -- CFFactor data FactorList -- List type Var = ForeignPtr Variable type CF = ForeignPtr CanonicalForm type Fac = ForeignPtr Factor type FacList = ForeignPtr FactorList -------------------------------------------------------------------------------- -- * constants foreign import ccall "level_trans" c_level_trans :: CInt foreign import ccall "level_base" c_level_base :: CInt foreign import ccall "level_quot" c_level_quot :: CInt foreign import ccall "level_expr" c_level_expr :: CInt -------------------------------------------------------------------------------- -- * versions foreign import ccall "get_factory_version" c_get_factory_version :: Ptr CChar -> Int -> IO () foreign import ccall "get_package_version" c_get_package_version :: Ptr CChar -> Int -> IO () getFactoryVersion :: IO String getFactoryVersion = do let n = 16 allocaArray n $ \ptr -> do c_get_factory_version ptr n peekCString ptr getPackageVersion :: IO String getPackageVersion = do let n = 16 allocaArray n $ \ptr -> do c_get_package_version ptr n peekCString ptr foreign import ccall "have_FLINT" c_have_FLINT :: IO CInt foreign import ccall "have_NTL" c_have_NTL :: IO CInt foreign import ccall "have_GMP" c_have_GMP :: IO CInt -------------------------------------------------------------------------------- -- * config foreign import ccall "set_default_switches" c_set_default_switches :: IO () setDefaultSwitches :: IO () setDefaultSwitches = do c_set_default_switches -------------------------------------------------------------------------------- -- * memory management foreign import ccall "&free_var" varFinalizerPtr :: FunPtr (Ptr Variable -> IO ()) foreign import ccall "&free_cf" cfFinalizerPtr :: FunPtr (Ptr CanonicalForm -> IO ()) foreign import ccall "&free_fac" facFinalizerPtr :: FunPtr (Ptr Factor -> IO ()) foreign import ccall "&free_faclist" faclistFinalizerPtr :: FunPtr (Ptr FactorList -> IO ()) makeVar :: Ptr Variable -> IO Var makeVar = newForeignPtr varFinalizerPtr makeCF :: Ptr CanonicalForm -> IO CF makeCF = newForeignPtr cfFinalizerPtr makeFac :: Ptr Factor -> IO Fac makeFac = newForeignPtr facFinalizerPtr makeFacList :: Ptr FactorList -> IO FacList makeFacList = newForeignPtr faclistFinalizerPtr -------------------------------------------------------------------------------- -- * variables foreign import ccall "new_var_level" c_new_var_level :: CInt -> IO (Ptr Variable) foreign import ccall "new_var_name" c_new_var_name :: CChar -> IO (Ptr Variable) foreign import ccall "new_var_level_name" c_new_var_level_name :: CInt -> CChar -> IO (Ptr Variable) newVarL :: Int -> IO Var newVarL level = makeVar =<< c_new_var_level (fromIntegral level) newVarN :: Char -> IO Var newVarN name = makeVar =<< c_new_var_name (castCharToCChar name) newVarLN :: Int -> Char -> IO Var newVarLN level name = makeVar =<< c_new_var_level_name (fromIntegral level) (castCharToCChar name) newTransVar :: IO Var newTransVar = makeVar =<< c_new_var_level (c_level_trans) foreign import ccall "root_of" c_root_of :: Ptr CanonicalForm -> IO (Ptr Variable) newRootOf :: CF -> IO Var newRootOf cf = withForeignPtr cf $ \ptr -> makeVar =<< c_root_of ptr foreign import ccall "get_var_level" c_get_var_level :: Ptr Variable -> IO CInt foreign import ccall "get_var_name" c_get_var_name :: Ptr Variable -> IO CChar getVarLevel :: Var -> IO Int getVarLevel var = withForeignPtr var $ \ptr -> fromIntegral <$> (c_get_var_level ptr) getVarName :: Var -> IO Char getVarName var = withForeignPtr var $ \ptr -> castCCharToChar <$> (c_get_var_name ptr) foreign import ccall "has_mipo" c_has_mipo :: Ptr Variable -> IO CInt foreign import ccall "get_mipo" c_get_mipo :: Ptr Variable -> Ptr Variable -> IO (Ptr CanonicalForm) foreign import ccall "set_mipo" c_set_mipo :: Ptr Variable -> Ptr CanonicalForm -> IO () foreign import ccall "set_reduce" c_set_reduce :: Ptr Variable -> CInt -> IO () hasMinimalPoly :: Var -> IO Bool hasMinimalPoly var = withForeignPtr var $ \ptr -> liftBool (c_has_mipo ptr) getMinimalPoly :: Var -> Var -> IO CF getMinimalPoly var1 var2 = withForeignPtr var1 $ \ptr1 -> withForeignPtr var2 $ \ptr2 -> makeCF =<< c_get_mipo ptr1 ptr2 setReduceFlag :: Var -> Bool -> IO () setReduceFlag var flag = withForeignPtr var $ \ptr -> c_set_reduce ptr (if flag then 1 else 0) -------------------------------------------------------------------------------- -- * factors foreign import ccall "get_factor" c_get_factor :: Ptr Factor -> IO (Ptr CanonicalForm) getFactorCF :: Fac -> IO CF getFactorCF fac = withForeignPtr fac $ \ptr -> makeCF =<< c_get_factor ptr foreign import ccall "get_fac_expo" c_get_fac_expo :: Ptr Factor -> IO CInt getFactorExpo :: Fac -> IO Int getFactorExpo fac = withForeignPtr fac $ \ptr -> fromIntegral <$> c_get_fac_expo ptr unpackFactor :: Fac -> IO (CF,Int) unpackFactor fac = do cf <- getFactorCF fac expo <- getFactorExpo fac return (cf,expo) -------------------------------------------------------------------------------- -- * lists foreign import ccall "get_list_length" c_get_list_length :: Ptr FactorList -> IO CInt getListLength :: FacList -> IO Int getListLength faclist = withForeignPtr faclist $ \ptr -> fromIntegral <$> c_get_list_length ptr -------------------------------------------------------------------------------- -- * factorization foreign import ccall "flatten_faclist" c_flatten_faclist :: Ptr FactorList -> Ptr (Ptr Factor) -> IO () flattenFactorList :: FacList -> IO [Fac] flattenFactorList faclist = withForeignPtr faclist $ \listptr -> do n <- fromIntegral <$> c_get_list_length listptr allocaArray n $ \arrptr -> do c_flatten_faclist listptr arrptr facptrs <- peekArray n arrptr mapM makeFac facptrs unpackFactorList :: FacList -> IO [(CF,Int)] unpackFactorList faclist = mapM unpackFactor =<< flattenFactorList faclist foreign import ccall "hs_factorize" c_hs_factorize :: Ptr CanonicalForm -> IO (Ptr FactorList) factorizeIO' :: CF -> IO FacList factorizeIO' cf = withForeignPtr cf $ \ptr -> makeFacList =<< (c_hs_factorize ptr) factorizeIO :: CF -> IO [(CF,Int)] factorizeIO cf = unpackFactorList =<< factorizeIO' cf {- foreign import ccall "rat_factorize" c_rat_factorize :: Ptr CanonicalForm -> Ptr Variable -> CInt -> IO (Ptr FactorList) foreign import ccall "fq_factorize" c_fq_factorize :: Ptr CanonicalForm -> Ptr Variable -> CInt -> IO (Ptr FactorList) foreign import ccall "fp_factorize" c_fp_factorize :: Ptr CanonicalForm -> CInt -> IO (Ptr FactorList) foreign import ccall "gf_factorize" c_gf_factorize :: Ptr CanonicalForm -> CInt -> IO (Ptr FactorList) fpFactorizeIO' :: CF -> Bool -> IO FacList fpFactorizeIO' cf subst_check_flag = withForeignPtr cf $ \ptr -> makeFacList =<< (c_fp_factorize ptr (bool2cint subst_check_flag)) gfFactorizeIO' :: CF -> Bool -> IO FacList gfFactorizeIO' cf subst_check_flag = withForeignPtr cf $ \ptr -> makeFacList =<< (c_gf_factorize ptr (bool2cint subst_check_flag)) ratFactorizeIO' :: CF -> Var -> Bool -> IO FacList ratFactorizeIO' cf var subst_check_flag = withForeignPtr cf $ \ptr -> withForeignPtr var $ \varptr -> makeFacList =<< (c_rat_factorize ptr varptr (bool2cint subst_check_flag)) fqFactorizeIO' :: CF -> Var -> Bool -> IO FacList fqFactorizeIO' cf var subst_check_flag = withForeignPtr cf $ \ptr -> withForeignPtr var $ \varptr -> makeFacList =<< (c_fq_factorize ptr varptr (bool2cint subst_check_flag)) fpFactorizeIO :: CF -> Bool -> IO [(CF,Int)] fpFactorizeIO cf flag = unpackFactorList =<< fpFactorizeIO' cf flag gfFactorizeIO :: CF -> Bool -> IO [(CF,Int)] gfFactorizeIO cf flag = unpackFactorList =<< gfFactorizeIO' cf flag ratFactorizeIO :: CF -> Var -> Bool -> IO [(CF,Int)] ratFactorizeIO cf var flag = unpackFactorList =<< ratFactorizeIO' cf var flag fqFactorizeIO :: CF -> Var -> Bool -> IO [(CF,Int)] fqFactorizeIO cf var flag = unpackFactorList =<< fqFactorizeIO' cf var flag -} -------------------------------------------------------------------------------- -- * basic CFs foreign import ccall "empty_cf" c_empty_cf :: IO (Ptr CanonicalForm) newEmptyCF :: IO CF newEmptyCF = makeCF =<< c_empty_cf foreign import ccall "const_cf" c_const_cf :: CInt -> IO (Ptr CanonicalForm) newSmallConstCF :: Int -> IO CF newSmallConstCF k = makeCF =<< c_const_cf (fromIntegral k) foreign import ccall "var_cf" c_var_cf :: Ptr Variable -> IO (Ptr CanonicalForm) foreign import ccall "var_pow_cf" c_var_pow_cf :: Ptr Variable -> Int -> IO (Ptr CanonicalForm) varIO :: Var -> IO CF varIO var = withForeignPtr var $ \vptr -> makeCF =<< c_var_cf vptr varPowIO :: Var -> Int -> IO CF varPowIO var expo = withForeignPtr var $ \vptr -> makeCF =<< c_var_pow_cf vptr expo -------------------------------------------------------------------------------- -- * basic CF predicates bool2cint :: Bool -> CInt bool2cint True = 1 bool2cint False = 0 cint2bool :: CInt -> Bool cint2bool k = (k/=0) liftBool :: IO CInt -> IO Bool liftBool action = action >>= \k -> return (cint2bool k) ---------------------------------------- foreign import ccall "is_zero" c_is_zero :: Ptr CanonicalForm -> IO CInt foreign import ccall "is_one" c_is_one :: Ptr CanonicalForm -> IO CInt isZeroIO :: CF -> IO Bool isZeroIO cf = withForeignPtr cf $ \ptr -> liftBool (c_is_zero ptr) isOneIO :: CF -> IO Bool isOneIO cf = withForeignPtr cf $ \ptr -> liftBool (c_is_one ptr) foreign import ccall "is_imm" c_is_imm :: Ptr CanonicalForm -> IO CInt foreign import ccall "is_univariate" c_is_univariate :: Ptr CanonicalForm -> IO CInt isImmediateIO :: CF -> IO Bool isImmediateIO cf = withForeignPtr cf $ \ptr -> liftBool (c_is_imm ptr) isUnivariateIO :: CF -> IO Bool isUnivariateIO cf = withForeignPtr cf $ \ptr -> liftBool (c_is_univariate ptr) foreign import ccall "in_ZZ" c_in_ZZ :: Ptr CanonicalForm -> IO CInt foreign import ccall "in_QQ" c_in_QQ :: Ptr CanonicalForm -> IO CInt foreign import ccall "in_GF" c_in_GF :: Ptr CanonicalForm -> IO CInt foreign import ccall "in_FF" c_in_FF :: Ptr CanonicalForm -> IO CInt isInZZ_IO :: CF -> IO Bool isInZZ_IO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_ZZ ptr) isInQQ_IO :: CF -> IO Bool isInQQ_IO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_QQ ptr) isInGF_IO :: CF -> IO Bool isInGF_IO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_GF ptr) isInFF_IO :: CF -> IO Bool isInFF_IO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_FF ptr) foreign import ccall "in_BaseDomain" c_in_BaseDomain :: Ptr CanonicalForm -> IO CInt foreign import ccall "in_CoeffDomain" c_in_CoeffDomain :: Ptr CanonicalForm -> IO CInt foreign import ccall "in_PolyDomain" c_in_PolyDomain :: Ptr CanonicalForm -> IO CInt foreign import ccall "in_Extension" c_in_Extension :: Ptr CanonicalForm -> IO CInt foreign import ccall "in_QuotDomain" c_in_QuotDomain :: Ptr CanonicalForm -> IO CInt isInBaseDomainIO :: CF -> IO Bool isInBaseDomainIO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_BaseDomain ptr) isInCoeffDomainIO :: CF -> IO Bool isInCoeffDomainIO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_CoeffDomain ptr) isInPolyDomainIO :: CF -> IO Bool isInPolyDomainIO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_PolyDomain ptr) isInExtensionIO :: CF -> IO Bool isInExtensionIO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_Extension ptr) isInQuotDomainIO :: CF -> IO Bool isInQuotDomainIO cf = withForeignPtr cf $ \ptr -> liftBool (c_in_QuotDomain ptr) -------------------------------------------------------------------------------- -- * basic properties foreign import ccall "degree_of" c_degree_of :: Ptr CanonicalForm -> IO CInt foreign import ccall "level_of" c_level_of :: Ptr CanonicalForm -> IO CInt foreign import ccall "mvar_of" c_mvar_of :: Ptr CanonicalForm -> IO (Ptr Variable) getDegree :: CF -> IO Int getDegree cf = withForeignPtr cf $ \ptr -> fromIntegral <$> (c_degree_of ptr) getLevel :: CF -> IO Int getLevel cf = withForeignPtr cf $ \ptr -> fromIntegral <$> (c_level_of ptr) getMainVar :: CF -> IO Var getMainVar cf = withForeignPtr cf $ \ptr -> makeVar =<< (c_mvar_of ptr) -------------------------------------------------------------------------------- -- * small values foreign import ccall "smallint_value" c_smallint_value :: Ptr CanonicalForm -> IO CLong -- !!! getSmallIntValue :: CF -> IO Int getSmallIntValue cf = withForeignPtr cf $ \ptr -> fromIntegral <$> (c_smallint_value ptr) foreign import ccall "numer" c_numer :: Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "denom" c_denom :: Ptr CanonicalForm -> IO (Ptr CanonicalForm) getNumer :: CF -> IO CF getNumer cf = withForeignPtr cf $ \ptr -> makeCF =<< (c_numer ptr) getDenom :: CF -> IO CF getDenom cf = withForeignPtr cf $ \ptr -> makeCF =<< (c_denom ptr) foreign import ccall "index_poly" c_index_poly :: Ptr CanonicalForm -> Int -> IO (Ptr CanonicalForm) foreign import ccall "map_into" c_map_into :: Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "substitute" c_substitute :: Ptr CanonicalForm -> Ptr Variable -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) -------------------------------------------------------------------------------- -- * Polynomial operations -- | Get the given degree part getCfAtIndex :: CF -> Int -> IO CF getCfAtIndex cf idx = withForeignPtr cf $ \ptr -> makeCF =<< (c_index_poly ptr $ fromIntegral idx) -- | Map into the current base domain mapIntoIO :: CF -> IO CF mapIntoIO cf = withForeignPtr cf $ \ptr -> makeCF =<< (c_map_into ptr) -- | Map into the current base domain substituteIO :: Var -> CF -> (CF -> IO CF) substituteIO var what cf = withForeignPtr var $ \pvar -> withForeignPtr what $ \pwhat -> withForeignPtr cf $ \pcf -> makeCF =<< (c_substitute pcf pvar pwhat) -------------------------------------------------------------------------------- -- * Binary operations foreign import ccall "is_equal" c_is_equal :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO CInt isEqualIO :: CF -> CF -> IO Bool isEqualIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> liftBool (c_is_equal p q) foreign import ccall "plus_cf" c_plus_cf :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "minus_cf" c_minus_cf :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "times_cf" c_times_cf :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "pow_cf" c_pow_cf :: Ptr CanonicalForm -> CInt -> IO (Ptr CanonicalForm) foreign import ccall "div_cf" c_div_cf :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "mod_cf" c_mod_cf :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "gcd_poly_cf" c_gcd_poly_cf :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) foreign import ccall "reduce_cf" c_reduce_cf :: Ptr CanonicalForm -> Ptr CanonicalForm -> IO (Ptr CanonicalForm) plusIO :: CF -> CF -> IO CF plusIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> makeCF =<< (c_plus_cf p q) minusIO :: CF -> CF -> IO CF minusIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> makeCF =<< (c_minus_cf p q) timesIO :: CF -> CF -> IO CF timesIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> makeCF =<< (c_times_cf p q) powIO :: CF -> Int -> IO CF powIO x n = withForeignPtr x $ \p -> makeCF =<< (c_pow_cf p $ fromIntegral n) divIO :: CF -> CF -> IO CF divIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> makeCF =<< (c_div_cf p q) modIO :: CF -> CF -> IO CF modIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> makeCF =<< (c_mod_cf p q) gcdPolyIO :: CF -> CF -> IO CF gcdPolyIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> makeCF =<< (c_gcd_poly_cf p q) reduceIO :: CF -> CF -> IO CF reduceIO x y = withForeignPtr x $ \p -> withForeignPtr y $ \q -> makeCF =<< (c_reduce_cf p q) -------------------------------------------------------------------------------- -- * GMP compatibility layer foreign import ccall "get_gmp_numerator" c_get_gmp_numerator :: Ptr CanonicalForm -> Ptr MPZ -> IO () foreign import ccall "get_gmp_denominator" c_get_gmp_denominator :: Ptr CanonicalForm -> Ptr MPZ -> IO () getGmpNumerator :: CF -> IO Integer getGmpNumerator cf = withForeignPtr cf $ \cfp -> GMP.withOutInteger_ (\mpz_ptr -> c_get_gmp_numerator cfp mpz_ptr) getGmpDenominator :: CF -> IO Integer getGmpDenominator cf = withForeignPtr cf $ \cfp -> GMP.withOutInteger_ (\mpz_ptr -> c_get_gmp_denominator cfp mpz_ptr) foreign import ccall "make_ZZ_from_gmp" c_make_ZZ_from_gmp :: Ptr MPZ -> IO (Ptr CanonicalForm) foreign import ccall "make_QQ_from_gmp" c_make_QQ_from_gmp :: Ptr MPZ -> Ptr MPZ -> CInt -> IO (Ptr CanonicalForm) makeIntegerCF :: Integer -> IO CF makeIntegerCF n = GMP.withInInteger n $ \mpz_ptr -> makeCF =<< (c_make_ZZ_from_gmp mpz_ptr) makeRationalCF :: Rational -> IO CF makeRationalCF n = GMP.withInInteger (numerator n) $ \mpz_ptr1 -> GMP.withInInteger (denominator n) $ \mpz_ptr2 -> makeCF =<< (c_make_QQ_from_gmp mpz_ptr1 mpz_ptr2 0) -------------------------------------------------------------------------------- -- * Base domain characteristic foreign import ccall "get_characteristic" c_get_characteristic :: IO CInt foreign import ccall "set_characteristic1" c_set_characteristic1 :: CInt -> IO () -- foreign import ccall "set_characteristic2" c_set_characteristic2 :: CInt -> CInt -> IO () foreign import ccall "set_characteristic3" c_set_characteristic3 :: CInt -> CInt -> CChar -> IO () getCharacteristic :: IO Int getCharacteristic = fromIntegral <$> c_get_characteristic -- | prime fields and QQ setCharacteristic1 :: Int -> IO () setCharacteristic1 = c_set_characteristic1 . fromIntegral {- -- | prime power fields (meaning FF?) -- apparently they removed this ???? setCharacteristic2 :: Int -> Int -> IO () setCharacteristic2 p n = c_set_characteristic2 (fromIntegral p) (fromIntegral n) -} -- | Galois fields setCharacteristic3 :: Int -> Int -> Char -> IO () setCharacteristic3 p n ch = c_set_characteristic3 (fromIntegral p) (fromIntegral n) (castCharToCChar ch) foreign import ccall "get_gf_value" c_get_gf_value :: Ptr CanonicalForm -> IO CInt foreign import ccall "is_FF_in_GF" c_is_FF_in_GF :: Ptr CanonicalForm -> IO CInt foreign import ccall "get_GF_degree" c_get_GF_degree :: IO CInt foreign import ccall "get_GF_generator" c_get_GF_generator :: IO (Ptr CanonicalForm) -- | This returns the exponent of the canonical generator. -- If the input is zero, it appears to return the order of the field, q, but don't rely on this... getGFValue :: CF -> IO Int getGFValue cf = withForeignPtr cf $ \ptr -> fromIntegral <$> (c_get_gf_value ptr) -- | True if element of the prime subfield isFFinGF_IO :: CF -> IO Bool isFFinGF_IO cf = withForeignPtr cf $ \ptr -> liftBool (c_is_FF_in_GF ptr) -- | Returns the degree of the Galois field (degree of extension over the prime field) getGFDegree :: IO Int getGFDegree = fromIntegral <$> c_get_GF_degree -- | Returns the generator of the Galois field getGFGenerator :: IO CF getGFGenerator = makeCF =<< c_get_GF_generator --------------------------------------------------------------------------------