You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.9 KiB
105 lines
2.9 KiB
import os
|
|
from typing import Tuple as tTuple, Type
|
|
|
|
import mpmath.libmp as mlib
|
|
|
|
from sympy.external import import_module
|
|
|
|
__all__ = [
|
|
# GROUND_TYPES is either 'gmpy' or 'python' depending on which is used. If
|
|
# gmpy is installed then it will be used unless the environment variable
|
|
# SYMPY_GROUND_TYPES is set to something other than 'auto', 'gmpy', or
|
|
# 'gmpy2'.
|
|
'GROUND_TYPES',
|
|
|
|
# If HAS_GMPY is 0, no supported version of gmpy is available. Otherwise,
|
|
# HAS_GMPY will be 2 for gmpy2 if GROUND_TYPES is 'gmpy'. It used to be
|
|
# possible for HAS_GMPY to be 1 for gmpy but gmpy is no longer supported.
|
|
'HAS_GMPY',
|
|
|
|
# SYMPY_INTS is a tuple containing the base types for valid integer types.
|
|
# This is either (int,) or (int, type(mpz(0))) depending on GROUND_TYPES.
|
|
'SYMPY_INTS',
|
|
|
|
# MPQ is either gmpy.mpq or the Python equivalent from
|
|
# sympy.external.pythonmpq
|
|
'MPQ',
|
|
|
|
# MPZ is either gmpy.mpz or int.
|
|
'MPZ',
|
|
|
|
# Either the gmpy or the mpmath function
|
|
'factorial',
|
|
|
|
# isqrt from gmpy or mpmath
|
|
'sqrt',
|
|
]
|
|
|
|
|
|
#
|
|
# SYMPY_GROUND_TYPES can be gmpy, gmpy2, python or auto
|
|
#
|
|
GROUND_TYPES = os.environ.get('SYMPY_GROUND_TYPES', 'auto').lower()
|
|
|
|
|
|
#
|
|
# Try to import gmpy2 by default. If gmpy or gmpy2 is specified in
|
|
# SYMPY_GROUND_TYPES then warn if gmpy2 is not found. In all cases there is a
|
|
# fallback based on pure Python int and PythonMPQ that should still work fine.
|
|
#
|
|
if GROUND_TYPES in ('auto', 'gmpy', 'gmpy2'):
|
|
|
|
# Actually import gmpy2
|
|
gmpy = import_module('gmpy2', min_module_version='2.0.0',
|
|
module_version_attr='version', module_version_attr_call_args=())
|
|
|
|
# Warn if user explicitly asked for gmpy but it isn't available.
|
|
if gmpy is None and GROUND_TYPES in ('gmpy', 'gmpy2'):
|
|
from warnings import warn
|
|
warn("gmpy library is not installed, switching to 'python' ground types")
|
|
|
|
elif GROUND_TYPES == 'python':
|
|
|
|
# The user asked for Python so ignore gmpy2 module.
|
|
gmpy = None
|
|
|
|
else:
|
|
|
|
# Invalid value for SYMPY_GROUND_TYPES. Ignore the gmpy2 module.
|
|
from warnings import warn
|
|
warn("SYMPY_GROUND_TYPES environment variable unrecognised. "
|
|
"Should be 'python', 'auto', 'gmpy', or 'gmpy2'")
|
|
gmpy = None
|
|
|
|
|
|
#
|
|
# At this point gmpy will be None if gmpy2 was not successfully imported or if
|
|
# the environment variable SYMPY_GROUND_TYPES was set to 'python' (or some
|
|
# unrecognised value). The two blocks below define the values exported by this
|
|
# module in each case.
|
|
#
|
|
SYMPY_INTS: tTuple[Type, ...]
|
|
|
|
if gmpy is not None:
|
|
|
|
HAS_GMPY = 2
|
|
GROUND_TYPES = 'gmpy'
|
|
SYMPY_INTS = (int, type(gmpy.mpz(0)))
|
|
MPZ = gmpy.mpz
|
|
MPQ = gmpy.mpq
|
|
|
|
factorial = gmpy.fac
|
|
sqrt = gmpy.isqrt
|
|
|
|
else:
|
|
from .pythonmpq import PythonMPQ
|
|
|
|
HAS_GMPY = 0
|
|
GROUND_TYPES = 'python'
|
|
SYMPY_INTS = (int,)
|
|
MPZ = int
|
|
MPQ = PythonMPQ
|
|
|
|
factorial = lambda x: int(mlib.ifac(x))
|
|
sqrt = lambda x: int(mlib.isqrt(x))
|