GMPY2(3) | gmpy2 | GMPY2(3) |
gmpy2 - gmpy2 Documentation
Contents:
gmpy2 is a C-coded Python extension module that supports multiple-precision arithmetic. gmpy2 is the successor to the original gmpy module. The gmpy module only supported the GMP multiple-precision library. gmpy2 adds support for the MPFR (correctly rounded real floating-point arithmetic) and MPC (correctly rounded complex floating-point arithmetic) libraries. gmpy2 also updates the API and naming conventions to be more consistent and support the additional functionality.
The following libraries are supported:
Home page: http://gmplib.org
Home page: http://www.mpir.org
Home page: http://www.mpfr.org
Home page: http://mpc.multiprecision.org
mpz_lucas: http://sourceforge.net/projects/mpzlucas/
mpz_prp: http://sourceforge.net/projects/mpzprp/
This manual documents the two major versions of gmpy2. Sections that are specific to a particular version will be identified as such.
The 2.0 version is the stable release that only receives bug fixes and very minor updates. Version 2.1 is currently under active development and includes several new capabilities. Most gmpy2 2.0 code should run unchanged with gmpy2 2.1.
The most significant change in gmpy2 2.1 is support for thread-safe contexts. This change required extensive refactoring of almost all internal functions.
Please see the History chapter for a detail list of the changes.
Pre-compiled versions of gmpy2 2.0.8 are available at https://pypi.org/project/gmpy2/.
A pre-compiled version of gmpy2 2.1.0a1 is available at https://pypi.org/project/gmpy2/2.1.0a1/. Updated Windows versions should be available again beginning with version 2.1.0b1.
gmpy2 has only been tested with the most recent versions of GMP, MPFR and MPC. Specifically, for integer and rational support, gmpy2 requires GMP 5.0.x or later. To support multiple-precision floating point arithmetic, MPFR 3.1.x or later is required. MPC 1.0.1 or later is required for complex arithmetic.
gmpy2 requires the development files for GMP, MPFR, and MPC. The actual package that provides these files varies between Linux distributions. Installing "libmpc-dev" (or its equivalent) is usually sufficient.
If your system has the development libraries installed, compiling should be as simple as:
cd <gmpy2 source directory> python setup.py build_ext --force install --force
If this fails, read on.
Note: You really shouldn't need to do this. Unless you need the capabilities provided a newer GMP/MPFR/MPC, you should use the versions provided by your distribution.
If your Linux distribution does not support recent versions of GMP, MPFR and MPC, you will need to compile your own versions. To avoid any possible conflict with existing libraries on your system, it is recommended to use a directory not normally used by your distribution.
Create the desired destination directory for GMP, MPFR, and MPC.
$ mkdir /home/<<your username>>/local
Download and un-tar the GMP source code. Change to the GMP source directory and compile GMP.
$ cd /home/<<your username>>/local/src/gmp-6.1.2 $ ./configure --prefix=/home/<<your username>>/local $ make $ make check $ make install
Download and un-tar the MPFR source code. Change to the MPFR source directory and compile MPFR.
$ cd /home/<<your username>>/local/src/mpfr-4.0.1 $ ./configure --prefix=/home/<<your username>>/local --with-gmp=/home/<<your username>>/local $ make $ make check $ make install
Download and un-tar the MPC source code. Change to the MPC source directory and compile MPC.
$ cd /home/<<your username>>/local/src/mpc-1.1.0 $ ./configure --prefix=/home/<<your username>>/local --with-gmp=/home/<<your username>>/local --with-mpfr=/home/<<your username>>/local $ make $ make check $ make install
Compile gmpy2 and specify the location of GMP, MPFR and MPC. The location of the GMP, MPFR, and MPC libraries is embedded into the gmpy2 library so the new versions of GMP, MPFR, and MPC do not need to be installed the system library directories. The prefix directory is added to the beginning of the directories that are checked so it will be found first.
$ python setup.py install --prefix=/home/case/local
If you get a "permission denied" error message, you may need to use:
$ python setup.py build --prefix=/home/case/local $ sudo python setup.py install --prefix=/home/case/local
The mpz type is compatible with Python's built-in int/long type but is significantly faster for large values. The cutover point for performance varies, but can be as low as 20 to 40 digits. A variety of additional integer functions are provided.
>>> import gmpy2 >>> from gmpy2 import mpz,mpq,mpfr,mpc >>> mpz(99) * 43 mpz(4257) >>> pow(mpz(99), 37, 59) mpz(18) >>> gmpy2.isqrt(99) mpz(9) >>> gmpy2.isqrt_rem(99) (mpz(9), mpz(18)) >>> gmpy2.gcd(123,27) mpz(3) >>> gmpy2.lcm(123,27) mpz(1107)
The mpq type is compatible with the fractions.Fraction type included with Python.
>>> mpq(3,7)/7 mpq(3,49) >>> mpq(45,3) * mpq(11,8) mpq(165,8)
The most significant new features in gmpy2 are support for correctly rounded arbitrary precision real and complex arithmetic based on the MPFR and MPC libraries. Floating point contexts are used to control exceptional conditions. For example, division by zero can either return an Infinity or raise an exception.
>>> mpfr(1)/7 mpfr('0.14285714285714285') >>> gmpy2.get_context().precision=200 >>> mpfr(1)/7 mpfr('0.1428571428571428571428571428571428571428571428571428571428571',200) >>> gmpy2.get_context() context(precision=200, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=True,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=False) >>> mpfr(1)/0 mpfr('inf') >>> gmpy2.get_context().trap_divzero=True >>> mpfr(1)/0 Traceback (most recent call last):
File "<stdin>", line 1, in <module> gmpy2.DivisionByZeroError: 'mpfr' division by zero in division >>> gmpy2.get_context() context(precision=200, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=True,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=True, divzero=True,
trap_expbound=False,
allow_complex=False) >>> gmpy2.sqrt(mpfr(-2)) mpfr('nan') >>> gmpy2.get_context().allow_complex=True >>> gmpy2.get_context().precision=53 >>> gmpy2.sqrt(mpfr(-2)) mpc('0.0+1.4142135623730951j') >>> >>> gmpy2.set_context(gmpy2.context()) >>> with gmpy2.local_context() as ctx: ... print(gmpy2.const_pi()) ... ctx.precision+=20 ... print(gmpy2.const_pi()) ... ctx.precision+=20 ... print(gmpy2.const_pi()) ... 3.1415926535897931 3.1415926535897932384628 3.1415926535897932384626433831 >>> print(gmpy2.const_pi()) 3.1415926535897931 >>>
gmpy2 maintains an internal list of freed mpz, xmpz, mpq, mpfr, and mpc objects for reuse. The cache significantly improves performance but also increases the memory footprint.
NOTE:
The gmpy2 mpz type supports arbitrary precision integers. It should be a drop-in replacement for Python's long type. Depending on the platform and the specific operation, an mpz will be faster than Python's long once the precision exceeds 20 to 50 digits. All the special integer functions in GMP are supported.
>>> import gmpy2 >>> from gmpy2 import mpz >>> mpz('123') + 1 mpz(124) >>> 10 - mpz(1) mpz(9) >>> gmpy2.is_prime(17) True >>> mpz('1_2') mpz(12)
NOTE:
NOTE:
See the documentation for gmpy2.is_prime for details on the underlaying primality tests that are performed.
g == gcd(a, b) and g == a * s + b * t
mpz(n) returns a new mpz object from a numeric value n. If n is not an integer, it will be truncated to an integer.
mpz(s[, base=0]) returns a new mpz object from a string s made of digits in the given base. If base = 0, then binary, octal, or hex Python strings are recognized by leading 0b, 0o, or 0x characters. Otherwise the string is assumed to be decimal. Values for base can range between 2 and 62.
gmpy2 provides access to an experimental integer type called xmpz. The xmpz type is a mutable integer type. In-place operations (+=, //=, etc.) modify the original object and do not create a new object. Instances of xmpz cannot be used as dictionary keys.
>>> import gmpy2 >>> from gmpy2 import xmpz >>> a = xmpz(123) >>> b = a >>> a += 1 >>> a xmpz(124) >>> b xmpz(124)
The ability to change an xmpz object in-place allows for efficient and rapid bit manipulation.
Individual bits can be set or cleared:
>>> a[10]=1 >>> a xmpz(1148)
Slice notation is supported. The bits referenced by a slice can be either 'read from' or 'written to'. To clear a slice of bits, use a source value of 0. In 2s-complement format, 0 is represented by an arbitrary number of 0-bits. To set a slice of bits, use a source value of ~0. The tilde operator inverts, or complements the bits in an integer. (~0 is -1 so you can also use -1.) In 2s-complement format, -1 is represented by an arbitrary number of 1-bits.
If a value for stop is specified in a slice assignment and the actual bit-length of the xmpz is less than stop, then the destination xmpz is logically padded with 0-bits to length stop.
>>> a=xmpz(0) >>> a[8:16] = ~0 >>> bin(a) '0b1111111100000000' >>> a[4:12] = ~a[4:12] >>> bin(a) '0b1111000011110000'
Bits can be reversed:
>>> bin(a) '0b10001111100' >>> a[::] = a[::-1] >>> bin(a) '0b111110001'
The iter_bits() method returns a generator that returns True or False for each bit position. The methods iter_clear(), and iter_set() return generators that return the bit positions that are 1 or 0. The methods support arguments start and stop that define the beginning and ending bit positions that are used. To mimic the behavior of slices. the bit positions checked include start but the last position checked is stop - 1.
>>> a=xmpz(117) >>> bin(a) '0b1110101' >>> list(a.iter_bits()) [True, False, True, False, True, True, True] >>> list(a.iter_clear()) [1, 3] >>> list(a.iter_set()) [0, 2, 4, 5, 6] >>> list(a.iter_bits(stop=12)) [True, False, True, False, True, True, True, False, False, False, False, False]
The following program uses the Sieve of Eratosthenes to generate a list of prime numbers.
from __future__ import print_function import time import gmpy2 def sieve(limit=1000000):
'''Returns a generator that yields the prime numbers up to limit.'''
# Increment by 1 to account for the fact that slices do not include
# the last index value but we do want to include the last value for
# calculating a list of primes.
sieve_limit = gmpy2.isqrt(limit) + 1
limit += 1
# Mark bit positions 0 and 1 as not prime.
bitmap = gmpy2.xmpz(3)
# Process 2 separately. This allows us to use p+p for the step size
# when sieving the remaining primes.
bitmap[4 : limit : 2] = -1
# Sieve the remaining primes.
for p in bitmap.iter_clear(3, sieve_limit):
bitmap[p*p : limit : p+p] = -1
return bitmap.iter_clear(2, limit) if __name__ == "__main__":
start = time.time()
result = list(sieve())
print(time.time() - start)
print(len(result))
The following functions are based on mpz_lucas.c and mpz_prp.c by David Cleaver.
A good reference for probable prime testing is http://www.pseudoprime.com/pseudo.html
Assuming:
gcd(n, a) == 1 n is odd
Then an Euler probable prime requires:
a**((n-1)/2) == 1 (mod n)
Assuming:
n is odd D = p*p - 4, D != 0 gcd(n, 2*D) == 1 n = s*(2**r) + Jacobi(D,n), s odd
Then an extra strong Lucas probable prime requires:
lucasu(p,1,s) == 0 (mod n)
or
lucasv(p,1,s) == +/-2 (mod n)
or
lucasv(p,1,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r
Assuming:
gcd(n,a) == 1
Then a Fermat probable prime requires:
a**(n-1) == 1 (mod n)
Assuming:
n is odd p > 0, q = +/-1 p*p - 4*q != 0
Then a Fibonacci probable prime requires:
lucasv(p,q,n) == p (mod n).
Assuming:
n is odd D = p*p - 4*q, D != 0 gcd(n, 2*q*D) == 1
Then a Lucas probable prime requires:
lucasu(p,q,n - Jacobi(D,n)) == 0 (mod n)
Assuming:
n is odd D = p*p - 4*q, D != 0 gcd(n, 2*q*D) == 1 n = s*(2**r) + Jacobi(D,n), s odd
Then a strong Lucas probable prime requires:
lucasu(p,q,s) == 0 (mod n)
or
lucasv(p,q,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r
Assuming:
gcd(n,a) == 1 n is odd n = s*(2**r) + 1, with s odd
Then a strong probable prime requires one of the following is true:
a**s == 1 (mod n)
or
a**(s*(2**t)) == -1 (mod n) for some t, 0 <= t < r.
gmpy2 provides a rational type call mpq. It should be a replacement for Python's fractions.Fraction module.
>>> import gmpy2 >>> from gmpy2 import mpq >>> mpq(1,7) mpq(1,7) >>> mpq(1,7) * 11 mpq(11,7) >>> mpq(11,7)/13 mpq(11,91)
mpq(n) returns an mpq object with a numeric value n. Decimal and Fraction values are converted exactly.
mpq(n, m) returns an mpq object with a numeric value n / m.
mpq(s[, base=10]) returns an mpq object from a string s made up of digits in the given base. s may be made up of two numbers in the same base separated by a '/' character. If base == 10, then an embedded '.' indicates a number with a decimal fractional part.
The mpfr type is based on the MPFR library. The new mpfr type supports correct rounding, selectable rounding modes, and many trigonometric, exponential, and special functions. A context manager is used to control precision, rounding modes, and the behavior of exceptions.
The default precision of an mpfr is 53 bits - the same precision as Python's float type. If the precision is changed, then mpfr(float('1.2')) differs from mpfr('1.2'). To take advantage of the higher precision provided by the mpfr type, always pass constants as strings.
>>> import gmpy2 >>> from gmpy2 import mpfr >>> mpfr('1.2') mpfr('1.2') >>> mpfr(float('1.2')) mpfr('1.2') >>> gmpy2.get_context().precision=100 >>> mpfr('1.2') mpfr('1.2000000000000000000000000000006',100) >>> mpfr(float('1.2')) mpfr('1.1999999999999999555910790149937',100) >>>
A context is used to control the behavior of mpfr and mpc arithmetic. In addition to controlling the precision, the rounding mode can be specified, minimum and maximum exponent values can be changed, various exceptions can be raised or ignored, gradual underflow can be enabled, and returning complex results can be enabled.
gmpy2.context() creates a new context with all options set to default. gmpy2.set_context(ctx) will set the active context to ctx. gmpy2.get_context() will return a reference to the active context. Note that contexts are mutable: modifying the reference returned by get_context() will modify the active context until a new context is enabled with set_context(). The copy() method of a context will return a copy of the context.
The following example just modifies the precision. The remaining options will be discussed later.
>>> gmpy2.set_context(gmpy2.context()) >>> gmpy2.get_context() context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=False,
allow_release_gil=False) >>> gmpy2.sqrt(5) mpfr('2.2360679774997898') >>> gmpy2.get_context().precision=100 >>> gmpy2.sqrt(5) mpfr('2.2360679774997896964091736687316',100) >>> gmpy2.get_context().precision+=20 >>> gmpy2.sqrt(5) mpfr('2.2360679774997896964091736687312762351',120) >>> ctx=gmpy2.get_context() >>> ctx.precision+=20 >>> gmpy2.sqrt(5) mpfr('2.2360679774997896964091736687312762354406182',140) >>> gmpy2.set_context(gmpy2.context()) >>> gmpy2.sqrt(5) mpfr('2.2360679774997898') >>> ctx.precision+=20 >>> gmpy2.sqrt(5) mpfr('2.2360679774997898') >>> gmpy2.set_context(ctx) >>> gmpy2.sqrt(5) mpfr('2.2360679774997896964091736687312762354406183596116',160) >>>
NOTE:
NOTE:
For example, gmpy2.sqrt(-2) will normally return mpfr('nan'). However, if allow_complex is set to True, then an mpc result will be returned.
>>> gmpy2.set_context(gmpy2.context()) >>> mpfr('nan') == mpfr('nan') False >>> gmpy2.get_context().trap_erange=True >>> mpfr('nan') == mpfr('nan') Traceback (most recent call last):
File "<stdin>", line 1, in <module> gmpy2.RangeError: comparison with NaN >>>
Contexts can also be used in conjunction with Python's with ... statement to temporarily change the context settings for a block of code and then restore the original settings when the block of code exits.
gmpy2.local_context() first save the current context and then creates a new context based on a context passed as the first argument, or the current context if no context is passed. The new context is modified if any optional keyword arguments are given. The original active context is restored when the block completes.
In the following example, the current context is saved by gmpy2.local_context() and then the block begins with a copy of the default context and the precision set to 100. When the block is finished, the original context is restored.
>>> with gmpy2.local_context(gmpy2.context(), precision=100) as ctx: ... print(gmpy2.sqrt(2)) ... ctx.precision += 100 ... print(gmpy2.sqrt(2)) ... 1.4142135623730950488016887242092 1.4142135623730950488016887242096980785696718753769480731766796 >>>
A context object can also be used directly to create a context manager block. However, instead of restoring the context to the active context when the with ... statement is executed, the restored context is the context used before any keyword argument modifications.
The code:
is equivalent to:
Contexts that implement the standard single, double, and quadruple precision floating point types can be created using ieee().
See fac(n) to get the exact integer result.
NOTE:
NOTE:
mpfr(n[, precision=0]) returns an mpfr object after converting a numeric value n. If no precision, or a precision of 0, is specified; the precision is taken from the current context.
mpfr(s[, precision=0[, [base=0]]) returns an mpfr object after converting a string 's' made up of digits in the given base, possibly with fractional part (with period as a separator) and/or exponent (with exponent marker 'e' for base<=10, else '@'). If no precision, or a precision of 0, is specified; the precision is taken from the current context. The base of the string representation must be 0 or in the interval 2 ... 62. If the base is 0, the leading digits of the string are used to identify the base: 0b implies base=2, 0x implies base=16, otherwise base=10 is assumed.
The mpfr type supports the __format__() special method to allow custom output formatting.
optional alignment code:
'<' -> left shifted in field '>' -> right shifted in field '^' -> centered in field
optional leading sign code
'+' -> always display leading sign '-' -> only display minus for negative values ' ' -> minus for negative values, space for positive values
optional width.precision optional rounding mode:
'U' -> round toward plus infinity 'D' -> round toward minus infinity 'Y' -> round away from zero 'Z' -> round toward zero 'N' -> round to nearest
optional conversion code:
'a','A' -> hex format 'b' -> binary format 'e','E' -> scientific format 'f','F' -> fixed point format 'g','G' -> fixed or scientific format
NOTE:
>>> import gmpy2 >>> from gmpy2 import mpfr >>> a=mpfr("1.23456") >>> "{0:15.3f}".format(a) ' 1.235' >>> "{0:15.3Uf}".format(a) ' 1.235' >>> "{0:15.3Df}".format(a) ' 1.234' >>> "{0:.3Df}".format(a) '1.234' >>> "{0:+.3Df}".format(a) '+1.234'
gmpy2 adds a multiple-precision complex type called mpc that is based on the MPC library. The context manager settings for mpfr arithmetic are applied to mpc arithmetic by default. It is possible to specify different precision and rounding modes for both the real and imaginary components of an mpc.
>>> import gmpy2 >>> from gmpy2 import mpc >>> gmpy2.sqrt(mpc("1+2j")) mpc('1.272019649514069+0.78615137775742328j') >>> gmpy2.get_context(real_prec=100,imag_prec=200) context(precision=53, real_prec=100, imag_prec=200,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=True,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=False) >>> gmpy2.sqrt(mpc("1+2j")) mpc('1.2720196495140689642524224617376+0.78615137775742328606955858584295892952312205783772323766490213j',(100,200))
Exceptions are normally raised in Python when the result of a real operation is not defined over the reals; for example, sqrt(-4) will raise an exception. The default context in gmpy2 implements the same behavior but by setting allow_complex to True, complex results will be returned.
>>> import gmpy2 >>> from gmpy2 import mpc >>> gmpy2.sqrt(-4) mpfr('nan') >>> gmpy2.get_context(allow_complex=True) context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=True,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=True) >>> gmpy2.sqrt(-4) mpc('0.0+2.0j')
mpc(c[, precision=0]) returns a new 'mpc' object from an existing complex number (either a Python complex object or another 'mpc' object). If the precision is not specified, then the precision is taken from the current context. The rounding mode is always taken from the current context.
mpc(r[, i=0[, precision=0]]) returns a new 'mpc' object by converting two non-complex numbers into the real and imaginary components of an 'mpc' object. If the precision is not specified, then the precision is taken from the current context. The rounding mode is always taken from the current context.
mpc(s[, [precision=0[, base=10]]) returns a new 'mpc' object by converting a string s into a complex number. If base is omitted, then a base-10 representation is assumed otherwise a base between 2 and 36 can be specified. If the precision is not specified, then the precision is taken from the current context. The rounding mode is always taken from the current context.
In addition to the standard Python string representation of a complex number: "1+2j", the string representation used by the MPC library: "(1 2)" is also supported.
NOTE:
The mpc type supports the __format__() special method to allow custom output formatting.
optional alignment code:
'<' -> left shifted in field '>' -> right shifted in field '^' -> centered in field
optional leading sign code
'+' -> always display leading sign '-' -> only display minus for negative values ' ' -> minus for negative values, space for positive values
optional width.real_precision.imag_precision optional rounding mode:
'U' -> round toward plus infinity 'D' -> round toward minus infinity 'Z' -> round toward zero 'N' -> round to nearest
optional output style:
'P' -> Python style, 1+2j, (default) 'M' -> MPC style, (1 2)
optional conversion code:
'a','A' -> hex format 'b' -> binary format 'e','E' -> scientific format 'f','F' -> fixed point format 'g','G' -> fixed or scientific format
NOTE:
>>> import gmpy2 >>> from gmpy2 import mpc >>> a=gmpy2.sqrt(mpc("1+2j")) >>> a mpc('1.272019649514069+0.78615137775742328j') >>> "{0:.4.4Mf}".format(a) '(1.2720 0.7862)' >>> "{0:.4.4f}".format(a) '1.2720+0.7862j' >>> "{0:^20.4.4U}".format(a) ' 1.2721+0.7862j ' >>> "{0:^20.4.4D}".format(a) ' 1.2720+0.7861j '
The gmpy2 module provides a C-API that can be conveniently used from Cython. All types and functions are declared in the header gmpy2.pxd that is installed automatically in your Python path together with the library.
In order to use the C-API you need to make one call to the function void import_gmpy2(void).
The types mpz, mpq, mpfr and mpc are declared as extension types in gmpy2.pxd. They correspond respectively to the C structures MPZ_Object, MPQ_Object, MPFR_Object and MPC_Object.
Fast type checking can be done with the following C functions
To create a new gmpy2 types there are four basic functions
The context can be set to NULL and controls the default behavior (e.g. precision).
The gmpy2.pxd header also provides convenience macro to wrap a (copy of) a mpz_t, mpq_t, mpfr_t or a mpc_t object into the corresponding gmpy2 type.
Each of the gmpy2 objects has a field corresponding to the underlying C type. The following functions give access to this field
mpz_t MPZ(mpz)
mpq_t MPQ(mpq)
mpfr_t MPFR(mpfr)
mpc_t MPC(mpc)
The header gmpy2.pxd as well as the C header gmpy2.h from which it depends are installed in the Python path. In order to make Cython and the C compiler aware of the existence of these files, the Python path should be part of the include directories.
Recall that import_gmpy2() needs to be called before any other function of the C-API.
Here is a minimal example of a Cython file test_gmpy2.pyx
"A minimal cython file test_gmpy2.pyx" from gmpy2 cimport * cdef extern from "gmp.h":
void mpz_set_si(mpz_t, long) import_gmpy2() # needed to initialize the C-API cdef mpz z = GMPy_MPZ_New(NULL) mpz_set_si(MPZ(z), -7) print(z + 3)
The corresponding setup.py is given below.
"A minimal setup.py for compiling test_gmpy2.pyx" from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize import sys ext = Extension("test_gmpy2", ["test_gmpy2.pyx"], include_dirs=sys.path, libraries=['gmp', 'mpfr', 'mpc']) setup(
name="cython_gmpy_test",
ext_modules=cythonize([ext], include_path=sys.path) )
With these two files in the same repository, you should be able to compile your module using
$ python setup.py build_ext --inplace
For more about compilation and installation of cython files and extension modules, please refer to the official documentation of Cython and distutils.
A python object could interact with gmpy2 if it implements one of the following methods:
Implementing on of these methods allow gmpy2 to convert a python object into a gmpy2 type. Example::
>>> from gmpy2 import mpz >>> class CustInt: ... def __init__(self, x): ... self.x = x ... def __mpz__(self): ... return mpz(self.x) ... >>> ci = CustInt(5) >>> z = mpz(ci); z mpz(5) >>> type(z) <type 'mpz'>
gmpy2 allow arithmetic operations between gmpy2 numbers and objects with conversion methods. Operation with object that implements floating conversion and exact conversion methods are not supported. That means that only the following cases are supported:
Examples:
>>> from gmpy2 import mpz, mpq, mpfr, mpc >>> class Q: ... def __mpz__(self): return mpz(1) ... def __mpq__(self): return mpq(3,2) >>> q = Q() >>> mpz(2) + q mpq(7,2) >>> mpq(1,2) * q mpq(3,4) >>> mpfr(10) * q mpfr('15.0')
Case Van Horsen
2022 - 2021, Case Van Horsen
1668984614 | 2.1 |