gmpy2-2.0.7/0000755000000000000000000000000012567136721011266 5ustar rootrootgmpy2-2.0.7/test3/0000755000000000000000000000000012567136721012330 5ustar rootrootgmpy2-2.0.7/test3/timing3.py0000666000000000000000000000147312204747360014260 0ustar rootrootimport gmpy2 as _g import time print("Typical expected results would be:",""" D:\PySym>python timing.py Factorial of 10000 took 0.0619989238859 (35660 digits) Fibonacci of 10000 took 0.000744228458022 (2090 digits) Factorial of 100000 took 4.44311764676 (456574 digits) Fibonacci of 100000 took 0.022344453738 (20899 digits) Factorial of 1000000 took 152.151135367 (5565709 digits) Fibonacci of 1000000 took 0.670207059778 (208988 digits) """) print("Actual timings and results...:") for i in (10000,100000,1000000): start=time.time() x=_g.fac(i) stend=time.time() print("Factorial of %d took %s (%d digits)" % ( i, stend-start, x.num_digits())) start=time.time() x=_g.fib(i) stend=time.time() print("Fibonacci of %d took %s (%d digits)" % ( i, stend-start, x.num_digits())) gmpy2-2.0.7/test3/timing2.py0000666000000000000000000000131412204747360014251 0ustar rootrootimport time import gmpy2 as gmpy def timedfib(n, zero): start=time.clock() a=zero; b=a+1 for i in range(n): a,b=b,a+b stend=time.clock() return type(zero), stend-start, a def timedfibsp(n, one): start=time.clock() result=gmpy.fib(n) stend=time.clock() return type(one), stend-start, result def test(n=100*1000): print("%dth Fibonacci number of various types:" % n) for z in 0, gmpy.mpz(0), gmpy.mpf(0): tip, tim, tot = timedfib(n, z) print(" %5.3f %s %s" % (tim, gmpy.fdigits(tot,10,6), tip)) tip, tim, tot = timedfibsp(n, 1) print(" %5.3f %s %s" % (tim, gmpy.fdigits(tot,10,6), "gmpy.fib")) if __name__=='__main__': test() gmpy2-2.0.7/test3/timing1.py0000666000000000000000000000233612204747360014255 0ustar rootrootimport time import gmpy2 as gmpy try: sum except NameError: def sum(x, z): for item in x: z += item return z def timedsum(n, zero): start=time.clock() tot=zero for i in range(n): tot+=i stend=time.clock() return type(zero), stend-start, tot def timedsum1(n, zero): start=time.clock() tot=sum(range(n), zero) stend=time.clock() return type(zero), stend-start, tot def timedmul(n, one): start=time.clock() tot=one for i in range(n): tot*=(i+1) stend=time.clock() return type(one), stend-start, tot def test(n=100*1000): print("Sum of %d items of various types:" % n) for z in 0, 0.0, gmpy.mpz(0), gmpy.mpf(0): tip, tim, tot = timedsum(n, z) print(" %5.3f %.0f %s" % (tim, float(tot), tip)) print("Sum of %d items of various types w/2.3 sum builtin:" % n) for z in 0, 0.0, gmpy.mpz(0), gmpy.mpf(0): tip, tim, tot = timedsum1(n, z) print(" %5.3f %.0f %s" % (tim, float(tot), tip)) print("Mul of %d items of various types:" % (n//5)) for z in 1, 1.0, gmpy.mpz(1), gmpy.mpf(1): tip, tim, tot = timedmul(n//5, z) print(" %5.3f %s" % (tim, tip)) if __name__=='__main__': test() gmpy2-2.0.7/test3/test_pack.py0000666000000000000000000000125412204747360014660 0ustar rootrootfrom __future__ import print_function import gmpy2 def test_pack_unpack(bits = 200, chunk = 500, terms = 50): """Test gmpy2.pack and gmpy2.unpack.""" for t in range(2, terms): for b in range(1, bits): # Test with all bits set to 1. v = [ 2**b - 1 ] * t for c in range(b, chunk): temp = gmpy2.pack(v, c) u = gmpy2.unpack(temp, c) assert u == v, (v, temp, u, (t, b, c)) def main(): print("Testing pack/unpack for a large number of values.") print("This test may take a few minutes.") test_pack_unpack() print("Test successful.") if __name__ == "__main__": main() gmpy2-2.0.7/test3/test_mpz_args.py0000666000000000000000000000363012204747360015564 0ustar rootroot# Test a wide variety of input values to the commonly used mpz operations. # This test should be run whenever optimizations are made to the handling of # arguments. import sys import gmpy2 as gmpy if sys.version.startswith('3'): intTypes = (int,) else: intTypes = (int, long) def writeln(s): sys.stdout.write(s+'\n') valueList = [0, 1, 2, 3, 4, 5] for power in (15, 16, 30, 32, 45, 48, 60, 64, 75, 90, 96, 105, 120, 128): for i in (-2, -1, 0, 1, 2): valueList.append(2**power + i) valueList.append('123456789012345678901234567890') valueList.append('10000000000000000000000000000000000000000000000000000000000000000') testValues = [] mpzValues = [] for i in valueList: for t in intTypes: testValues.append(t(i)) testValues.append(-t(i)) mpzValues.append(gmpy.mpz(i)) mpzValues.append(-gmpy.mpz(i)) testValues.extend(mpzValues) for i in testValues: for z in mpzValues: # Test all permutations of addition assert int(i)+int(z) == i+z, (repr(i),repr(z)) assert int(z)+int(i) == z+i, (repr(i),repr(z)) # Test all permutations of subtraction assert int(i)-int(z) == i-z, (repr(i),repr(z)) assert int(z)-int(i) == z-i, (repr(i),repr(z)) # Test all permutations of multiplication assert int(i)*int(z) == i*z, (repr(i),repr(z)) assert int(z)*int(i) == z*i, (repr(i),repr(z)) # Test all permutations of division if z!=0: temp = int(i)//int(z) assert int(i)//int(z) == i//z, (repr(i),repr(z)) assert int(i)%int(z) == i%z, (repr(i),repr(z)) assert divmod(int(i),int(z)) == divmod(i,z), (repr(i),repr(z)) if i!=0: temp = int(z)//int(i) assert int(z)//int(i) == z//i, (repr(i),repr(z)) assert int(z)%int(i) == z%i, (repr(i),repr(z)) assert divmod(int(z),int(i)) == divmod(z,i), (repr(i),repr(z)) gmpy2-2.0.7/test3/test_leaks.py0000666000000000000000000000361312204747360015042 0ustar rootrootfrom __future__ import print_function import gmpy2 import fractions import decimal MPZ = gmpy2.mpz MPQ = gmpy2.mpq MPF = gmpy2.mpf FR = fractions.Fraction DC = decimal.Decimal int_vals = [] int_vals.extend([1, 2, 3, -10, 256, 23**65]) int_vals.extend([MPZ(1), MPZ(2), MPZ(3), MPZ(-10), MPZ(23**65)]) float_vals = [] float_vals.extend([1.23, -3.124159, 0.0234, float("nan")]) float_vals.extend([MPF(1.23), MPF("-3.124159"), MPF("0.0234")]) frac_vals = [] frac_vals.extend([FR(1,2), FR(-7,2345)]) frac_vals.extend([MPQ(1,2), MPQ(-7,2345)]) all_vals = int_vals + float_vals + frac_vals def test_leaks1(bits = 80, chunk = 150, terms = 20): """Test gmpy2.pack and gmpy2.unpack.""" for t in range(2, terms): for b in range(1, bits): # Test with all bits set to 1. v = [ 2**b - 1 ] * t for c in range(b, chunk): temp = gmpy2.pack(v, c) u = gmpy2.unpack(temp, c) assert u == v, (v, temp, u, (t, b, c)) def test_leaks2(): """Test binary operations.""" def test_binary(a, b): t = a + b t = a - b t = a * b try: t = a / b except: pass try: t = a // b except: pass try: t = divmod(a, b) except: pass t = gmpy2.add(a, b) t = gmpy2.sub(a, b) t = gmpy2.mul(a, b) t = gmpy2.div(a, b) t = gmpy2.agm(a, b) t = gmpy2.atan2(a, b) for x in all_vals: for y in all_vals: test_binary(x, y) test_binary(y, x) def main(count = 100): print("Testing for memory leaks by repeating a set of calculations.") print("This test may take a few minutes.") for i in range(count): print("Pass: {0}".format(i)) test_leaks2() print("Test successful.") if __name__ == "__main__": main() gmpy2-2.0.7/test3/test_large.py0000666000000000000000000000156712204747360015043 0ustar rootrootfrom gmpy2 import * from math import log from time import time # This test is designed to detect issues when allocating memory for large # numbers. If it crashes and you need to work with very large numbers, # you will need to compile GMP from scratch and try a different memory # allocation option. def pi(N): print("Computing pi to %s decimal places." % N) start = time() N = int(round(log(10,2)*N)) sq2 = fsqrt(mpf(2, N)) a = mpz(6) - 4*sq2 y = sq2-1 for k in range(0, 10000): xx = fsqrt(fsqrt(1-y**4)) y = (1-xx)/(1+xx) anew = a*(1+y)**4 - 2**(2*k+3)*y*(1+y+y**2) if anew == a: break a = anew print("Computation took %5.2f seconds." % (time() - start)) return 1/a if __name__ == '__main__': print("Testing operations with large numbers.") pi(1000000) gmpy2-2.0.7/test3/test_hash.py0000666000000000000000000000234612204747360014670 0ustar rootroot# Hash test for Python 3.2. import gmpy2 import fractions import sys try: m = sys.hash_info.modulus except NameError: print("new-style hash is not supported") sys.exit(0) for s in [0, m//2, m, m*2, m*m, 7, 13, 19, 87907, 79797, 44*44]: for i in range(-10,10): for k in [-1, 1, 7, 11, -(2**15), 2**16, 2**30, 2**31, 2**32, 2**33, 2**61, -(2**62), 2**63, 2**64]: val = k*(s + i) assert hash(val) == hash(gmpy2.mpz(val)), (val, hash(val), hash(gmpy2.mpz(val))) print("hash tests for integer values passed") for d in [1, -2, 3, -47, m, m*2, 324, 797080, -979]: for s in [0, m//2, m, m*2, m*m]: for i in range(-10,10): for k in [-1, 1, 7, 11, -(2**15), 2**16, 2**30, 2**31, 2**32, 2**33, 2**61, -(2**62), 2**63, 2**64, 131313164, -4643131646131346460964347]: val = k*(s + i) if val: assert hash(fractions.Fraction(d,val)) == hash(gmpy2.mpq(d,val)), (d,val,hash(fractions.Fraction(d,val)),hash(gmpy.mpq(d,val))) if d: assert hash(fractions.Fraction(val,d)) == hash(gmpy2.mpq(val,d)), (val,d,hash(fractions.Fraction(val,d)),hash(gmpy.mpq(val,d))) print("hash tests for rational values passed") gmpy2-2.0.7/test3/gmpy_truediv.py0000666000000000000000000000017612204747360015423 0ustar rootroot''' make a "true division" function available for testing ''' from __future__ import division def truediv(a, b): return a/b gmpy2-2.0.7/test3/gmpy_test_xmpz.py0000666000000000000000000002335412351625226016000 0ustar rootroot# partial unit test for gmpy2 xmpz functionality # relies on Tim Peters' "doctest.py" test-driver import gmpy2 as _g, doctest, sys, operator, gc __test__={} a=_g.xmpz(123) b=_g.xmpz(456) aa=_g.mpz(123) bb=_g.mpz(456) __test__['index']=\ r''' >>> a=_g.xmpz(123) >>> b=_g.xmpz(456) >>> range(333)[a] 123 >>> range(333)[b] Traceback (innermost last): ... IndexError: range object index out of range ''' __test__['elemop']=\ r''' >>> a=_g.xmpz(123) >>> b=_g.xmpz(456) >>> a+b mpz(579) >>> a-b mpz(-333) >>> a*b mpz(56088) >>> a//b mpz(0) >>> a/b mpfr('0.26973684210526316') >>> b//a mpz(3) >>> b/a mpfr('3.7073170731707319') >>> a%b mpz(123) >>> 0%b mpz(0) >>> b+a mpz(579) >>> b-a mpz(333) >>> b*a mpz(56088) >>> b%a mpz(87) >>> divmod(a,b) (mpz(0), mpz(123)) >>> divmod(b,a) (mpz(3), mpz(87)) >>> divmod(0,b) (mpz(0), mpz(0)) >>> -a >>> a xmpz(-123) >>> a=_g.xmpz(123) >>> a+1 mpz(124) >>> a+=1; a xmpz(124) >>> a=_g.xmpz(123) >>> a+(-1) mpz(122) >>> a-=1; a xmpz(122) >>> a=_g.xmpz(123) >>> (-1)+a mpz(122) >>> 1+a mpz(124) >>> a-1 mpz(122) >>> a-(-1) mpz(124) >>> 1-a mpz(-122) >>> (-1)-a mpz(-124) >>> a+True mpz(124) >>> a+False mpz(123) >>> a*False mpz(0) >>> a//True mpz(123) >>> -a >>> abs(a) >>> a xmpz(123) >>> pow(a,10) mpz(792594609605189126649) >>> pow(a,7,b) mpz(99) >>> _g.sign(b-a) 1 >>> _g.sign(b-b) 0 >>> _g.sign(a-b) -1 >>> _g.sign(a) 1 >>> -a >>> _g.sign(a) -1 >>> a=_g.xmpz(123) >>> z=b-b; _g.sign(z) 0 >>> s='12345678901234567890123456789' >>> int(s) == _g.xmpz(s) True >>> _g.xmpz(s) == int(s) True >>> del s >>> _g.is_even(a) False >>> _g.is_odd(a) True >>> _g.is_even(b) True >>> _g.is_odd(b) False >>> _g.is_even(2) True ''' __test__['special'] = \ r''' >>> a=_g.xmpz(123) >>> b=_g.xmpz(456) >>> a == float('Inf') False >>> a != float('Inf') True >>> a > float('Inf') False >>> a >= float('Inf') False >>> a < float('Inf') True >>> a <= float('Inf') True >>> a == float('-Inf') False >>> a != float('-Inf') True >>> a > float('-Inf') True >>> a >= float('-Inf') True >>> a < float('-Inf') False >>> a <= float('-Inf') False >>> a == float('nan') False >>> a != float('nan') True >>> a > float('nan') False >>> a >= float('nan') False >>> a < float('nan') False >>> a <= float('nan') False >>> float('Inf') == a False >>> float('Inf') != a True >>> float('Inf') > a True >>> float('Inf') >= a True >>> float('Inf') < a False >>> float('Inf') <= a False >>> float('-Inf') == a False >>> float('-Inf') != a True >>> float('-Inf') > a False >>> float('-Inf') >= a False >>> float('-Inf') < a True >>> float('-Inf') <= a True >>> float('nan') == a False >>> float('nan') != a True >>> float('nan') > a False >>> float('nan') >= a False >>> float('nan') < a False >>> float('nan') <= a False >>> a + float('Inf') mpfr('inf') >>> float('Inf') + a mpfr('inf') >>> a + float('-Inf') mpfr('-inf') >>> float('-Inf') + a mpfr('-inf') >>> a + float('nan') mpfr('nan') >>> float('nan') + a mpfr('nan') >>> a - float('Inf') mpfr('-inf') >>> float('Inf') - a mpfr('inf') >>> a - float('-Inf') mpfr('inf') >>> float('-Inf') - a mpfr('-inf') >>> a - float('nan') mpfr('nan') >>> float('nan') - a mpfr('nan') >>> a * float('Inf') mpfr('inf') >>> float('Inf') * a mpfr('inf') >>> a * float('-Inf') mpfr('-inf') >>> float('-Inf') * a mpfr('-inf') >>> -a >>> a * float('Inf') mpfr('-inf') >>> float('Inf') * a mpfr('-inf') >>> a * float('-Inf') mpfr('inf') >>> float('-Inf') * a mpfr('inf') >>> -a >>> a * float('nan') mpfr('nan') >>> float('nan') * a mpfr('nan') >>> _g.xmpz(0) * float('Inf') mpfr('nan') >>> _g.xmpz(0) * float('-Inf') mpfr('nan') >>> float('Inf') * _g.xmpz(0) mpfr('nan') >>> float('-Inf') * _g.xmpz(0) mpfr('nan') >>> a / float('Inf') mpfr('0.0') >>> float('Inf') / a mpfr('inf') >>> a / float('-Inf') mpfr('-0.0') >>> float('-Inf') / a mpfr('-inf') >>> a / float('nan') mpfr('nan') >>> float('nan') / a mpfr('nan') >>> -a >>> a / float('Inf') mpfr('-0.0') >>> float('Inf') / a mpfr('-inf') >>> a / float('-Inf') mpfr('0.0') >>> float('-Inf') / a mpfr('inf') >>> -a ''' __test__['divexact']=\ r''' >>> a=_g.xmpz('1234567912345678912345679') >>> b=_g.xmpz('789789789789789789789789') >>> c=a*b >>> _g.divexact(c,a) mpz(789789789789789789789789) >>> ''' __test__['divmod']=\ r''' >>> _g.c_divmod(17,5) (mpz(4), mpz(-3)) >>> _g.c_divmod(-17,5) (mpz(-3), mpz(-2)) >>> _g.c_divmod(17,-5) (mpz(-3), mpz(2)) >>> _g.c_divmod(-17,-5) (mpz(4), mpz(3)) >>> _g.f_divmod(17,5) (mpz(3), mpz(2)) >>> _g.f_divmod(-17,5) (mpz(-4), mpz(3)) >>> _g.f_divmod(17,-5) (mpz(-4), mpz(-3)) >>> _g.f_divmod(-17,-5) (mpz(3), mpz(-2)) >>> _g.t_divmod(17,5) (mpz(3), mpz(2)) >>> _g.t_divmod(-17,5) (mpz(-3), mpz(-2)) >>> _g.t_divmod(17,-5) (mpz(-3), mpz(2)) >>> _g.t_divmod(-17,-5) (mpz(3), mpz(-2)) ''' __test__['cmpr']=\ r''' >>> a=_g.xmpz(123) >>> b=_g.xmpz(456) >>> c=_g.xmpz(a) >>> c is a 0 >>> c==a 1 >>> c>a 0 >>> c>> d=a.copy() >>> a is d 0 >>> a == d 1 >>> a>b 0 >>> a>> not _g.xmpz(0) 1 >>> not a 0 >>> _g.xmpz(1) == None False >>> _g.xmpz(1) == '1' False >>> _g.xmpz(1) == 'abc' False >>> [_g.xmpz(23), None].count(None) 1 >>> _g.xmpz(3.14) xmpz(3) >>> _g.xmpz(_g.mpq(17,3)) xmpz(5) >>> _g.xmpz(23) xmpz(23) >>> _g.xmpz(-23) xmpz(-23) >>> x=1000*1000*1000*1000*1000*1000*1000 >>> _g.xmpz(x) xmpz(1000000000000000000000) >>> a == float('Inf') False >>> a != float('Inf') True >>> a > float('Inf') False >>> a >= float('Inf') False >>> a < float('Inf') True >>> a <= float('Inf') True >>> a == float('-Inf') False >>> a != float('-Inf') True >>> a > float('-Inf') True >>> a >= float('-Inf') True >>> a < float('-Inf') False >>> a <= float('-Inf') False >>> a == float('nan') False >>> a != float('nan') True >>> a > float('nan') False >>> a >= float('nan') False >>> a < float('nan') False >>> a <= float('nan') False ''' __test__['bitops']=\ r''' >>> a=_g.xmpz(123) >>> b=_g.xmpz(456) >>> ~a >>> a xmpz(-124) >>> a=_g.xmpz(123) >>> a&b mpz(72) >>> a|b mpz(507) >>> a^b mpz(435) >>> a<<1 mpz(246) >>> a>>1 mpz(61) >>> a<<-1 Traceback (innermost last): ... ValueError: negative shift count >>> a>>-2 Traceback (innermost last): ... ValueError: negative shift count >>> a<<0 mpz(123) >>> a>>0 mpz(123) >>> a.bit_set(20) mpz(1048699) >>> a=_g.xmpz(123) >>> a.bit_clear(0) mpz(122) >>> a=_g.xmpz(123) >>> for i in range(8): ... print(a.bit_test(i)) ... True True False True True True True False >>> for i in range(10): ... print(b.bit_test(i)) ... False False False True False False True True True False >>> [a.bit_scan0(j) for j in range(33)] [2, 2, 2, 7, 7, 7, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> [a.bit_scan1(j) for j in range(10)] [0, 1, 3, 3, 4, 5, 6, None, None, None] >>> n=_g.xmpz(-(7+6*16+5*256+7*4092)) >>> [n.bit_scan0(j) for j in range(18)] [1, 1, 3, 3, 6, 6, 6, 8, 8, 10, 10, 12, 12, 13, 14, None, None, None] >>> [n.bit_scan1(j) for j in range(33)] [0, 2, 2, 4, 4, 5, 7, 7, 9, 9, 11, 11, 15, 15, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> _g.xmpz(0).bit_length() 0 >>> _g.xmpz(12345).bit_length() 14 >>> _g.bit_mask(9) mpz(511) >>> _g.xbit_mask(9) xmpz(511) ''' __test__['format']=\ r''' >>> a=_g.xmpz(123) >>> b=_g.xmpz(456) >>> str(a) '123' >>> repr(a) 'xmpz(123)' >>> hex(a) '0x7b' >>> oct(a) '0o173' >>> _g.xmpz('123') xmpz(123) >>> _g.xmpz('1001001011',2) xmpz(587) >>> _g.xmpz('0b1001001011') xmpz(587) >>> _g.xmpz('1001001011',2).digits(2) '0b1001001011' >>> for i in range(2,63): ... print(a.digits(i)) ... 0b1111011 11120 1323 443 323 234 0o173 146 123 102 a3 96 8b 83 0x7b 74 6f 69 63 5i 5d 58 53 4n 4j 4f 4b 47 43 3u 3r 3o 3l 3i 3f 3C 39 36 33 30 2d 2b 2Z 2X 2V 2T 2R 2P 2N 2L 2J 2H 2F 2D 2B 29 27 25 23 21 1z >>> print(a.digits(63)) Traceback (innermost last): ... ValueError: base must be in the interval 2 ... 62 >>> _g.xmpz('43') xmpz(43) >>> _g.xmpz('043') xmpz(43) >>> _g.xmpz('43',10) xmpz(43) >>> _g.xmpz('0o43',0) xmpz(35) >>> _g.xmpz('0x43') xmpz(67) >>> _g.xmpz('0x43',10) Traceback (innermost last): File "", line 1, in ? _g.xmpz('0x43') ValueError: invalid digits >>> ''' __test__['number']=\ r''' >>> a=_g.xmpz(123) >>> b=_g.xmpz(456) >>> _g.is_square(a) 0 >>> _g.is_power(a) 0 >>> _g.is_square(99*99) 1 >>> _g.is_square(99*99*99) 0 >>> _g.is_square(0) 1 >>> _g.is_square(-1) 0 >>> _g.is_power(99*99*99) 1 >>> _g.gcd(a,b) mpz(3) >>> temp=_g.gcdext(a,b) >>> temp[0]==a*temp[1]+b*temp[2] True >>> _g.lcm(a,b) mpz(18696) >>> _g.fac(7) mpz(5040) >>> _g.fib(17) mpz(1597) >>> del temp >>> for i in range(10): ... print(_g.bincoef(10,i)) ... 1 10 45 120 210 252 210 120 45 10 >>> _g.divm(b,a,_g.xmpz(20)) mpz(12) >>> _g.divm(a,b,100) Traceback (innermost last): File "", line 1, in ? _g.divm(a,b,100) ZeroDivisionError: not invertible >>> _g.divm(6,12,14) mpz(4) >>> _g.divm(0,1,2) mpz(0) ''' def _test(chat=None): if chat: print("Unit tests for gmpy2 (xmpz functionality)") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print("Repeating tests, with caching disabled") _g.set_cache(0,128) sav = sys.stdout class _Dummy: encoding = None def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0) finally: sys.stdout = sav if chat: print() print("Overall results for mpz:") return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test3/gmpy_test_thr.py0000666000000000000000000000703612204747360015577 0ustar rootroot# partial unit test for gmpy2 threaded mpz functionality # relies on Tim Peters' "doctest.py" test-driver import gmpy2 as _g, doctest, sys, operator, gc, queue, threading from functools import reduce __test__={} def _tf(N=2, _K=1234**5678): """Takes about 100ms on a first-generation Macbook Pro""" for i in range(N): assert (_g.mpz(1234)**5678)==_K a=_g.mpz(123) b=_g.mpz(456) c=_g.mpz(123456789123456789) def factorize(x=c): r''' (Takes about 25ms, on c, on a first-generation Macbook Pro) >>> factorize(a) [3, 41] >>> factorize(b) [2, 2, 2, 3, 19] >>> ''' import gmpy2 as _g savex=x prime=2 x=_g.mpz(x) factors=[] while x>=prime: newx,mult=x.remove(prime) if mult: factors.extend([int(prime)]*mult) x=newx prime=_g.next_prime(prime) for factor in factors: assert _g.is_prime(factor) from operator import mul assert reduce(mul, factors)==savex return factors def elemop(N=1000): r''' (Takes about 40ms on a first-generation Macbook Pro) ''' for i in range(N): assert a+b == 579 assert a-b == -333 assert b*a == a*b == 56088 assert b%a == 87 assert divmod(a, b) == (0, 123) assert divmod(b, a) == (3, 87) assert -a == -123 assert pow(a, 10) == 792594609605189126649 assert pow(a, 7, b) == 99 assert cmp(a, b) == -1 assert '7' in str(c) assert '0' not in str(c) assert a.sqrt() == 11 assert _g.lcm(a, b) == 18696 assert _g.fac(7) == 5040 assert _g.fib(17) == 1597 assert _g.divm(b, a, 20) == 12 assert _g.divm(4, 8, 20) == 3 assert _g.divm(4, 8, 20) == 3 assert _g.mpz(20) == 20 assert _g.mpz(8) == 8 assert _g.mpz(4) == 4 assert a.invert(100) == 87 def _test(chat=None): if chat: print("Unit tests for gmpy2 (threading)") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print("Repeating tests, with caching disabled") _g.set_cache(0,128) sav = sys.stdout class _Dummy: def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0) finally: sys.stdout = sav if chat: print() print("Overall results for thr:") return doctest.master.summarize(chat) class DoOne(threading.Thread): def __init__(self, q): threading.Thread.__init__(self) self.q = q def run(self): while True: task = self.q.get() if task is None: break task() def _test_thr(Ntasks=5, Nthreads=1): q = queue.Queue() funcs = (_tf, 1), (factorize, 4), (elemop, 2) for i in range(Ntasks): for f, n in funcs: for x in range(n): q.put(f) for i in range(Nthreads): q.put(None) thrs = [DoOne(q) for i in range(Nthreads)] for t in thrs: t.start() for t in thrs: t.join() if __name__=='__main__': _test(1) gmpy2-2.0.7/test3/gmpy_test_mpz.py0000666000000000000000000004761712351625226015620 0ustar rootroot# partial unit test for gmpy2 mpz functionality # relies on Tim Peters' "doctest.py" test-driver r''' >>> list(filter(lambda x: not x.startswith('_'), dir(_g))) ['Default', 'DivisionByZeroError', 'ExponentOutOfBoundsError', 'InexactResultError', 'InvalidOperationError', 'OverflowResultError', 'RangeError', 'RoundAwayZero', 'RoundDown', 'RoundToNearest', 'RoundToZero', 'RoundUp', 'UnderflowResultError', 'acos', 'acosh', 'add', 'agm', 'ai', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'bincoef', 'bit_clear', 'bit_flip', 'bit_length', 'bit_mask', 'bit_scan0', 'bit_scan1', 'bit_set', 'bit_test', 'c_div', 'c_div_2exp', 'c_divmod', 'c_divmod_2exp', 'c_mod', 'c_mod_2exp', 'cbrt', 'ceil', 'check_range', 'comb', 'const_catalan', 'const_euler', 'const_log2', 'const_pi', 'context', 'copy_sign', 'cos', 'cosh', 'cot', 'coth', 'csc', 'csch', 'degrees', 'denom', 'digamma', 'digits', 'div', 'div_2exp', 'divexact', 'divm', 'eint', 'erf', 'erfc', 'exp', 'exp10', 'exp2', 'expm1', 'f2q', 'f_div', 'f_div_2exp', 'f_divmod', 'f_divmod_2exp', 'f_mod', 'f_mod_2exp', 'fac', 'factorial', 'fib', 'fib2', 'floor', 'fma', 'fmod', 'fms', 'frac', 'frexp', 'from_binary', 'fsum', 'gamma', 'gcd', 'gcdext', 'get_cache', 'get_context', 'get_emax_max', 'get_emin_min', 'get_exp', 'get_max_precision', 'hamdist', 'hypot', 'ieee', 'inf', 'invert', 'iroot', 'iroot_rem', 'is_bpsw_prp', 'is_euler_prp', 'is_even', 'is_extra_strong_lucas_prp', 'is_fermat_prp', 'is_fibonacci_prp', 'is_finite', 'is_inf', 'is_infinite', 'is_integer', 'is_lessgreater', 'is_lucas_prp', 'is_nan', 'is_number', 'is_odd', 'is_power', 'is_prime', 'is_regular', 'is_selfridge_prp', 'is_signed', 'is_square', 'is_strong_bpsw_prp', 'is_strong_lucas_prp', 'is_strong_prp', 'is_strong_selfridge_prp', 'is_unordered', 'is_zero', 'isqrt', 'isqrt_rem', 'j0', 'j1', 'jacobi', 'jn', 'kronecker', 'lcm', 'legendre', 'lgamma', 'li2', 'license', 'lngamma', 'local_context', 'log', 'log10', 'log1p', 'log2', 'lucas', 'lucas2', 'lucasu', 'lucasu_mod', 'lucasv', 'lucasv_mod', 'max2', 'maxnum', 'min2', 'minnum', 'modf', 'mp_limbsize', 'mp_version', 'mpc', 'mpc_random', 'mpc_version', 'mpfr', 'mpfr_from_old_binary', 'mpfr_grandom', 'mpfr_random', 'mpfr_version', 'mpq', 'mpq_from_old_binary', 'mpz', 'mpz_from_old_binary', 'mpz_random', 'mpz_rrandomb', 'mpz_urandomb', 'mul', 'mul_2exp', 'nan', 'next_above', 'next_below', 'next_prime', 'next_toward', 'norm', 'num_digits', 'numer', 'pack', 'phase', 'polar', 'popcount', 'powmod', 'proj', 'qdiv', 'radians', 'random_state', 'rec_sqrt', 'rect', 'reldiff', 'remainder', 'remove', 'remquo', 'rint', 'rint_ceil', 'rint_floor', 'rint_round', 'rint_trunc', 'root', 'round2', 'round_away', 'sec', 'sech', 'set_cache', 'set_context', 'set_exp', 'set_sign', 'sign', 'sin', 'sin_cos', 'sinh', 'sinh_cosh', 'sqrt', 'square', 'sub', 't_div', 't_div_2exp', 't_divmod', 't_divmod_2exp', 't_mod', 't_mod_2exp', 'tan', 'tanh', 'to_binary', 'trunc', 'unpack', 'version', 'xbit_mask', 'xmpz', 'y0', 'y1', 'yn', 'zero', 'zeta'] >>> list([x for x in dir(a) if x != '__dir__']) ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__ifloordiv__', '__ilshift__', '__imod__', '__imul__', '__index__', '__init__', '__int__', '__invert__', '__ipow__', '__irshift__', '__isub__', '__le__', '__len__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_clear', 'bit_flip', 'bit_length', 'bit_scan0', 'bit_scan1', 'bit_set', 'bit_test', 'denominator', 'digits', 'num_digits', 'numerator'] >>> ''' import gmpy2 as _g, doctest, sys, operator, gc __test__={} a=_g.mpz(123) b=_g.mpz(456) # Disable tests since they are not reliable with Python 3.1 but left behind # in case it is needed in the future. if sys.platform in ('__DISABLE__linux2', '__DISABLE__darwin'): def _memsize(): """ this function tries to return a measurement of how much memory this process is consuming (if it doesn't manage to, it returns 0). """ import os try: x = int(os.popen('ps -p %d -o vsz|tail -1' % os.getpid()).read()) except: x = 0 return x else: def _memsize(): return 0 def factorize(x): r''' >>> factorize(a) [3, 41] >>> factorize(b) [2, 2, 2, 3, 19] >>> ''' savex=x prime=2 x=_g.mpz(x) factors=[] while x>=prime: newx,mult=_g.remove(x,prime) if mult: factors.extend([int(prime)]*mult) x=newx prime=_g.next_prime(prime) for factor in factors: assert _g.is_prime(factor) from operator import mul from functools import reduce assert reduce(mul, factors)==savex return factors __test__['index']=\ r''' >>> range(333)[a] 123 >>> range(333)[b] Traceback (innermost last): ... IndexError: range object index out of range ''' __test__['elemop']=\ r''' >>> a+b mpz(579) >>> a-b mpz(-333) >>> a*b mpz(56088) >>> a//b mpz(0) >>> a/b mpfr('0.26973684210526316') >>> b//a mpz(3) >>> b/a mpfr('3.7073170731707319') >>> a%b mpz(123) >>> 0%b mpz(0) >>> b+a mpz(579) >>> b-a mpz(333) >>> b*a mpz(56088) >>> b%a mpz(87) >>> divmod(a,b) (mpz(0), mpz(123)) >>> divmod(b,a) (mpz(3), mpz(87)) >>> divmod(0,b) (mpz(0), mpz(0)) >>> -a mpz(-123) >>> a+1 mpz(124) >>> a+(-1) mpz(122) >>> (-1)+a mpz(122) >>> 1+a mpz(124) >>> a-1 mpz(122) >>> a-(-1) mpz(124) >>> 1-a mpz(-122) >>> (-1)-a mpz(-124) >>> a+True mpz(124) >>> a+False mpz(123) >>> a*False mpz(0) >>> a//True mpz(123) >>> abs(-a)==a 1 >>> pow(a,10) mpz(792594609605189126649) >>> pow(a,7,b) mpz(99) >>> _g.sign(b-a) 1 >>> _g.sign(b-b) 0 >>> _g.sign(a-b) -1 >>> _g.sign(a) 1 >>> _g.sign(-a) -1 >>> z=b-b; _g.sign(z) 0 >>> import pickle >>> pickle.loads(pickle.dumps(_g.mpz(12346789))) mpz(12346789) >>> s='12345678901234567890123456789' >>> int(s) == _g.mpz(s) True >>> _g.mpz(s) == int(s) True >>> del s >>> _g.is_even(a) False >>> _g.is_odd(a) True >>> _g.is_even(b) True >>> _g.is_odd(b) False >>> _g.is_even(2) True ''' __test__['special'] = \ r''' >>> _g.context().trap_divzero == False True >>> a == float('Inf') False >>> a != float('Inf') True >>> a > float('Inf') False >>> a >= float('Inf') False >>> a < float('Inf') True >>> a <= float('Inf') True >>> a == float('-Inf') False >>> a != float('-Inf') True >>> a > float('-Inf') True >>> a >= float('-Inf') True >>> a < float('-Inf') False >>> a <= float('-Inf') False >>> a == float('nan') False >>> a != float('nan') True >>> a > float('nan') False >>> a >= float('nan') False >>> a < float('nan') False >>> a <= float('nan') False >>> float('Inf') == a False >>> float('Inf') != a True >>> float('Inf') > a True >>> float('Inf') >= a True >>> float('Inf') < a False >>> float('Inf') <= a False >>> float('-Inf') == a False >>> float('-Inf') != a True >>> float('-Inf') > a False >>> float('-Inf') >= a False >>> float('-Inf') < a True >>> float('-Inf') <= a True >>> float('nan') == a False >>> float('nan') != a True >>> float('nan') > a False >>> float('nan') >= a False >>> float('nan') < a False >>> float('nan') <= a False >>> a + float('Inf') mpfr('inf') >>> float('Inf') + a mpfr('inf') >>> a + float('-Inf') mpfr('-inf') >>> float('-Inf') + a mpfr('-inf') >>> a + float('nan') mpfr('nan') >>> float('nan') + a mpfr('nan') >>> a - float('Inf') mpfr('-inf') >>> float('Inf') - a mpfr('inf') >>> a - float('-Inf') mpfr('inf') >>> float('-Inf') - a mpfr('-inf') >>> a - float('nan') mpfr('nan') >>> float('nan') - a mpfr('nan') >>> a * float('Inf') mpfr('inf') >>> float('Inf') * a mpfr('inf') >>> a * float('-Inf') mpfr('-inf') >>> float('-Inf') * a mpfr('-inf') >>> -a * float('Inf') mpfr('-inf') >>> float('Inf') * -a mpfr('-inf') >>> -a * float('-Inf') mpfr('inf') >>> float('-Inf') * -a mpfr('inf') >>> a * float('nan') mpfr('nan') >>> float('nan') * a mpfr('nan') >>> _g.mpz(0) * float('Inf') mpfr('nan') >>> _g.mpz(0) * float('-Inf') mpfr('nan') >>> float('Inf') * _g.mpz(0) mpfr('nan') >>> float('-Inf') * _g.mpz(0) mpfr('nan') >>> a / float('Inf') mpfr('0.0') >>> -a / float('Inf') mpfr('-0.0') >>> float('Inf') / a mpfr('inf') >>> float('Inf') / -a mpfr('-inf') >>> a / float('-Inf') mpfr('-0.0') >>> -a / float('-Inf') mpfr('0.0') >>> float('-Inf') / a mpfr('-inf') >>> float('-Inf') / -a mpfr('inf') >>> a / float('nan') mpfr('nan') >>> float('nan') / a mpfr('nan') >>> float('nan') / _g.mpz(0) mpfr('nan') >>> float('nan') / _g.mpz(0) mpfr('nan') >>> divmod(a, float('Inf')) (mpfr('0.0'), mpfr('123.0')) >>> divmod(a, float('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, float('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, float('-Inf')) (mpfr('0.0'), mpfr('-123.0')) >>> divmod(a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpz(0), float('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(_g.mpz(0), float('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(_g.mpz(0), float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpfr('Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpfr('-Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpfr('nan'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) ''' __test__['divexact']=\ r''' >>> a=_g.mpz('1234567912345678912345679') >>> b=_g.mpz('789789789789789789789789') >>> c=a*b >>> _g.divexact(c,a) mpz(789789789789789789789789) >>> ''' __test__['divmod']=\ r''' >>> _g.c_divmod(17,5) (mpz(4), mpz(-3)) >>> _g.c_divmod(-17,5) (mpz(-3), mpz(-2)) >>> _g.c_divmod(17,-5) (mpz(-3), mpz(2)) >>> _g.c_divmod(-17,-5) (mpz(4), mpz(3)) >>> _g.f_divmod(17,5) (mpz(3), mpz(2)) >>> _g.f_divmod(-17,5) (mpz(-4), mpz(3)) >>> _g.f_divmod(17,-5) (mpz(-4), mpz(-3)) >>> _g.f_divmod(-17,-5) (mpz(3), mpz(-2)) >>> _g.t_divmod(17,5) (mpz(3), mpz(2)) >>> _g.t_divmod(-17,5) (mpz(-3), mpz(-2)) >>> _g.t_divmod(17,-5) (mpz(-3), mpz(2)) >>> _g.t_divmod(-17,-5) (mpz(3), mpz(-2)) ''' __test__['cmpr']=\ r''' >>> c=_g.mpz(a) >>> c is a 1 >>> c==a 1 >>> c>a 0 >>> c>> a>b 0 >>> a>> not _g.mpz(0) 1 >>> not a 0 >>> _g.mpz(1) == None False >>> _g.mpz(1) == '1' False >>> _g.mpz(1) == 'abc' False >>> [_g.mpz(23), None].count(None) 1 >>> _g.mpz(3.14) mpz(3) >>> _g.mpz(_g.mpq(17,3)) mpz(5) >>> _g.mpz(23) mpz(23) >>> _g.mpz(-23) mpz(-23) >>> x=1000*1000*1000*1000*1000*1000*1000 >>> _g.mpz(x) mpz(1000000000000000000000) >>> a == float('Inf') False >>> a != float('Inf') True >>> a > float('Inf') False >>> a >= float('Inf') False >>> a < float('Inf') True >>> a <= float('Inf') True >>> a == float('-Inf') False >>> a != float('-Inf') True >>> a > float('-Inf') True >>> a >= float('-Inf') True >>> a < float('-Inf') False >>> a <= float('-Inf') False >>> a == float('nan') False >>> a != float('nan') True >>> a > float('nan') False >>> a >= float('nan') False >>> a < float('nan') False >>> a <= float('nan') False ''' __test__['bitops']=\ r''' >>> ~a mpz(-124) >>> a&b mpz(72) >>> a|b mpz(507) >>> a^b mpz(435) >>> a<<1 mpz(246) >>> a>>1 mpz(61) >>> a<<-1 Traceback (innermost last): ... ValueError: negative shift count >>> a>>-2 Traceback (innermost last): ... ValueError: negative shift count >>> a<<0 mpz(123) >>> a>>0 mpz(123) >>> _g.popcount(a) 6 >>> _g.popcount(b) 4 >>> _g.popcount(-7) -1 >>> _g.popcount(0) 0 >>> _g.hamdist(a,b) 6 >>> _g.hamdist(3) Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments >>> _g.hamdist(a) Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments >>> _g.hamdist(a, 3, 4) Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments >>> _g.f_mod_2exp(a,5) mpz(27) >>> _g.f_mod_2exp(b,5) mpz(8) >>> _g.f_mod_2exp(b,5)==(b%32) 1 >>> _g.f_mod_2exp(a,5)==(a%32) 1 >>> a.bit_set(20) mpz(1048699) >>> a.bit_clear(0) mpz(122) >>> for i in range(8): ... print(a.bit_test(i)) ... True True False True True True True False >>> for i in range(10): ... print(b.bit_test(i)) ... False False False True False False True True True False >>> [a.bit_scan0(j) for j in range(33)] [2, 2, 2, 7, 7, 7, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> [a.bit_scan1(j) for j in range(10)] [0, 1, 3, 3, 4, 5, 6, None, None, None] >>> n=_g.mpz(-(7+6*16+5*256+7*4092)) >>> [n.bit_scan0(j) for j in range(18)] [1, 1, 3, 3, 6, 6, 6, 8, 8, 10, 10, 12, 12, 13, 14, None, None, None] >>> [n.bit_scan1(j) for j in range(33)] [0, 2, 2, 4, 4, 5, 7, 7, 9, 9, 11, 11, 15, 15, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> _g.mpz(0).bit_length() 0 >>> _g.mpz(12345).bit_length() 14 >>> _g.bit_mask(9) mpz(511) ''' __test__['format']=\ r''' >>> str(a) '123' >>> repr(a) 'mpz(123)' >>> hex(a) '0x7b' >>> oct(a) '0o173' >>> _g.mpz('123') mpz(123) >>> _g.mpz('1001001011',2) mpz(587) >>> _g.mpz('1001001011',2).digits(2) '1001001011' >>> for i in range(2,63): ... print(a.digits(i)) ... 1111011 11120 1323 443 323 234 173 146 123 102 a3 96 8b 83 7b 74 6f 69 63 5i 5d 58 53 4n 4j 4f 4b 47 43 3u 3r 3o 3l 3i 3f 3C 39 36 33 30 2d 2b 2Z 2X 2V 2T 2R 2P 2N 2L 2J 2H 2F 2D 2B 29 27 25 23 21 1z >>> print(a.digits(63)) Traceback (innermost last): ... ValueError: base must be in the interval 2 ... 62 >>> _g.mpz('43') mpz(43) >>> _g.mpz('043') mpz(43) >>> _g.mpz('43',0) mpz(43) >>> _g.mpz('0o43') mpz(35) >>> _g.mpz('0x43') mpz(67) >>> _g.mpz('0x43',10) Traceback (innermost last): File "", line 1, in ? _g.mpz('0x43') ValueError: invalid digits >>> ''' __test__['binio']=\ r''' >>> a == _g.from_binary(_g.to_binary(a)) True >>> -a == _g.from_binary(_g.to_binary(-a)) True >>> z = _g.mpz(573406620562849222387053) >>> for i in range(2,37): ... print(i,z.num_digits(i)) ... 2 79 3 50 4 40 5 35 6 31 7 29 8 27 9 25 10 24 11 23 12 23 13 22 14 21 15 21 16 20 17 20 18 19 19 19 20 19 21 18 22 18 23 18 24 18 25 18 26 17 27 17 28 17 29 17 30 17 31 16 32 16 33 16 34 16 35 16 36 16 >>> _g.num_digits(23) 2 >>> _g.num_digits(23,2) 5 >>> _g.num_digits(23,99) Traceback (most recent call last): File "", line 1, in ? ValueError: base must be in the interval 2 ... 62 >>> hash(a) 123 >>> hash(b) 456 >>> hash(z) == hash(int(z)) True >>> int(_g.mpz(-3)) -3 ''' __test__['number']=\ r''' >>> _g.iroot_rem(a,2) (mpz(11), mpz(2)) >>> _g.iroot_rem(a,3) (mpz(4), mpz(59)) >>> _g.iroot_rem(a*a) Traceback (most recent call last): File "", line 1, in TypeError: iroot_rem() requires 'mpz','int' arguments >>> _g.iroot_rem(a*a,2) (mpz(123), mpz(0)) >>> print(_g.isqrt(a)) 11 >>> print(_g.isqrt(b)) 21 >>> print(_g.isqrt_rem(a)) (mpz(11), mpz(2)) >>> print(_g.isqrt_rem(b)) (mpz(21), mpz(15)) >>> for i in range(5): ... print(_g.iroot(a,i+1),_g.iroot(b,i+1)) ... (mpz(123), True) (mpz(456), True) (mpz(11), False) (mpz(21), False) (mpz(4), False) (mpz(7), False) (mpz(3), False) (mpz(4), False) (mpz(2), False) (mpz(3), False) >>> _g.is_square(a) 0 >>> _g.is_power(a) 0 >>> _g.is_square(99*99) 1 >>> _g.is_square(99*99*99) 0 >>> _g.is_square(0) 1 >>> _g.is_square(-1) 0 >>> _g.is_power(99*99*99) 1 >>> _g.gcd(a,b) mpz(3) >>> temp=_g.gcdext(a,b) >>> temp[0]==a*temp[1]+b*temp[2] True >>> _g.lcm(a,b) mpz(18696) >>> _g.fac(7) mpz(5040) >>> _g.fib(17) mpz(1597) >>> for i in range(10): ... print(_g.bincoef(10,i)) ... 1 10 45 120 210 252 210 120 45 10 >>> _g.divm(b,a,20) mpz(12) >>> _g.divm(a,b,100) Traceback (innermost last): File "", line 1, in ? _g.divm(a,b,100) ZeroDivisionError: not invertible >>> _g.divm(6,12,14) mpz(4) >>> _g.divm(0,1,2) mpz(0) >>> # guard against regression of an ancient gmpy bug: divm w/non-coprime parms >>> _g.divm(4,8,20) mpz(3) >>> _g.divm(4,8,20) mpz(3) >>> _g.mpz(20) mpz(20) >>> _g.mpz(8) mpz(8) >>> _g.mpz(4) mpz(4) >>> # guard against regression of a memory leak in divm >>> __ = gc.collect() >>> _siz = 87654 >>> _siz = _memsize() >>> for x in range(45678): ... _xx=_g.divm(b,a,20) >>> del _xx >>> __ = gc.collect() >>> (_memsize()-_siz) <= 32 True >>> _g.invert(a,100) mpz(87) >>> _g.invert(b,100) Traceback (most recent call last): ... ZeroDivisionError: invert() no inverse exists >>> _g.invert(3) Traceback (innermost last): ... TypeError: invert() requires 'mpz','mpz' arguments >>> _g.invert() Traceback (innermost last): ... TypeError: invert() requires 'mpz','mpz' arguments >>> _g.comb(3,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: binomial coefficient with negative k >>> _g.isqrt(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt() of negative number >>> _g.isqrt_rem(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt_rem() of negative number >>> _g.remove(3,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: factor must be > 1 >>> _g.remove(3) Traceback (innermost last): ... TypeError: remove() requires 'mpz','mpz' arguments >>> _g.remove() Traceback (innermost last): ... TypeError: remove() requires 'mpz','mpz' arguments >>> _g.is_prime(3,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: repetition count for is_prime() must be positive >>> _g.jacobi(10,3) 1 >>> _g.jacobi(10,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: y must be odd and >0 >>> _g.jacobi(3) Traceback (innermost last): ... TypeError: jacobi() requires 'mpz','mpz' arguments >>> _g.jacobi() Traceback (innermost last): ... TypeError: jacobi() requires 'mpz','mpz' arguments >>> _g.legendre(10,3) 1 >>> _g.legendre(10,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: y must be odd and >0 >>> _g.legendre(3) Traceback (innermost last): ... TypeError: legendre() requires 'mpz','mpz' arguments >>> _g.legendre() Traceback (innermost last): ... TypeError: legendre() requires 'mpz','mpz' arguments >>> _g.kronecker(10,3) 1 >>> _g.kronecker(10,-3) 1 >>> _g.kronecker(3) Traceback (innermost last): ... TypeError: kronecker() requires 'mpz','mpz' arguments >>> _g.kronecker() Traceback (innermost last): ... TypeError: kronecker() requires 'mpz','mpz' arguments >>> a=10**20 >>> b=a+39 >>> _g.jacobi(a,b) 1 >>> _g.legendre(a,b) 1 >>> _g.kronecker(a,b) 1 ''' def _test(chat=None): if chat: print("Unit tests for gmpy2 (mpz functionality)") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print("Repeating tests, with caching disabled") _g.set_cache(0,128) sav = sys.stdout class _Dummy: encoding = None def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) finally: sys.stdout = sav if chat: print() print("Overall results for mpz:") return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test3/gmpy_test_mpq.py0000666000000000000000000001412012351625226015566 0ustar rootroot# partial unit test for gmpy2 mpq functionality # relies on Tim Peters' "doctest.py" test-driver r''' >>> list([x for x in dir(a) if x != '__dir__']) ['__abs__', '__add__', '__bool__', '__ceil__', '__class__', '__delattr__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'denominator', 'digits', 'numerator'] >>> ''' import gmpy2 as _g, doctest,sys import fractions F=fractions.Fraction __test__={} a=_g.mpq('123/456') b=_g.mpq('789/123') af=F(123,456) bf=F(789,123) __test__['compat']=\ r''' >>> a==af True >>> af==a True >>> a < af False >>> a <= af True >>> a > af False >>> a >= af True >>> af < a False >>> af <= a True >>> af > a False >>> af >= a True >>> a+bf mpq(41657,6232) >>> divmod(123*a, b) == divmod(123*af, bf) True >>> divmod(-23*a, b) == divmod(-23*af, bf) True >>> divmod(a+17, b-23) == divmod(af+17, bf-23) True >>> divmod(-a, -b) == divmod(-af, -bf) True ''' __test__['elemop']=\ r''' >>> a+b mpq(41657,6232) >>> a-b mpq(-38295,6232) >>> a*b mpq(263,152) >>> a/b mpq(1681,39976) >>> a//b mpz(0) >>> a//-b mpz(-1) >>> -a//b mpz(-1) >>> -a//-b mpz(0) >>> b+a mpq(41657,6232) >>> b-a mpq(38295,6232) >>> b*a mpq(263,152) >>> b/a mpq(39976,1681) >>> b//a mpz(23) >>> a+1 mpq(193,152) >>> 1+a mpq(193,152) >>> a-1 mpq(-111,152) >>> 1-a mpq(111,152) >>> a*1 mpq(41,152) >>> 1*a mpq(41,152) >>> a/1 mpq(41,152) >>> 1/a mpq(152,41) >>> a % b mpq(41,152) >>> a % -b mpq(-38295,6232) >>> 2*a % 7*b mpq(263,76) >>> -a mpq(-41,152) >>> abs(-a) mpq(41,152) >>> _g.sign(b-a) 1 >>> _g.sign(b-b) 0 >>> _g.sign(a-b) -1 >>> _g.sign(a) 1 >>> _g.sign(-a) -1 >>> z=b-b; _g.sign(z) 0 >>> _g.numer(a) == a.numerator True >>> _g.denom(a) == a.denominator True >>> an=_g.numer(a); ad=_g.denom(a); >>> an==0 or 1==a*_g.mpq(ad,an) 1 >>> bn=_g.numer(b); bd=_g.denom(b); >>> bn==0 or 1==b*_g.mpq(bd,bn) 1 >>> zn=_g.numer(z); zd=_g.denom(z); >>> zn==0 or 1==z*_g.mpq(zd,zn) 1 >>> (a+b) == _g.mpq(an*bd+ad*bn,ad*bd) 1 >>> (a+z) == _g.mpq(an*zd+ad*zn,ad*zd) 1 >>> (a+a) == _g.mpq(an*ad+ad*an,ad*ad) 1 >>> import pickle >>> pickle.loads(pickle.dumps(_g.mpq(1234,6789))) mpq(1234,6789) >>> ''' __test__['cmpr']=\ r''' >>> c=_g.mpq(a) >>> c is a 1 >>> c==a 1 >>> c>a 0 >>> c>> a>b 0 >>> a>> not _g.mpq(0) 1 >>> not a 0 >>> a>1 0 >>> a>1.0 0 >>> a<1 1 >>> a<1.0 1 >>> a==1 0 >>> a==1.0 0 >>> int(1/a) 3 >>> int(-1/a) -3 >>> ''' __test__['format']=\ r''' >>> str(a) '41/152' >>> repr(a) 'mpq(41,152)' >>> a==eval(repr(a),_g.__dict__) 1 >>> str(-a) '-41/152' >>> repr(-a) 'mpq(-41,152)' >>> (-a)==eval(repr(-a),_g.__dict__) 1 >>> for i in range(1,7): ... for j in range(3,10): ... if _g.mpq(i,j) != _g.mpq("%d/%d"%(i,j)): ... print('er1:',i,j); break ... aa=_g.mpq(i,j); ai=_g.numer(aa); aj=_g.denom(aa) ... if aj!=1 and str(aa) != ("%d/%d"%(ai,aj)): ... print('er2:',i,j,str(aa),("%d/%d"%(ai,aj))); break ... if aj==1 and str(aa) != ("%d"%ai): ... print('er3:',i,j,str(aa),"%d"%ai); break ... if aj!=1 and repr(aa) != ("mpq(%d,%d)"%(ai,aj)): ... print('er4:',i,j,repr(aa),("mpq(%d,%d)"%(ai,aj))); break ... if aj==1 and repr(aa) != ("mpq(%d,%d)"%(ai,aj)): ... print('er5:',i,j,repr(aa),"mpq(%d,%d)"%(ai,aj)); break >>> fmo='_g.mpq('+hex(a.numerator)+','+hex(a.denominator)+')' >>> fmo '_g.mpq(0x29,0x98)' >>> eval(fmo)==a 1 >>> fmo='_g.mpq("'+_g.numer(a).digits(30)+'/'+_g.denom(a).digits(30)+'",30)' >>> fmo '_g.mpq("1b/52",30)' >>> eval(fmo)==a 1 >>> _g.digits(a,30) '1b/52' >>> a.digits(30) '1b/52' >>> _g.mpq(1000*1000*1000*1000*1000*1000*1000,23) mpq(1000000000000000000000,23) >>> _g.mpq(23,1000*1000*1000*1000*1000*1000*1000) mpq(23,1000000000000000000000) >>> _g.mpq(23**15,1000**7) mpq(266635235464391245607,1000000000000000000000) >>> x=_g.mpq('234/567') >>> del x >>> _g.mpq('7788') mpq(7788,1) >>> _g.mpq('12.34') mpq(617,50) ''' __test__['binio']=\ r''' >>> a == _g.from_binary(_g.to_binary(a)) True >>> -a == _g.from_binary(_g.to_binary(-a)) True ''' __test__['power']=\ r''' >>> _g.mpq(2,3)**3 mpq(8,27) >>> _g.mpq(8,27)**_g.mpq('2/3') mpfr('0.44444444444444448') >>> _g.mpq(2,3)**-3 mpq(27,8) >>> _g.mpq(8,27)**_g.mpq('-2/3') mpfr('2.25') >>> _g.mpq(3)**3 == _g.mpz(3)**3 True >>> (a**-7) == 1/(a**7) True >>> (b**5) == 1/(b**-5) True >>> ''' __test__['qdiv']=\ r''' >>> _g.qdiv(12,2) mpz(6) >>> _g.qdiv(12,5) mpq(12,5) >>> a is _g.qdiv(a) 1 >>> a is _g.qdiv(a,1) 1 >>> a is _g.qdiv(a,2) 0 >>> x=_g.numer(a) >>> x is _g.qdiv(x) 1 >>> x is _g.qdiv(x,1) 1 >>> x is _g.qdiv(x,2) 0 >>> y=_g.mpq(4,1) >>> y is _g.qdiv(y) 0 >>> y == _g.qdiv(y) 1 >>> ''' def _test(chat=None): if chat: print("Unit tests for gmpy2 (mpq functionality)") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print("Repeating tests, with caching disabled") _g.set_cache(0,128) sav = sys.stdout class _Dummy: encoding = None def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) finally: sys.stdout = sav if chat: print() print("Overall results for mpq:") return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test3/gmpy_test_mpf.py0000666000000000000000000002073012351625226015557 0ustar rootroot# partial unit test for gmpy2 mpfr functionality # relies on Tim Peters' "doctest.py" test-driver r''' >>> list([x for x in dir(a) if x != '__dir__']) ['__abs__', '__add__', '__bool__', '__ceil__', '__class__', '__delattr__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'as_mantissa_exp', 'as_simple_fraction', 'conjugate', 'digits', 'imag', 'is_integer', 'precision', 'rc', 'real'] >>> ''' import sys import gmpy2 as _g, doctest, sys __test__={} a=_g.mpfr('123.456') b=_g.mpfr('789.123') __test__['functions']=\ r''' >>> _g.log(2) mpfr('0.69314718055994529') >>> _g.log(10) mpfr('2.3025850929940459') >>> _g.log('a') Traceback (most recent call last): File "", line 1, in TypeError: log() argument type not supported >>> _g.log(float('nan')) mpfr('nan') >>> _g.log(float('inf')) mpfr('inf') >>> _g.log(float('-inf')) mpfr('nan') >>> _g.log(_g.mpfr('12.3456')) mpfr('2.5132997242892183') ''' __test__['elemop']=\ r''' >>> str(a+b) '912.57900000000006' >>> str(a-b) '-665.66700000000003' >>> str(a*b) '97421.969088000013' >>> str(a/b) '0.15644709379906555' >>> str(b+a) '912.57900000000006' >>> str(b-a) '665.66700000000003' >>> str(b*a) '97421.969088000013' >>> str(b/a) '6.3919372083981338' >>> str(-a) '-123.456' >>> str(abs(-a)) '123.456' >>> _g.mpfr(2) + 3 mpfr('5.0') >>> 3 + _g.mpfr(2) mpfr('5.0') >>> _g.mpfr(2) * 3 mpfr('6.0') >>> 3 * _g.mpfr(2) mpfr('6.0') >>> _g.sign(b-a) 1 >>> _g.sign(b-b) 0 >>> _g.sign(a-b) -1 >>> _g.sign(a) 1 >>> _g.sign(-a) -1 >>> z=b-b; _g.sign(z) 0 >>> import math >>> math.ceil(a) mpfr('124.0') >>> str(a.__ceil__()) '124.0' >>> str(_g.ceil(a)) '124.0' >>> math.floor(a) mpfr('123.0') >>> str(a.__floor__()) '123.0' >>> str(_g.floor(a)) '123.0' >>> math.trunc(a) mpfr('123.0') >>> str(a.__trunc__()) '123.0' >>> str(_g.trunc(a)) '123.0' >>> x=-a >>> math.floor(x) mpfr('-124.0') >>> str(x.__floor__()) '-124.0' >>> str(_g.floor(x)) '-124.0' >>> math.ceil(x) mpfr('-123.0') >>> str(x.__ceil__()) '-123.0' >>> str(_g.ceil(x)) '-123.0' >>> math.trunc(x) mpfr('-123.0') >>> str(x.__trunc__()) '-123.0' >>> str(_g.trunc(x)) '-123.0' >>> _g.ceil(12.3)==math.ceil(12.3) 1 >>> _g.floor(12.3)==math.floor(12.3) 1 >>> _g.ceil(-12.3)==math.ceil(-12.3) 1 >>> _g.floor(-12.3)==math.floor(-12.3) 1 >>> _g.reldiff(a**2,float(a)**2) < 1.03 * (2.0**-(a.precision-1)) 1 >>> _g.reldiff(a**2,a*a) < (2.0**-(a.precision-1)) 1 >>> _g.reldiff(b**2,float(b)**2) < 1.03 * (2.0**-(b.precision-1)) 1 >>> _g.reldiff(b**2,b*b) < (2.0**-(b.precision-1)) 1 >>> _g.reldiff(3.4) Traceback (innermost last): File "", line 1, in ? _g.reldiff(3.4) TypeError: reldiff() requires 'mpfr','mpfr' arguments >>> _g.sqrt(a) mpfr('11.111075555498667') >>> _g.sqrt(-1) mpfr('nan') >>> save=_g.get_context().precision >>> _g.const_catalan() mpfr('0.91596559417721901') >>> _g.const_euler() mpfr('0.57721566490153287') >>> _g.const_log2() mpfr('0.69314718055994529') >>> _g.const_pi() mpfr('3.1415926535897931') >>> _g.get_context().precision = 100 >>> _g.const_catalan() mpfr('0.91596559417721901505460351493252',100) >>> _g.const_euler() mpfr('0.57721566490153286060651209008234',100) >>> _g.const_log2() mpfr('0.69314718055994530941723212145798',100) >>> _g.const_pi() mpfr('3.1415926535897932384626433832793',100) >>> _g.get_context().precision = save >>> del(save) >>> import pickle >>> flt = _g.mpfr(1234.6789) >>> flt == pickle.loads(pickle.dumps(flt)) True >>> flt = _g.mpfr('1.1') >>> flt == pickle.loads(pickle.dumps(flt)) True ''' __test__['newdiv']=\ r''' >>> >>> a/b mpfr('0.15644709379906555') >>> a//b mpfr('0.0') >>> b/a mpfr('6.3919372083981338') >>> b//a mpfr('6.0') >>> ''' __test__['cmpr']=\ r''' >>> c=_g.mpfr(a) >>> c is a 1 >>> c==a 1 >>> c>a 0 >>> c>> a>b 0 >>> a>> not _g.mpfr(0) 1 >>> not a 0 >>> _g.f2q(a,0.1) mpz(123) >>> _g.f2q(a,0.01) mpz(123) >>> _g.f2q(a,0.001) mpq(247,2) >>> _g.f2q(a,0.0001) mpq(1358,11) >>> _g.f2q(a,0.00001) mpq(7037,57) >>> _g.f2q(a,0.000001) mpq(15432,125) >>> _g.f2q(a,0.0000001) mpq(15432,125) >>> _g.f2q(a) mpq(15432,125) >>> print(_g.mpfr(_g.mpz(1234))) 1234.0 >>> x=1000*1000*1000*1000 >>> _g.mpfr(x) mpfr('1000000000000.0') >>> c=_g.mpfr(a) >>> a is c 1 >>> c=_g.mpfr(a,99) >>> a is c 0 >>> a==c 1 >>> _g.mpfr('1.1') == _g.mpfr('1.1') * _g.mpfr(1) True >>> _g.mpfr('1.1',64) == _g.mpfr('1.1',128) False >>> _g.mpfr('1.1',64) == _g.mpfr(_g.mpfr('1.1',128),64) True >>> a = _g.mpfr('.123', 64) >>> b = _g.mpfr('.123', 128) >>> c = _g.mpfr('.123', 128) * _g.mpfr(1, 128) >>> a == b False >>> a == c False >>> b == c False >>> f=_g.mpfr >>> bool(float('nan')) == bool(f('nan')) True >>> (float('nan') == float('nan')) == (float('nan') == f('nan')) == (f('nan') == float('nan')) == (f('nan') == f('nan')) True >>> (float('nan') != float('nan')) == (float('nan') != f('nan')) == (f('nan') != float('nan')) == (f('nan') != f('nan')) True >>> bool(float('inf')) == bool(f('inf')) True >>> bool(float('-inf')) == bool(f('-inf')) True ''' __test__['format']=\ r''' >>> str(a) '123.456' >>> repr(a) "mpfr('123.456')" >>> a.digits(10,0) ('12345600000000000', 3, 53) >>> a.digits(10,1) Traceback (most recent call last): ... ValueError: digits must be 0 or >= 2 >>> a.digits(10,2) ('12', 3, 53) >>> a.digits(10,3) ('123', 3, 53) >>> a.digits(10,4) ('1235', 3, 53) >>> a.digits(10,5) ('12346', 3, 53) >>> a.digits(10,6) ('123456', 3, 53) >>> a.digits(10,7) ('1234560', 3, 53) >>> a.digits(10,8) ('12345600', 3, 53) >>> for i in range(11,99): ... tempa=('%.16f' % (i/10.0)).replace('.','') ... tempb=_g.mpfr(i/10.0).digits(10,17)[0] ... assert tempb.startswith(tempa.rstrip('0')), (tempa, tempb) ... >>> _g.mpfr(3.4) mpfr('3.3999999999999999') >>> print(_g.mpfr(3.4)) 3.3999999999999999 >>> a.digits(1) Traceback (most recent call last): File "", line 1, in ? ValueError: base must be in the interval 2 ... 62 >>> a.digits(2,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: digits must be 0 or >= 2 >>> a.digits(10,0) ('12345600000000000', 3, 53) >>> saveprec=a.precision >>> newa = _g.round2(a,33) >>> newa mpfr('123.456',33) >>> newa = _g.round2(newa,saveprec) >>> newa.precision==saveprec 1 >>> del(newa) >>> _g.digits(_g.mpfr(23.45)) ('23449999999999999', 2, 53) >>> ''' __test__['binio']=\ r''' >>> _g.from_binary('pep') Traceback (most recent call last): File "", line 1, in ? TypeError: from_binary() requires bytes argument >>> a == _g.from_binary(_g.to_binary(a)) True >>> -a == _g.from_binary(_g.to_binary(-a)) True >>> 1/a == _g.from_binary(_g.to_binary(1/a)) True >>> _g.to_binary(_g.mpfr(0)) b'\x04\x00\x00\x005\x00\x00\x00' >>> 0 == _g.from_binary(_g.to_binary(_g.mpfr(0))) True >>> 0.5 == _g.from_binary(_g.to_binary(_g.mpfr(0.5))) True >>> -0.5 == _g.from_binary(_g.to_binary(_g.mpfr(-0.5))) True >>> -2.0 == _g.from_binary(_g.to_binary(_g.mpfr(-2.0))) True >>> 2.0 == _g.from_binary(_g.to_binary(_g.mpfr(2.0))) True >>> hash(_g.mpfr(23.0))==hash(23) True >>> int(a) 123 >>> int(-a) -123 >>> ''' def _test(chat=None): if chat: print("Unit tests for gmpy2 (mpfr functionality)") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print("Repeating tests, with caching disabled") _g.set_cache(0,128) sav = sys.stdout class _Dummy: encoding = None def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) finally: sys.stdout = sav if chat: print() print("Overall results for mpfr:") return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test3/gmpy_test_dec.py0000666000000000000000000000533212351625226015531 0ustar rootroot# partial unit test for gmpy/decimal interoperability # relies on Tim Peters' "doctest.py" test-driver r''' >>> list([x for x in dir(f) if x != '__dir__']) ['__abs__', '__add__', '__bool__', '__ceil__', '__class__', '__delattr__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'as_mantissa_exp', 'as_simple_fraction', 'conjugate', 'digits', 'imag', 'is_integer', 'precision', 'rc', 'real'] >>> ''' try: import decimal as _d except ImportError: _d = None import gmpy2 as _g, doctest, sys __test__={} f=_g.mpfr('123.456') q=_g.mpq('789123/1000') z=_g.mpz('234') if _d: d=_d.Decimal('12.34') fd=_d.Decimal('123.456') qd=_d.Decimal('789.123') zd=_d.Decimal('234') __test__['compat']=\ r''' >>> f == fd False >>> fd == f False >>> q == qd True >>> qd == q True >>> z == zd True >>> zd == z True >>> f > d True >>> d > f False ''' __test__['elemop']=\ r''' >>> print(_g.mpz(23) == _d.Decimal(23)) True >>> print(_g.mpz(d)) 12 >>> print(_g.mpq(d)) 617/50 >>> print(_g.mpfr(d)) 12.34 >>> print(f+d) 135.79599999999999 >>> print(d+f) 135.79599999999999 >>> print(q+d) 801.46300000000008 >>> print(d+q) 801.46300000000008 >>> print(z+d) 246.34 >>> print(d+z) 246.34 >>> print(_g.ceil(d)) 13.0 >>> print(_g.floor(d)) 12.0 >>> print(_g.trunc(d)) 12.0 >>> _g.mpfr(d).precision 53 >>> ''' def _test(chat=None): if chat: print("Unit tests for gmpy2 (decimal interoperation)") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) if not _d: if chat: print("Can't test, since can't import decimal") return 0, 0 thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) if chat: print() print("Overall results for dec:") return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test3/gmpy_test_cvr.py0000666000000000000000000003160312564432250015567 0ustar rootroot# partial unit test for gmpy2 extra cover # relies on Tim Peters' "doctest.py" test-driver r''' >>> _g.version() '2.0.7' >>> int('gmpy2.c' in _g._cvsid()) 1 ''' import gmpy2 as _g, doctest, sys __test__={} __test__['misc_stuff']=\ r''' >>> print(_g.mpfr(3.0)) 3.0 >>> _g.mp_limbsize() in (32, 64) True >>> _g.next_prime(2357*7069-1) == 2357*7069 False ''' # If the next_prime() test fails, you have encountered a bug in MPIR. Please # see https://code.google.com/p/gmpy/issues/detail?id=76 for more details. try: x = float('inf') except ValueError: pass else: __test__['infinity'] = \ r''' >>> x = float('inf') >>> n = float('nan') >>> _g.mpfr(x) mpfr('inf') >>> _g.mpfr(-x) mpfr('-inf') >>> _g.mpq(x) Traceback (most recent call last): ... OverflowError: 'mpq' does not support Infinity >>> _g.mpq(-x) Traceback (most recent call last): ... OverflowError: 'mpq' does not support Infinity >>> _g.mpz(x) Traceback (most recent call last): ... OverflowError: 'mpz' does not support Infinity >>> _g.mpz(-x) Traceback (most recent call last): ... OverflowError: 'mpz' does not support Infinity >>> _g.mpfr(n) mpfr('nan') >>> _g.mpfr(n) mpfr('nan') >>> _g.mpfr(n) mpfr('nan') ''' __test__['user_errors']=\ r''' >>> _g.version(23) Traceback (most recent call last): ... TypeError: version() takes no arguments (1 given) >>> _g.mp_version(23) Traceback (most recent call last): ... TypeError: mp_version() takes no arguments (1 given) >>> _g.get_cache(23) Traceback (most recent call last): ... TypeError: get_cache() takes no arguments (1 given) >>> _g.set_cache() Traceback (most recent call last): ... TypeError: function takes exactly 2 arguments (0 given) >>> _g.set_cache(200) Traceback (most recent call last): ... TypeError: function takes exactly 2 arguments (1 given) >>> _g.set_cache(200,-23) Traceback (most recent call last): ... ValueError: object size must between 0 and 16384 >>> _g.set_cache(2000,256) Traceback (most recent call last): ... ValueError: cache size must between 0 and 1000 >>> _g.set_cache(-23,256) Traceback (most recent call last): ... ValueError: cache size must between 0 and 1000 >>> _g.set_cache(200,256000) Traceback (most recent call last): ... ValueError: object size must between 0 and 16384 >>> _g.context().precision = -1 Traceback (most recent call last): File "", line 1, in ? ValueError: invalid value for precision >>> _g.mpz('12'+chr(0)+'34') Traceback (most recent call last): File "", line 1, in ? ValueError: string contains NULL characters >>> _g.mpfr('12'+chr(0)+'34') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> _g.mpq('12'+chr(0)+'34') Traceback (most recent call last): File "", line 1, in ? ValueError: string contains NULL characters >>> _g.mpq_from_old_binary(b'bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid mpq binary (too short) >>> _g.mpq_from_old_binary(b'bologna') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid mpq binary (num len) >>> _g.mpq_from_old_binary(b'\001\000\000\000\003\002') mpq(3,2) >>> _g.mpq('ba/bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> print('ba/bo') ba/bo >>> _g.mpq('1/bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> print('1/bo') 1/bo >>> _g.mpq('1/0') Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: zero denominator in 'mpq' >>> _g.mpfr([]) Traceback (most recent call last): File "", line 1, in ? TypeError: mpfr() requires numeric or string argument >>> _g.mpfr_from_old_binary(b'bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid mpf binary encoding (too short) >>> _g.mpfr('bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> int(_g.mpz(1000*1000*1000*1000*1000*1000*1000)) 1000000000000000000000 >>> _g.bit_scan0(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: starting bit must be >= 0 >>> _g.bit_scan1(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: starting bit must be >= 0 >>> _g.f_mod_2exp(12,-1) Traceback (most recent call last): File "", line 1, in ? OverflowError: can't convert negative value to unsigned int >>> _g.bit_test(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: bit_index must be >= 0 >>> _g.bit_set(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: bit_index must be >= 0 >>> _g.mpz(23).bit_set(12,1,2,3) Traceback (most recent call last): ... TypeError: bit_set() takes exactly one argument (4 given) >>> _g.bit_set(12,1,2,3) Traceback (most recent call last): ... TypeError: bit_set() requires 'mpz','int' arguments >>> _g.root(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: n must be > 0 >>> _g.root(12,0) Traceback (most recent call last): File "", line 1, in ? ValueError: n must be > 0 >>> _g.iroot(-12,2) Traceback (most recent call last): File "", line 1, in ? ValueError: iroot() of negative number >>> _g.digits(3,'peep') Traceback (most recent call last): ... TypeError: digits() requires 'int' argument for base >>> _g.digits(3.14) ('31400000000000001', 1, 53) >>> _g.mpz(3).digits('bu') Traceback (most recent call last): ... TypeError: digits() requires 'int' argument for base >>> _g.mpfr(3).digits('bu') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.qdiv(3,_g.mpq(1)) mpz(3) >>> _g.qdiv(3,_g.mpz(1)) mpz(3) >>> _g.qdiv(3,_g.mpfr(1)) mpz(3) >>> _g.qdiv(3,1.0) mpz(3) >>> _g.qdiv(3,1) mpz(3) >>> _g.qdiv(3) mpz(3) >>> _g.qdiv(3,'bu') Traceback (most recent call last): File "", line 1, in ? TypeError: second argument cannot be converted to 'mpq' >>> _g.qdiv(3,4,5) Traceback (most recent call last): File "", line 1, in ? TypeError: function takes at most 2 arguments (3 given) >>> _g.qdiv('bu') Traceback (most recent call last): File "", line 1, in ? TypeError: first argument cannot be converted to 'mpq' >>> _g.qdiv(1.0,1) Traceback (most recent call last): File "", line 1, in ? TypeError: first argument cannot be converted to 'mpq' >>> _g.qdiv(1,0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: division or modulo by zero in qdiv >>> _g.f2q(-1.0) mpz(-1) >>> _g.mpz(1,2,3) Traceback (most recent call last): File "", line 1, in ? TypeError: function takes at most 2 arguments (3 given) >>> _g.mpz('bi','bo') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpz('bi',99) Traceback (most recent call last): File "", line 1, in ? ValueError: base for mpz() must be 0 or in the interval 2 ... 62 >>> _g.mpz(1,2) Traceback (most recent call last): File "", line 1, in ? TypeError: mpz() with non-string argument needs exactly 1 argument >>> _g.mpz(None) Traceback (most recent call last): File "", line 1, in ? TypeError: mpz() requires numeric or string argument >>> _g.mpq(1,2,3) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq() requires 0, 1 or 2 arguments >>> _g.mpq('bi','bo') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpq('bi',99) Traceback (most recent call last): File "", line 1, in ? ValueError: base for mpq() must be 0 or in the interval 2 ... 62 >>> _g.mpq(None) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq() requires numeric or string argument >>> _g.mpq(1,None) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq() requires numeric or string argument >>> _g.mpq(1,0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: zero denominator in 'mpq' >>> _g.mpfr() mpfr('0.0') >>> _g.mpfr(1,'bo') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpfr(1,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: precision for mpfr() must be >= 0 >>> _g.mpfr('ba',0,'bu') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpfr('ba',0,99) Traceback (most recent call last): File "", line 1, in ? ValueError: base for mpfr() must be 0 or in the interval 2 ... 62 >>> _g.mpfr(1,2,3) Traceback (most recent call last): File "", line 1, in ? TypeError: function takes at most 2 arguments (3 given) >>> +_g.mpz(1) mpz(1) >>> +_g.mpfr(1) mpfr('1.0') >>> +_g.mpq(1) mpq(1,1) >>> _g.mpz(2)**-2 Traceback (most recent call last): File "", line 1, in ? ValueError: pow() exponent cannot be negative >>> _g.mpz(2)**_g.mpz(1000000000000000*1000000000000000) Traceback (most recent call last): File "", line 1, in ? ValueError: pow() outrageous exponent >>> pow(_g.mpz(2),3,0) Traceback (most recent call last): File "", line 1, in ? ValueError: pow() 3rd argument cannot be 0 >>> pow(_g.mpz(2),3,-5) mpz(-2) >>> pow(_g.mpq(2),3,-5) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq.pow() no modulo allowed >>> a=10000000000**2 >>> _g.mpq(2)**a Traceback (most recent call last): File "", line 1, in ? ValueError: mpq.pow() outrageous exponent >>> _g.mpq(2)**_g.mpq(1,a) mpfr('1.0') >>> _g.mpq(2)**0 mpq(1,1) >>> _g.mpq(2)**-1 mpq(1,2) >>> _g.mpq(2)**_g.mpq(1,2) mpfr('1.4142135623730951') >>> _g.mpq(-2)**_g.mpq(1,2) mpfr('nan') >>> _g.mpq(0)**_g.mpq(1,2) mpfr('0.0') >>> _g.mpq(0)**-1 Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: mpq.pow() 0 base to negative exponent >>> _g.mpq(-1)**-1 mpq(-1,1) >>> _g.mpfr(9,100)**2 mpfr('81.0') >>> _g.mpfr(9,100)**0.5 mpfr('3.0') >>> _g.mpfr(9,100)**_g.mpfr(0.5) mpfr('3.0') >>> _g.mpfr(0)**2 mpfr('0.0') >>> pow(_g.mpfr(2),3,-5) Traceback (most recent call last): File "", line 1, in ? TypeError: pow() 3rd argument not allowed unless all arguments are integers >>> _g.mpz(1)+'bu' Traceback (most recent call last): File "", line 1, in ? TypeError: unsupported operand type(s) for +: 'mpz' and 'str' >>> _g.mpz(1)+_g.mpfr(1) mpfr('2.0') >>> _g.mpz(1)+_g.mpq(1) mpq(2,1) >>> _g.mpq(1)+'bu' Traceback (most recent call last): File "", line 1, in ? TypeError: unsupported operand type(s) for +: 'mpq' and 'str' >>> _g.mpfr(1)+'bu' Traceback (most recent call last): File "", line 1, in ? TypeError: unsupported operand type(s) for +: 'mpfr' and 'str' >>> _g.mpfr(1)+_g.mpq(2) mpfr('3.0') >>> divmod(_g.mpz(3),0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: division or modulo by zero >>> divmod(_g.mpz(0),3) (mpz(0), mpz(0)) >>> _g.divm(1,2,0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: not invertible >>> abs(_g.mpq(0)) mpq(0,1) >>> _g.mpz(0)**2 mpz(0) >>> _g.mpq(-2)**0 mpq(1,1) >>> _g.fac(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: fac() of negative number >>> _g.fib(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: Fibonacci of negative number >>> _g.comb(7,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: binomial coefficient with negative k >>> _g.isqrt_rem(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt_rem() of negative number >>> _g.isqrt(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt() of negative number >>> _g.jacobi(23, -34) Traceback (most recent call last): ... ValueError: y must be odd and >0 >>> _g.legendre(23, -34) Traceback (most recent call last): ... ValueError: y must be odd and >0 >>> # guard against conversion error on 64-bit systems >>> _g.mpz(2**32) != _g.mpz(0) True >>> # test hash properties on 64-bit systems >>> temp = 123456789012345678901234567890 >>> hash(temp) == hash(_g.mpz(temp)) True >>> del temp ''' def _test(chat=None): if chat: print("Unit tests for gmpy2 (extra cover)") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) print(__test__.keys()) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) if chat: print() print("Overall results for cvr:") return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test3/gmpy_test.py0000666000000000000000000000246012204747360014716 0ustar rootrootimport sys import doctest import gmpy2 if sys.argv[-1] == 'debug': gmpy.set_debug(1) import gmpy_test_cvr #~ import gmpy_test_rnd import gmpy_test_mpf import gmpy_test_mpq import gmpy_test_mpz import gmpy_test_dec import gmpy_test_xmpz test_modules = (gmpy_test_cvr, gmpy_test_mpf, gmpy_test_mpq, gmpy_test_mpz, gmpy_test_dec, gmpy_test_xmpz) _g = gmpy2 print("Unit tests for gmpy2") print(" on Python %s" % sys.version) print("Testing gmpy2 {0}".format(_g.version())) print(" Mutliple-precision library: {0}".format(_g.mp_version())) print(" Floating-point library: {0}".format(_g.mpfr_version())) print(" Complex library: {0}".format(_g.mpc_version())) print(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) print(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) pf, pt = 0, 0 for x in test_modules: testit = x._test() failures, tests = testit if tests == 0: continue print("%s %3d tests, %d failures" % (x.__name__, tests-pt, failures-pf)) pf, pt = failures, tests doctest.master.summarize(1) if sys.version_info < (3,1,1): print("There is a known bug with Fraction == mpq for versions of Python") print("less than 3.1.1. Please upgrade if you rely on comparisons between") print("Python's Fraction and gmpy2's mpq.") gmpy2-2.0.7/test2/0000755000000000000000000000000012567136721012327 5ustar rootrootgmpy2-2.0.7/test2/timing3.py0000666000000000000000000000147312204747360014257 0ustar rootrootimport gmpy2 as _g import time print "Typical expected results would be:",""" D:\PySym>python timing.py Factorial of 10000 took 0.0619989238859 (35660 digits) Fibonacci of 10000 took 0.000744228458022 (2090 digits) Factorial of 100000 took 4.44311764676 (456574 digits) Fibonacci of 100000 took 0.022344453738 (20899 digits) Factorial of 1000000 took 152.151135367 (5565709 digits) Fibonacci of 1000000 took 0.670207059778 (208988 digits) """ print "Actual timings and results...:" for i in (10000,100000,1000000): start=time.clock() x=_g.fac(i) stend=time.clock() print "Factorial of %d took %s (%d digits)" % ( i, stend-start, x.num_digits()) start=time.clock() x=_g.fib(i) stend=time.clock() print "Fibonacci of %d took %s (%d digits)" % ( i, stend-start, x.num_digits()) gmpy2-2.0.7/test2/timing2.py0000666000000000000000000000131212204747360014246 0ustar rootrootimport time import gmpy2 as gmpy def timedfib(n, zero): start=time.clock() a=zero; b=a+1 for i in range(n): a,b=b,a+b stend=time.clock() return type(zero), stend-start, a def timedfibsp(n, one): start=time.clock() result=gmpy.fib(n) stend=time.clock() return type(one), stend-start, result def test(n=100*1000): print "%dth Fibonacci number of various types:" % n for z in 0L, gmpy.mpz(0), gmpy.mpf(0): tip, tim, tot = timedfib(n, z) print " %5.3f %s %s" % (tim, gmpy.fdigits(tot,10,6), tip) tip, tim, tot = timedfibsp(n, 1) print " %5.3f %s %s" % (tim, gmpy.fdigits(tot,10,6), "gmpy.fib") if __name__=='__main__': test() gmpy2-2.0.7/test2/timing1.py0000666000000000000000000000233312204747360014251 0ustar rootrootimport time import gmpy2 as gmpy try: sum except NameError: def sum(x, z): for item in x: z += item return z def timedsum(n, zero): start=time.clock() tot=zero for i in range(n): tot+=i stend=time.clock() return type(zero), stend-start, tot def timedsum1(n, zero): start=time.clock() tot=sum(range(n), zero) stend=time.clock() return type(zero), stend-start, tot def timedmul(n, one): start=time.clock() tot=one for i in range(n): tot*=(i+1) stend=time.clock() return type(one), stend-start, tot def test(n=100*1000): print "Sum of %d items of various types:" % n for z in 0L, 0.0, gmpy.mpz(0), gmpy.mpf(0): tip, tim, tot = timedsum(n, z) print " %5.3f %.0f %s" % (tim, float(tot), tip) print "Sum of %d items of various types w/2.3 sum builtin:" % n for z in 0L, 0.0, gmpy.mpz(0), gmpy.mpf(0): tip, tim, tot = timedsum1(n, z) print " %5.3f %.0f %s" % (tim, float(tot), tip) print "Mul of %d items of various types:" % (n//5) for z in 1L, 1.0, gmpy.mpz(1), gmpy.mpf(1): tip, tim, tot = timedmul(n//5, z) print " %5.3f %s" % (tim, tip) if __name__=='__main__': test() gmpy2-2.0.7/test2/test_mpz_args.py0000666000000000000000000000363012204747360015563 0ustar rootroot# Test a wide variety of input values to the commonly used mpz operations. # This test should be run whenever optimizations are made to the handling of # arguments. import sys import gmpy2 as gmpy if sys.version.startswith('3'): intTypes = (int,) else: intTypes = (int, long) def writeln(s): sys.stdout.write(s+'\n') valueList = [0, 1, 2, 3, 4, 5] for power in (15, 16, 30, 32, 45, 48, 60, 64, 75, 90, 96, 105, 120, 128): for i in (-2, -1, 0, 1, 2): valueList.append(2**power + i) valueList.append('123456789012345678901234567890') valueList.append('10000000000000000000000000000000000000000000000000000000000000000') testValues = [] mpzValues = [] for i in valueList: for t in intTypes: testValues.append(t(i)) testValues.append(-t(i)) mpzValues.append(gmpy.mpz(i)) mpzValues.append(-gmpy.mpz(i)) testValues.extend(mpzValues) for i in testValues: for z in mpzValues: # Test all permutations of addition assert int(i)+int(z) == i+z, (repr(i),repr(z)) assert int(z)+int(i) == z+i, (repr(i),repr(z)) # Test all permutations of subtraction assert int(i)-int(z) == i-z, (repr(i),repr(z)) assert int(z)-int(i) == z-i, (repr(i),repr(z)) # Test all permutations of multiplication assert int(i)*int(z) == i*z, (repr(i),repr(z)) assert int(z)*int(i) == z*i, (repr(i),repr(z)) # Test all permutations of division if z!=0: temp = int(i)//int(z) assert int(i)//int(z) == i//z, (repr(i),repr(z)) assert int(i)%int(z) == i%z, (repr(i),repr(z)) assert divmod(int(i),int(z)) == divmod(i,z), (repr(i),repr(z)) if i!=0: temp = int(z)//int(i) assert int(z)//int(i) == z//i, (repr(i),repr(z)) assert int(z)%int(i) == z%i, (repr(i),repr(z)) assert divmod(int(z),int(i)) == divmod(z,i), (repr(i),repr(z)) gmpy2-2.0.7/test2/test_large.py0000666000000000000000000000156412204747360015037 0ustar rootrootfrom gmpy2 import * from math import log from time import time # This test is designed to detect issues when allocating memory for large # numbers. If it crashes and you need to work with very large numbers, # you will need to compile GMP from scratch and try a different memory # allocation option. def pi(N): print "Computing pi to %s decimal places." % N start = time() N = int(round(log(10,2)*N)) sq2 = fsqrt(mpf(2, N)) a = mpz(6) - 4*sq2 y = sq2-1 for k in range(0, 10000): xx = fsqrt(fsqrt(1-y**4)) y = (1-xx)/(1+xx) anew = a*(1+y)**4 - 2**(2*k+3)*y*(1+y+y**2) if anew == a: break a = anew print "Computation took %5.2f seconds." % (time() - start) return 1/a if __name__ == '__main__': print "Testing operations with large numbers." pi(1000000) gmpy2-2.0.7/test2/gmpy_truediv.py0000666000000000000000000000017612204747360015422 0ustar rootroot''' make a "true division" function available for testing ''' from __future__ import division def truediv(a, b): return a/b gmpy2-2.0.7/test2/gmpy_test_thr.py0000666000000000000000000000676212204747360015603 0ustar rootroot# partial unit test for gmpy2 threaded mpz functionality # relies on Tim Peters' "doctest.py" test-driver import gmpy2 as _g, doctest, sys, operator, gc, Queue, threading __test__={} def _tf(N=2, _K=1234**5678): """Takes about 100ms on a first-generation Macbook Pro""" for i in range(N): assert (_g.mpz(1234)**5678)==_K a=_g.mpz(123) b=_g.mpz(456) c=_g.mpz(123456789123456789) def factorize(x=c): r''' (Takes about 25ms, on c, on a first-generation Macbook Pro) >>> factorize(a) [3, 41] >>> factorize(b) [2, 2, 2, 3, 19] >>> ''' import gmpy2 as _g savex=x prime=2 x=_g.mpz(x) factors=[] while x>=prime: newx,mult=x.remove(prime) if mult: factors.extend([int(prime)]*mult) x=newx prime=_g.next_prime(prime) for factor in factors: assert _g.is_prime(factor) from operator import mul assert reduce(mul, factors)==savex return factors def elemop(N=1000): r''' (Takes about 40ms on a first-generation Macbook Pro) ''' for i in range(N): assert a+b == 579 assert a-b == -333 assert b*a == a*b == 56088 assert b%a == 87 assert divmod(a, b) == (0, 123) assert divmod(b, a) == (3, 87) assert -a == -123 assert pow(a, 10) == 792594609605189126649 assert pow(a, 7, b) == 99 assert cmp(a, b) == -1 assert '7' in str(c) assert '0' not in str(c) assert a.sqrt() == 11 assert _g.lcm(a, b) == 18696 assert _g.fac(7) == 5040 assert _g.fib(17) == 1597 assert _g.divm(b, a, 20) == 12 assert _g.divm(4, 8, 20) == 3 assert _g.divm(4, 8, 20) == 3 assert _g.mpz(20) == 20 assert _g.mpz(8) == 8 assert _g.mpz(4) == 4 assert a.invert(100) == 87 def _test(chat=None): if chat: print "Unit tests for gmpy2 (threading)" print " on Python %s" % sys.version print "Testing gmpy2 {0}".format(_g.version()) print " Mutliple-precision library: {0}".format(_g.mp_version()) print " Floating-point library: {0}".format(_g.mpfr_version()) print " Complex library: {0}".format(_g.mpc_version()) print " Caching Values: (Number) {0}".format(_g.get_cache()[0]) print " Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1]) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print "Repeating tests, with caching disabled" _g.set_zcache(0) sav = sys.stdout class _Dummy: def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0) finally: sys.stdout = sav if chat: print print "Overall results for thr:" return doctest.master.summarize(chat) class DoOne(threading.Thread): def __init__(self, q): threading.Thread.__init__(self) self.q = q def run(self): while True: task = self.q.get() if task is None: break task() def _test_thr(Ntasks=5, Nthreads=1): q = Queue.Queue() funcs = (_tf, 1), (factorize, 4), (elemop, 2) for i in range(Ntasks): for f, n in funcs: for x in range(n): q.put(f) for i in range(Nthreads): q.put(None) thrs = [DoOne(q) for i in range(Nthreads)] for t in thrs: t.start() for t in thrs: t.join() if __name__=='__main__': _test(1) gmpy2-2.0.7/test2/gmpy_test_mpz.py0000666000000000000000000004522512351625226015610 0ustar rootroot# partial unit test for gmpy2 mpz functionality # relies on Tim Peters' "doctest.py" test-driver r''' >>> filter(lambda x: not x.startswith('_'), dir(_g)) ['Default', 'DivisionByZeroError', 'ExponentOutOfBoundsError', 'InexactResultError', 'InvalidOperationError', 'OverflowResultError', 'RangeError', 'RoundAwayZero', 'RoundDown', 'RoundToNearest', 'RoundToZero', 'RoundUp', 'UnderflowResultError', 'acos', 'acosh', 'add', 'agm', 'ai', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'bincoef', 'bit_clear', 'bit_flip', 'bit_length', 'bit_mask', 'bit_scan0', 'bit_scan1', 'bit_set', 'bit_test', 'c_div', 'c_div_2exp', 'c_divmod', 'c_divmod_2exp', 'c_mod', 'c_mod_2exp', 'cbrt', 'ceil', 'check_range', 'comb', 'const_catalan', 'const_euler', 'const_log2', 'const_pi', 'context', 'copy_sign', 'cos', 'cosh', 'cot', 'coth', 'csc', 'csch', 'degrees', 'denom', 'digamma', 'digits', 'div', 'div_2exp', 'divexact', 'divm', 'eint', 'erf', 'erfc', 'exp', 'exp10', 'exp2', 'expm1', 'f2q', 'f_div', 'f_div_2exp', 'f_divmod', 'f_divmod_2exp', 'f_mod', 'f_mod_2exp', 'fac', 'factorial', 'fib', 'fib2', 'floor', 'fma', 'fmod', 'fms', 'frac', 'frexp', 'from_binary', 'fsum', 'gamma', 'gcd', 'gcdext', 'get_cache', 'get_context', 'get_emax_max', 'get_emin_min', 'get_exp', 'get_max_precision', 'hamdist', 'hypot', 'ieee', 'inf', 'invert', 'iroot', 'iroot_rem', 'is_bpsw_prp', 'is_euler_prp', 'is_even', 'is_extra_strong_lucas_prp', 'is_fermat_prp', 'is_fibonacci_prp', 'is_finite', 'is_inf', 'is_infinite', 'is_integer', 'is_lessgreater', 'is_lucas_prp', 'is_nan', 'is_number', 'is_odd', 'is_power', 'is_prime', 'is_regular', 'is_selfridge_prp', 'is_signed', 'is_square', 'is_strong_bpsw_prp', 'is_strong_lucas_prp', 'is_strong_prp', 'is_strong_selfridge_prp', 'is_unordered', 'is_zero', 'isqrt', 'isqrt_rem', 'j0', 'j1', 'jacobi', 'jn', 'kronecker', 'lcm', 'legendre', 'lgamma', 'li2', 'license', 'lngamma', 'local_context', 'log', 'log10', 'log1p', 'log2', 'lucas', 'lucas2', 'lucasu', 'lucasu_mod', 'lucasv', 'lucasv_mod', 'max2', 'maxnum', 'min2', 'minnum', 'modf', 'mp_limbsize', 'mp_version', 'mpc', 'mpc_random', 'mpc_version', 'mpfr', 'mpfr_from_old_binary', 'mpfr_grandom', 'mpfr_random', 'mpfr_version', 'mpq', 'mpq_from_old_binary', 'mpz', 'mpz_from_old_binary', 'mpz_random', 'mpz_rrandomb', 'mpz_urandomb', 'mul', 'mul_2exp', 'nan', 'next_above', 'next_below', 'next_prime', 'next_toward', 'norm', 'num_digits', 'numer', 'pack', 'phase', 'polar', 'popcount', 'powmod', 'proj', 'qdiv', 'radians', 'random_state', 'rec_sqrt', 'rect', 'reldiff', 'remainder', 'remove', 'remquo', 'rint', 'rint_ceil', 'rint_floor', 'rint_round', 'rint_trunc', 'root', 'round2', 'round_away', 'sec', 'sech', 'set_cache', 'set_context', 'set_exp', 'set_sign', 'sign', 'sin', 'sin_cos', 'sinh', 'sinh_cosh', 'sqrt', 'square', 'sub', 't_div', 't_div_2exp', 't_divmod', 't_divmod_2exp', 't_mod', 't_mod_2exp', 'tan', 'tanh', 'to_binary', 'trunc', 'unpack', 'version', 'xbit_mask', 'xmpz', 'y0', 'y1', 'yn', 'zero', 'zeta'] >>> filter(lambda x: not x.startswith('__'), dir(a)) ['bit_clear', 'bit_flip', 'bit_length', 'bit_scan0', 'bit_scan1', 'bit_set', 'bit_test', 'denominator', 'digits', 'num_digits', 'numerator'] >>> ''' import gmpy2 as _g, doctest, sys, operator, gc __test__={} a=_g.mpz(123) b=_g.mpz(456) # Disable tests since they are not reliable with Python 3.1 but left behind # in case it is needed in the future. if sys.platform in ('__DISABLE__linux2', '__DISABLE__darwin'): def _memsize(): """ this function tries to return a measurement of how much memory this process is consuming (if it doesn't manage to, it returns 0). """ import os try: x = int(os.popen('ps -p %d -o vsz|tail -1' % os.getpid()).read()) except: x = 0 return x else: def _memsize(): return 0 def factorize(x): r''' >>> factorize(a) [3, 41] >>> factorize(b) [2, 2, 2, 3, 19] >>> ''' import gmpy2 as _g savex=x prime=2 x=_g.mpz(x) factors=[] while x>=prime: newx,mult=_g.remove(x,prime) if mult: factors.extend([int(prime)]*mult) x=newx prime=_g.next_prime(prime) for factor in factors: assert _g.is_prime(factor) from operator import mul assert reduce(mul, factors)==savex return factors if sys.version[:3] >= '2.5': __test__['index']=\ r''' >>> range(333)[a] 123 >>> range(333)[b] Traceback (innermost last): ... IndexError: list index out of range >>> ix = operator.index >>> ix(_g.mpz(sys.maxint)) == sys.maxint True >>> type(ix(_g.mpz(sys.maxint))) is int True >>> ix(_g.mpz(sys.maxint+1)) == sys.maxint+1 True >>> type(ix(_g.mpz(sys.maxint+1))) is long True ''' __test__['elemop']=\ r''' >>> a+b mpz(579) >>> a-b mpz(-333) >>> a*b mpz(56088) >>> a/b mpz(0) >>> a%b mpz(123) >>> 0%b mpz(0) >>> b+a mpz(579) >>> b-a mpz(333) >>> b*a mpz(56088) >>> b%a mpz(87) >>> divmod(a,b) (mpz(0), mpz(123)) >>> divmod(b,a) (mpz(3), mpz(87)) >>> divmod(0,b) (mpz(0), mpz(0)) >>> -a mpz(-123) >>> a+1 mpz(124) >>> a+(-1) mpz(122) >>> (-1)+a mpz(122) >>> 1+a mpz(124) >>> a-1 mpz(122) >>> a-(-1) mpz(124) >>> 1-a mpz(-122) >>> (-1)-a mpz(-124) >>> a+True mpz(124) >>> a+False mpz(123) >>> a*False mpz(0) >>> a//True mpz(123) >>> abs(-a)==a 1 >>> pow(a,10) mpz(792594609605189126649L) >>> pow(a,7,b) mpz(99) >>> _g.sign(b-a) 1 >>> _g.sign(b-b) 0 >>> _g.sign(a-b) -1 >>> _g.sign(a) 1 >>> _g.sign(-a) -1 >>> z=b-b; _g.sign(z) 0 >>> _g.mpz(4)**(0.5) mpfr('2.0') >>> import pickle >>> pickle.loads(pickle.dumps(_g.mpz(12346789))) mpz(12346789) >>> s='12345678901234567890123456789' >>> int(s) == _g.mpz(s) True >>> _g.mpz(s) == int(s) True >>> del s >>> _g.is_even(a) False >>> _g.is_odd(a) True >>> _g.is_even(b) True >>> _g.is_odd(b) False >>> _g.is_even(2) True ''' from gmpy_truediv import truediv __test__['newdiv']=\ r''' >>> a/b mpz(0) >>> a//b mpz(0) >>> truediv(a,b) mpfr('0.26973684210526316') >>> b/a mpz(3) >>> b//a mpz(3) >>> truediv(b,a) mpfr('3.7073170731707319') >>> ''' __test__['divexact']=\ r''' >>> a=_g.mpz('1234567912345678912345679') >>> b=_g.mpz('789789789789789789789789') >>> c=a*b >>> _g.divexact(c,a) mpz(789789789789789789789789L) >>> ''' __test__['divmod']=\ r''' >>> _g.c_divmod(17,5) (mpz(4), mpz(-3)) >>> _g.c_divmod(-17,5) (mpz(-3), mpz(-2)) >>> _g.c_divmod(17,-5) (mpz(-3), mpz(2)) >>> _g.c_divmod(-17,-5) (mpz(4), mpz(3)) >>> _g.f_divmod(17,5) (mpz(3), mpz(2)) >>> _g.f_divmod(-17,5) (mpz(-4), mpz(3)) >>> _g.f_divmod(17,-5) (mpz(-4), mpz(-3)) >>> _g.f_divmod(-17,-5) (mpz(3), mpz(-2)) >>> _g.t_divmod(17,5) (mpz(3), mpz(2)) >>> _g.t_divmod(-17,5) (mpz(-3), mpz(-2)) >>> _g.t_divmod(17,-5) (mpz(-3), mpz(2)) >>> _g.t_divmod(-17,-5) (mpz(3), mpz(-2)) ''' __test__['cmpr']=\ r''' >>> c=_g.mpz(a) >>> c is a 1 >>> c==a 1 >>> c>a 0 >>> c>> cmp(a,c) 0 >>> cmp(a,b) -1 >>> a>b 0 >>> a>> not _g.mpz(0) 1 >>> not a 0 >>> _g.mpz(1) == None False >>> _g.mpz(1) == '1' False >>> _g.mpz(1) == 'abc' False >>> [_g.mpz(23), None].count(None) 1 >>> _g.mpz(3.14) mpz(3) >>> _g.mpz(_g.mpq(17,3)) mpz(5) >>> _g.mpz(23L) mpz(23) >>> _g.mpz(-23L) mpz(-23) >>> x=1000L*1000*1000*1000*1000*1000*1000 >>> _g.mpz(x) mpz(1000000000000000000000L) >>> try: print cmp(_g.mpz(1), _g.mpz(-1)) ... except: print 'ouch!' 1 ''' __test__['special'] = \ r''' >>> _g.context().trap_divzero == False True >>> a == float('Inf') False >>> a != float('Inf') True >>> a > float('Inf') False >>> a >= float('Inf') False >>> a < float('Inf') True >>> a <= float('Inf') True >>> a == float('-Inf') False >>> a != float('-Inf') True >>> a > float('-Inf') True >>> a >= float('-Inf') True >>> a < float('-Inf') False >>> a <= float('-Inf') False >>> a == float('nan') False >>> a != float('nan') True >>> a > float('nan') False >>> a >= float('nan') False >>> a < float('nan') False >>> a <= float('nan') False >>> float('Inf') == a False >>> float('Inf') != a True >>> float('Inf') > a True >>> float('Inf') >= a True >>> float('Inf') < a False >>> float('Inf') <= a False >>> float('-Inf') == a False >>> float('-Inf') != a True >>> float('-Inf') > a False >>> float('-Inf') >= a False >>> float('-Inf') < a True >>> float('-Inf') <= a True >>> float('nan') == a False >>> float('nan') != a True >>> float('nan') > a False >>> float('nan') >= a False >>> float('nan') < a False >>> float('nan') <= a False >>> a + float('Inf') mpfr('inf') >>> float('Inf') + a mpfr('inf') >>> a + float('-Inf') mpfr('-inf') >>> float('-Inf') + a mpfr('-inf') >>> a + float('nan') mpfr('nan') >>> float('nan') + a mpfr('nan') >>> a - float('Inf') mpfr('-inf') >>> float('Inf') - a mpfr('inf') >>> a - float('-Inf') mpfr('inf') >>> float('-Inf') - a mpfr('-inf') >>> a - float('nan') mpfr('nan') >>> float('nan') - a mpfr('nan') >>> a * float('Inf') mpfr('inf') >>> float('Inf') * a mpfr('inf') >>> a * float('-Inf') mpfr('-inf') >>> float('-Inf') * a mpfr('-inf') >>> -a * float('Inf') mpfr('-inf') >>> float('Inf') * -a mpfr('-inf') >>> -a * float('-Inf') mpfr('inf') >>> float('-Inf') * -a mpfr('inf') >>> a * float('nan') mpfr('nan') >>> float('nan') * a mpfr('nan') >>> _g.mpz(0) * float('Inf') mpfr('nan') >>> _g.mpz(0) * float('-Inf') mpfr('nan') >>> float('Inf') * _g.mpz(0) mpfr('nan') >>> float('-Inf') * _g.mpz(0) mpfr('nan') >>> a / float('Inf') mpfr('0.0') >>> -a / float('Inf') mpfr('-0.0') >>> float('Inf') / a mpfr('inf') >>> float('Inf') / -a mpfr('-inf') >>> a / float('-Inf') mpfr('-0.0') >>> -a / float('-Inf') mpfr('0.0') >>> float('-Inf') / a mpfr('-inf') >>> float('-Inf') / -a mpfr('inf') >>> a / float('nan') mpfr('nan') >>> float('nan') / a mpfr('nan') >>> float('nan') / _g.mpz(0) mpfr('nan') >>> float('nan') / _g.mpz(0) mpfr('nan') >>> divmod(a, float('Inf')) (mpfr('0.0'), mpfr('123.0')) >>> divmod(a, float('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, float('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, float('-Inf')) (mpfr('0.0'), mpfr('-123.0')) >>> divmod(a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpz(0), float('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(_g.mpz(0), float('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(_g.mpz(0), float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpfr('Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpfr('-Inf'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(_g.mpfr('nan'), _g.mpz(0)) (mpfr('nan'), mpfr('nan')) ''' __test__['bitops']=\ r''' >>> ~a mpz(-124) >>> a&b mpz(72) >>> a|b mpz(507) >>> a^b mpz(435) >>> a<<1 mpz(246) >>> a>>1 mpz(61) >>> a<<-1 Traceback (innermost last): ... ValueError: negative shift count >>> a>>-2 Traceback (innermost last): ... ValueError: negative shift count >>> a<<0 mpz(123) >>> a>>0 mpz(123) >>> _g.popcount(a) 6 >>> _g.popcount(b) 4 >>> _g.popcount(-7) -1 >>> _g.popcount(0) 0 >>> _g.hamdist(a,b) 6 >>> _g.hamdist(3) Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments >>> _g.hamdist() Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments >>> _g.f_mod_2exp(a,5) mpz(27) >>> _g.f_mod_2exp(b,5) mpz(8) >>> _g.f_mod_2exp(b,5)==(b%32) 1 >>> _g.f_mod_2exp(a,5)==(a%32) 1 >>> a.bit_set(20) mpz(1048699) >>> a.bit_clear(0) mpz(122) >>> for i in range(8): ... print a.bit_test(i), ... if i==7: print ... True True False True True True True False >>> for i in range(10): ... print b.bit_test(i), ... if i==9: print ... False False False True False False True True True False >>> [a.bit_scan0(j) for j in range(33)] [2, 2, 2, 7, 7, 7, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> [a.bit_scan1(j) for j in range(10)] [0, 1, 3, 3, 4, 5, 6, None, None, None] >>> n=_g.mpz(-(7+6*16+5*256+7*4092)) >>> [n.bit_scan0(j) for j in range(18)] [1, 1, 3, 3, 6, 6, 6, 8, 8, 10, 10, 12, 12, 13, 14, None, None, None] >>> [n.bit_scan1(j) for j in range(33)] [0, 2, 2, 4, 4, 5, 7, 7, 9, 9, 11, 11, 15, 15, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> _g.mpz(0).bit_length() 0 >>> _g.mpz(12345).bit_length() 14 ''' __test__['format']=\ r''' >>> str(a) '123' >>> repr(a) 'mpz(123)' >>> hex(a) '0x7b' >>> oct(a) '0173' >>> _g.mpz('123') mpz(123) >>> _g.mpz('1001001011',2) mpz(587) >>> _g.mpz('1001001011',2).digits(2) '1001001011' >>> for i in range(2,63): ... print a.digits(i), ... if i%6==0: print ... 1111011 11120 1323 443 323 234 173 146 123 102 a3 96 8b 83 7b 74 6f 69 63 5i 5d 58 53 4n 4j 4f 4b 47 43 3u 3r 3o 3l 3i 3f 3C 39 36 33 30 2d 2b 2Z 2X 2V 2T 2R 2P 2N 2L 2J 2H 2F 2D 2B 29 27 25 23 21 1z >>> print a.digits(63) Traceback (innermost last): ... ValueError: base must be in the interval 2 ... 62 >>> _g.mpz('43') mpz(43) >>> _g.mpz('043') mpz(43) >>> _g.mpz('43',0) mpz(43) >>> _g.mpz('0o43') mpz(35) >>> _g.mpz('0x43') mpz(67) >>> _g.mpz('0x43',10) Traceback (innermost last): File "", line 1, in ? _g.mpz('0x43') ValueError: invalid digits >>> ''' __test__['binio']=\ r''' >>> a== _g.from_binary(_g.to_binary(a)) True >>> -a== _g.from_binary(_g.to_binary(-a)) True >>> z=_g.mpz(573406620562849222387053L) >>> divmod(z,a) (mpz(4661842443600400182008L), mpz(69)) >>> for i in range(2,37): ... print i,z.num_digits(i), ... if i%6==0: print ... 2 79 3 50 4 40 5 35 6 31 7 29 8 27 9 25 10 24 11 23 12 23 13 22 14 21 15 21 16 20 17 20 18 19 19 19 20 19 21 18 22 18 23 18 24 18 25 18 26 17 27 17 28 17 29 17 30 17 31 16 32 16 33 16 34 16 35 16 36 16 >>> _g.num_digits(23) 2 >>> _g.num_digits(23,2) 5 >>> _g.num_digits(23,99) Traceback (most recent call last): File "", line 1, in ? ValueError: base must be in the interval 2 ... 62 >>> hash(a) 123 >>> hash(b) 456 >>> hash(z) == hash(long(z)) True >>> long(_g.mpz(-3)) -3L >>> ''' __test__['number']=\ r''' >>> _g.iroot_rem(a,2) (mpz(11), mpz(2)) >>> _g.iroot_rem(a,3) (mpz(4), mpz(59)) >>> _g.iroot_rem(a*a) Traceback (most recent call last): File "", line 1, in TypeError: iroot_rem() requires 'mpz','int' arguments >>> _g.iroot_rem(a*a,2) (mpz(123), mpz(0)) >>> print _g.isqrt(a), _g.isqrt(b) 11 21 >>> print _g.isqrt_rem(a), _g.isqrt_rem(b) (mpz(11), mpz(2)) (mpz(21), mpz(15)) >>> for i in range(5): ... print _g.iroot(a,i+1),_g.iroot(b,i+1) ... (mpz(123), True) (mpz(456), True) (mpz(11), False) (mpz(21), False) (mpz(4), False) (mpz(7), False) (mpz(3), False) (mpz(4), False) (mpz(2), False) (mpz(3), False) >>> _g.is_square(a) 0 >>> _g.is_power(a) 0 >>> _g.is_square(99*99) 1 >>> _g.is_square(99*99*99) 0 >>> _g.is_square(0) 1 >>> _g.is_square(-1) 0 >>> _g.is_power(99*99*99) 1 >>> _g.gcd(a,b) mpz(3) >>> temp=_g.gcdext(a,b) >>> temp[0]==a*temp[1]+b*temp[2] True >>> _g.lcm(a,b) mpz(18696) >>> _g.fac(7) mpz(5040) >>> _g.fib(17) mpz(1597) >>> for i in range(10): ... print _g.bincoef(10,i) ... 1 10 45 120 210 252 210 120 45 10 >>> _g.divm(b,a,20) mpz(12) >>> _g.divm(a,b,100) Traceback (innermost last): File "", line 1, in ? _g.divm(a,b,100) ZeroDivisionError: not invertible >>> _g.divm(6,12,14) mpz(4) >>> _g.divm(0,1,2) mpz(0) >>> # guard against regression of an ancient gmpy bug: divm w/non-coprime parms >>> _g.divm(4,8,20) mpz(3) >>> _g.divm(4,8,20) mpz(3) >>> _g.mpz(20) mpz(20) >>> _g.mpz(8) mpz(8) >>> _g.mpz(4) mpz(4) >>> # guard against regression of a memory leak in divm >>> __ = gc.collect() >>> _siz = 87654 >>> _siz = _memsize() >>> for x in xrange(45678): ... _xx=_g.divm(b,a,20) >>> del _xx >>> __ = gc.collect() >>> (_memsize()-_siz) <= 16 True >>> _g.invert(a,100) mpz(87) >>> _g.invert(b,100) Traceback (most recent call last): ... ZeroDivisionError: invert() no inverse exists >>> _g.invert(3) Traceback (innermost last): ... TypeError: invert() requires 'mpz','mpz' arguments >>> _g.comb(3,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: binomial coefficient with negative k >>> _g.isqrt(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt() of negative number >>> _g.isqrt_rem(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt_rem() of negative number >>> _g.remove(3,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: factor must be > 1 >>> _g.remove(3) Traceback (innermost last): ... TypeError: remove() requires 'mpz','mpz' arguments >>> _g.is_prime(3,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: repetition count for is_prime() must be positive >>> _g.jacobi(10,3) 1 >>> _g.jacobi(10,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: y must be odd and >0 >>> _g.jacobi(3) Traceback (innermost last): ... TypeError: jacobi() requires 'mpz','mpz' arguments >>> _g.legendre(10,3) 1 >>> _g.legendre(10,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: y must be odd and >0 >>> _g.legendre(3) Traceback (innermost last): ... TypeError: legendre() requires 'mpz','mpz' arguments >>> _g.kronecker(10,3) 1 >>> _g.kronecker(10,-3) 1 >>> _g.kronecker(3) Traceback (innermost last): ... TypeError: kronecker() requires 'mpz','mpz' arguments >>> a=10L**20 >>> b=a+39 >>> _g.jacobi(a,b) 1 >>> _g.legendre(a,b) 1 >>> _g.kronecker(a,b) 1 ''' def _test(chat=None): try: float('nan') except ValueError: if "special" in __test__: del(__test__["special"]) if chat: print "Unit tests for gmpy2 (mpz functionality)" print " on Python %s" % sys.version print "Testing gmpy2 {0}".format(_g.version()) print " Mutliple-precision library: {0}".format(_g.mp_version()) print " Floating-point library: {0}".format(_g.mpfr_version()) print " Complex library: {0}".format(_g.mpc_version()) print " Caching Values: (Number) {0}".format(_g.get_cache()[0]) print " Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1]) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) if chat: print "Repeating tests, with caching disabled" _g.set_cache(0,128) sav = sys.stdout class _Dummy: def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) finally: sys.stdout = sav if chat: print print "Overall results for mpz:" return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test2/gmpy_test_mpq.py0000666000000000000000000001233612351625226015574 0ustar rootroot# partial unit test for gmpy2 mpq functionality # relies on Tim Peters' "doctest.py" test-driver r''' >>> filter(lambda x: not x.startswith('__'), dir(a)) ['denominator', 'digits', 'numerator'] >>> ''' import gmpy2 as _g, doctest,sys __test__={} a=_g.mpq('123/456') b=_g.mpq('789/123') __test__['elemop']=\ r''' >>> a+b mpq(41657,6232) >>> a-b mpq(-38295,6232) >>> a*b mpq(263,152) >>> a/b mpq(1681,39976) >>> b+a mpq(41657,6232) >>> b-a mpq(38295,6232) >>> b*a mpq(263,152) >>> b/a mpq(39976,1681) >>> a+1 mpq(193,152) >>> 1+a mpq(193,152) >>> a-1 mpq(-111,152) >>> 1-a mpq(111,152) >>> a*1 mpq(41,152) >>> 1*a mpq(41,152) >>> a/1 mpq(41,152) >>> 1/a mpq(152,41) >>> -a mpq(-41,152) >>> abs(-a) mpq(41,152) >>> _g.sign(b-a) 1 >>> _g.sign(b-b) 0 >>> _g.sign(a-b) -1 >>> _g.sign(a) 1 >>> _g.sign(-a) -1 >>> z=b-b; _g.sign(z) 0 >>> _g.numer(a) == a.numerator True >>> _g.denom(a) == a.denominator True >>> an=_g.numer(a); ad=_g.denom(a); >>> an==0 or 1==a*_g.mpq(ad,an) 1 >>> bn=_g.numer(b); bd=_g.denom(b); >>> bn==0 or 1==b*_g.mpq(bd,bn) 1 >>> zn=_g.numer(z); zd=_g.denom(z); >>> zn==0 or 1==z*_g.mpq(zd,zn) 1 >>> (a+b) == _g.mpq(an*bd+ad*bn,ad*bd) 1 >>> (a+z) == _g.mpq(an*zd+ad*zn,ad*zd) 1 >>> (a+a) == _g.mpq(an*ad+ad*an,ad*ad) 1 >>> import pickle >>> pickle.loads(pickle.dumps(_g.mpq(1234,6789))) mpq(1234,6789) >>> ''' from gmpy_truediv import truediv __test__['newdiv']=\ r''' >>> a/b mpq(1681,39976) >>> a//b mpz(0) >>> truediv(a,b) mpq(1681,39976) >>> b/a mpq(39976,1681) >>> b//a mpz(23) >>> truediv(b,a) mpq(39976,1681) >>> ''' __test__['cmpr']=\ r''' >>> c=_g.mpq(a) >>> c is a 1 >>> c==a 1 >>> c>a 0 >>> c>> cmp(a,c) 0 >>> cmp(a,b) -1 >>> a>b 0 >>> a>> not _g.mpq(0) 1 >>> not a 0 >>> a>1 0 >>> a>1.0 0 >>> a<1 1 >>> a<1.0 1 >>> a==1 0 >>> a==1.0 0 >>> cmp(a,1) -1 >>> cmp(1.0,a) 1 >>> long(1/a) 3L >>> long(-1/a) -3L >>> int(1/a) 3 >>> int(-1/a) -3 >>> ''' __test__['format']=\ r''' >>> str(a) '41/152' >>> repr(a) 'mpq(41,152)' >>> a==eval(repr(a),_g.__dict__) 1 >>> str(-a) '-41/152' >>> repr(-a) 'mpq(-41,152)' >>> (-a)==eval(repr(-a),_g.__dict__) 1 >>> for i in range(1,7): ... for j in range(3,10): ... if _g.mpq(i,j) != _g.mpq("%d/%d"%(i,j)): ... print 'er1:',i,j; break ... aa=_g.mpq(i,j); ai=_g.numer(aa); aj=_g.denom(aa) ... if aj!=1 and str(aa) != ("%d/%d"%(ai,aj)): ... print 'er2:',i,j,str(aa),("%d/%d"%(ai,aj)); break ... if aj==1 and str(aa) != ("%d"%ai): ... print 'er3:',i,j,str(aa),"%d"%ai; break ... if aj!=1 and repr(aa) != ("mpq(%d,%d)"%(ai,aj)): ... print 'er4:',i,j,repr(aa),("mpq(%d,%d)"%(ai,aj)); break ... if aj==1 and repr(aa) != ("mpq(%d,%d)"%(ai,aj)): ... print 'er5:',i,j,repr(aa),"mpq(%d,%d)"%(ai,aj); break >>> fmo='_g.mpq('+hex(a.numerator)+','+hex(a.denominator)+')' >>> fmo '_g.mpq(0x29,0x98)' >>> eval(fmo)==a 1 >>> fmo='_g.mpq("'+_g.numer(a).digits(30)+'/'+_g.denom(a).digits(30)+'",30)' >>> fmo '_g.mpq("1b/52",30)' >>> eval(fmo)==a 1 >>> _g.digits(a,30) '1b/52' >>> a.digits(30) '1b/52' >>> _g.mpq(1000L*1000*1000*1000*1000*1000*1000,23) mpq(1000000000000000000000L,23) >>> _g.mpq(23,1000L*1000*1000*1000*1000*1000*1000) mpq(23,1000000000000000000000L) >>> _g.mpq(23L**15L,1000L**7L) mpq(266635235464391245607L,1000000000000000000000L) >>> x=_g.mpq('234/567') >>> del x >>> _g.mpq('7788') mpq(7788,1) >>> _g.mpq('12.34') mpq(617,50) ''' __test__['binio']=\ r''' >>> a == _g.from_binary(_g.to_binary(a)) True >>> -a == _g.from_binary(_g.to_binary(-a)) True ''' __test__['power']=\ r''' >>> _g.mpq(2,3)**3 mpq(8,27) >>> _g.mpq(8,27)**_g.mpq('2/3') mpfr('0.44444444444444448') >>> _g.mpq(2,3)**-3 mpq(27,8) >>> _g.mpq(8,27)**_g.mpq('-2/3') mpfr('2.25') >>> print float(_g.mpfr('0.2')**2) 0.04 >>> print float(_g.mpfr('0.2')**-2) 25.0 >>> _g.mpq(3)**3 == _g.mpz(3)**3 1 >>> (a**-7) == 1/(a**7) 1 >>> (b**5) == 1/(b**-5) 1 >>> ''' __test__['qdiv']=\ r''' >>> _g.qdiv(12,2) mpz(6) >>> _g.qdiv(12,5) mpq(12,5) >>> a is _g.qdiv(a) 1 >>> a is _g.qdiv(a,1) 1 >>> a is _g.qdiv(a,2) 0 >>> x=_g.numer(a) >>> x is _g.qdiv(x) 1 >>> x is _g.qdiv(x,1) 1 >>> x is _g.qdiv(x,2) 0 >>> y=_g.mpq(4,1) >>> y is _g.qdiv(y) 0 >>> y == _g.qdiv(y) 1 >>> ''' def _test(chat=None): if chat: print "Unit tests for gmpy2 (mpq functionality)" print " on Python %s" % sys.version print "Testing gmpy2 {0}".format(_g.version()) print " Mutliple-precision library: {0}".format(_g.mp_version()) print " Floating-point library: {0}".format(_g.mpfr_version()) print " Complex library: {0}".format(_g.mpc_version()) print " Caching Values: (Number) {0}".format(_g.get_cache()[0]) print " Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1]) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print "Repeating tests, with caching disabled" _g.set_cache(0,128) sav = sys.stdout class _Dummy: def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) finally: sys.stdout = sav if chat: print print "Overall results for mpq:" return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test2/gmpy_test_mpf.py0000666000000000000000000001763312351625226015566 0ustar rootroot# partial unit test for gmpy2 mpfr functionality # relies on Tim Peters' "doctest.py" test-driver r''' >>> filter(lambda x: not x.startswith('__'), dir(a)) ['as_integer_ratio', 'as_mantissa_exp', 'as_simple_fraction', 'conjugate', 'digits', 'imag', 'is_integer', 'precision', 'rc', 'real'] >>> ''' import sys import gmpy2 as _g, doctest, sys __test__={} a=_g.mpfr('123.456') b=_g.mpfr('789.123') __test__['functions']=\ r''' >>> _g.log(2) mpfr('0.69314718055994529') >>> _g.log(10) mpfr('2.3025850929940459') >>> _g.log('a') Traceback (most recent call last): File "", line 1, in TypeError: log() argument type not supported >>> _g.log(float('nan')) mpfr('nan') >>> _g.log(float('inf')) mpfr('inf') >>> _g.log(float('-inf')) mpfr('nan') >>> _g.log(_g.mpfr('12.3456')) mpfr('2.5132997242892183') >>> _g.log(_g.mpfr('12.3456'),7) Traceback (most recent call last): File "", line 1, in TypeError: log() takes exactly one argument (2 given) ''' __test__['elemop']=\ r''' >>> str(a+b) '912.57900000000006' >>> str(a-b) '-665.66700000000003' >>> str(a*b) '97421.969088000013' >>> str(a/b) '0.15644709379906555' >>> str(b+a) '912.57900000000006' >>> str(b-a) '665.66700000000003' >>> str(b*a) '97421.969088000013' >>> str(b/a) '6.3919372083981338' >>> str(-a) '-123.456' >>> _g.mpfr(2,200) + 3 mpfr('5.0') >>> 3 + _g.mpfr(2,200) mpfr('5.0') >>> _g.mpfr(2,200) * 3 mpfr('6.0') >>> 3 * _g.mpfr(2,200) mpfr('6.0') >>> str(abs(-a)) '123.456' >>> _g.sign(b-a) 1 >>> _g.sign(b-b) 0 >>> _g.sign(a-b) -1 >>> _g.sign(a) 1 >>> _g.sign(-a) -1 >>> z=b-b; _g.sign(z) 0 >>> import math >>> math.ceil(a) 124.0 >>> str(a.__ceil__()) '124.0' >>> str(_g.ceil(a)) '124.0' >>> math.floor(a) 123.0 >>> str(a.__floor__()) '123.0' >>> str(_g.floor(a)) '123.0' >>> str(a.__trunc__()) '123.0' >>> str(_g.trunc(a)) '123.0' >>> x=-a >>> math.floor(x) -124.0 >>> str(x.__floor__()) '-124.0' >>> str(_g.floor(x)) '-124.0' >>> str(x.__ceil__()) '-123.0' >>> math.ceil(x) -123.0 >>> str(_g.ceil(x)) '-123.0' >>> str(x.__trunc__()) '-123.0' >>> str(_g.trunc(x)) '-123.0' >>> _g.ceil(12.3)==math.ceil(12.3) 1 >>> _g.floor(12.3)==math.floor(12.3) 1 >>> _g.ceil(-12.3)==math.ceil(-12.3) 1 >>> _g.floor(-12.3)==math.floor(-12.3) 1 >>> _g.reldiff(a**2,float(a)**2) < 1.03 * (2.0**-(a.precision-1)) 1 >>> _g.reldiff(a**2,a*a) < (2.0**-(a.precision-1)) 1 >>> _g.reldiff(b**2,float(b)**2) < 1.03 * (2.0**-(b.precision-1)) 1 >>> _g.reldiff(b**2,b*b) < (2.0**-(b.precision-1)) 1 >>> _g.reldiff(3.4) Traceback (innermost last): File "", line 1, in ? _g.reldiff(3.4) TypeError: reldiff() requires 'mpfr','mpfr' arguments >>> _g.sqrt(a) mpfr('11.111075555498667') >>> _g.sqrt(-1.0) mpfr('nan') >>> save=_g.get_context().precision >>> _g.const_catalan() mpfr('0.91596559417721901') >>> _g.const_euler() mpfr('0.57721566490153287') >>> _g.const_log2() mpfr('0.69314718055994529') >>> _g.const_pi() mpfr('3.1415926535897931') >>> _g.get_context().precision = 100 >>> _g.const_catalan() mpfr('0.91596559417721901505460351493252',100) >>> _g.const_euler() mpfr('0.57721566490153286060651209008234',100) >>> _g.const_log2() mpfr('0.69314718055994530941723212145798',100) >>> _g.const_pi() mpfr('3.1415926535897932384626433832793',100) >>> _g.get_context().precision = save >>> del(save) >>> import pickle >>> flt = _g.mpfr(1234.6789) >>> flt == pickle.loads(pickle.dumps(flt)) True >>> flt = _g.mpfr('1.1') >>> flt == pickle.loads(pickle.dumps(flt)) True ''' from gmpy_truediv import truediv __test__['newdiv']=\ r''' >>> >>> a/b mpfr('0.15644709379906555') >>> a//b mpfr('0.0') >>> truediv(a,b) mpfr('0.15644709379906555') >>> b/a mpfr('6.3919372083981338') >>> b//a mpfr('6.0') >>> truediv(b,a) mpfr('6.3919372083981338') >>> ''' __test__['cmpr']=\ r''' >>> c=_g.mpfr(a) >>> c is a 1 >>> c==a 1 >>> c>a 0 >>> c>> cmp(a,c) 0 >>> cmp(a,b) -1 >>> a>b 0 >>> a>> not _g.mpfr(0) 1 >>> not a 0 >>> _g.f2q(a,0.1) mpz(123) >>> _g.f2q(a,0.01) mpz(123) >>> _g.f2q(a,0.001) mpq(247,2) >>> _g.f2q(a,0.0001) mpq(1358,11) >>> _g.f2q(a,0.00001) mpq(7037,57) >>> _g.f2q(a,0.000001) mpq(15432,125) >>> _g.f2q(a,0.0000001) mpq(15432,125) >>> _g.f2q(a) mpq(15432,125) >>> print _g.mpfr(_g.mpz(1234)) 1234.0 >>> x=1000*1000*1000*1000L >>> _g.mpfr(x) mpfr('1000000000000.0') >>> c=_g.mpfr(a) >>> a is c 1 >>> c=_g.mpfr(a,99) >>> a is c 0 >>> a==c 1 >>> _g.mpfr('1.1') == _g.mpfr('1.1') * _g.mpfr(1) True >>> _g.mpfr('1.1',64) == _g.mpfr('1.1',128) False >>> _g.mpfr('1.1',64) == _g.mpfr(_g.mpfr('1.1',128),64) True >>> a = _g.mpfr('.123', 64) >>> b = _g.mpfr('.123', 128) >>> c = _g.mpfr('.123', 128) * _g.mpfr(1, 128) >>> a == b False >>> a == c False >>> b == c False >>> a == _g.round2(b,64) True >>> _g.round2(_g.mpfr('ffffffffffffffffe8000000000000000', 256, 16),64).digits(16) ('10000000000000000', 34, 64) >>> _g.round2(_g.mpfr('fffffffffffffffff8000000000000000', 256, 16),64).digits(16) ('10000000000000000', 34, 64) >>> _g.round2(b,64) mpfr('0.122999999999999999999',64) ''' __test__['format']=\ r''' >>> str(a) '123.456' >>> repr(a) "mpfr('123.456')" >>> a.digits(10,0) ('12345600000000000', 3, 53) >>> a.digits(10,1) Traceback (most recent call last): ... ValueError: digits must be 0 or >= 2 >>> a.digits(10,2) ('12', 3, 53) >>> a.digits(10,3) ('123', 3, 53) >>> a.digits(10,4) ('1235', 3, 53) >>> a.digits(10,5) ('12346', 3, 53) >>> a.digits(10,6) ('123456', 3, 53) >>> a.digits(10,7) ('1234560', 3, 53) >>> a.digits(10,8) ('12345600', 3, 53) >>> _g.mpfr(3.4) mpfr('3.3999999999999999') >>> print _g.mpfr(3.4) 3.3999999999999999 >>> a.digits(1) Traceback (most recent call last): File "", line 1, in ? ValueError: base must be in the interval 2 ... 62 >>> a.digits(2,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: digits must be 0 or >= 2 >>> a.digits(10,0,0,-1,2) Traceback (most recent call last): ... TypeError: function takes at most 2 arguments (5 given) >>> saveprec=a.precision >>> newa = _g.round2(a,33) >>> newa mpfr('123.456',33) >>> newa = _g.round2(newa,saveprec) >>> newa.precision==saveprec 1 >>> del(newa) >>> _g.digits(_g.mpfr(23.45)) ('23449999999999999', 2, 53) >>> ''' __test__['binio']=\ r''' >>> _g.from_binary('pep') Traceback (most recent call last): File "", line 1, in ? TypeError: from_binary() argument type not supported >>> a == _g.from_binary(_g.to_binary(a)) True >>> -a == _g.from_binary(_g.to_binary(-a)) True >>> 1/a == _g.from_binary(_g.to_binary(1/a)) True >>> _g.to_binary(_g.mpfr(0)) '\x04\x00\x00\x005\x00\x00\x00' >>> 0 == _g.from_binary(_g.to_binary(_g.mpfr(0))) True >>> 0.5 == _g.from_binary(_g.to_binary(_g.mpfr(0.5))) True >>> -0.5 == _g.from_binary(_g.to_binary(_g.mpfr(-0.5))) True >>> -2.0 == _g.from_binary(_g.to_binary(_g.mpfr(-2.0))) True >>> 2.0 == _g.from_binary(_g.to_binary(_g.mpfr(2.0))) True >>> hash(_g.mpfr(23.0))==hash(23) True >>> long(a) 123L >>> long(-a) -123L >>> int(a) 123 >>> int(-a) -123 >>> ''' def _test(chat=None): if chat: print "Unit tests for gmpy2 (mpfr functionality)" print " on Python %s" % sys.version print "Testing gmpy2 {0}".format(_g.version()) print " Mutliple-precision library: {0}".format(_g.mp_version()) print " Floating-point library: {0}".format(_g.mpfr_version()) print " Complex library: {0}".format(_g.mpc_version()) print " Caching Values: (Number) {0}".format(_g.get_cache()[0]) print " Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1]) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0) if chat: print "Repeating tests, with caching disabled" _g.set_cache(0,128) sav = sys.stdout class _Dummy: def write(self,*whatever): pass try: sys.stdout = _Dummy() doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) finally: sys.stdout = sav if chat: print print "Overall results for mpfr:" return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test2/gmpy_test_dec.py0000666000000000000000000000363512351625226015534 0ustar rootroot# partial unit test for gmpy2/decimal interoperability # relies on Tim Peters' "doctest.py" test-driver r''' >>> filter(lambda x: not x.startswith('__'), dir(f)) ['as_integer_ratio', 'as_mantissa_exp', 'as_simple_fraction', 'conjugate', 'digits', 'imag', 'is_integer', 'precision', 'rc', 'real'] >>> ''' try: import decimal as _d except ImportError: _d = None import gmpy2 as _g, doctest, sys __test__={} f=_g.mpfr('123.456') q=_g.mpq('789123/1000') z=_g.mpz('234') if _d: d=_d.Decimal('12.34') __test__['elemop']=\ r''' >>> print _g.mpz(23) == _d.Decimal(23) True >>> print _g.mpz(d) 12 >>> print _g.mpq(d) 617/50 >>> print _g.mpfr(d) 12.34 >>> print f+d 135.79599999999999 >>> print d+f 135.79599999999999 >>> print q+d 801.46300000000008 >>> print d+q 801.46300000000008 >>> print z+d 246.34 >>> print d+z 246.34 >>> print _g.ceil(d) 13.0 >>> print _g.floor(d) 12.0 >>> print _g.trunc(d) 12.0 >>> _g.mpfr(d).precision 53 >>> ''' def _test(chat=None): python_version = sys.version_info[:3] if chat: print "Unit tests for gmpy2 (decimal interoperation)" print " on Python %s" % sys.version print "Testing gmpy2 {0}".format(_g.version()) print " Mutliple-precision library: {0}".format(_g.mp_version()) print " Floating-point library: {0}".format(_g.mpfr_version()) print " Complex library: {0}".format(_g.mpc_version()) print " Caching Values: (Number) {0}".format(_g.get_cache()[0]) print " Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1]) if not _d: if chat: print "Can't test, since can't import decimal" return 0, 0 thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) if chat: print print "Overall results for dec:" return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test2/gmpy_test_cvr.py0000666000000000000000000003226412564432250015572 0ustar rootroot# partial unit test for gmpy2 extra cover # relies on Tim Peters' "doctest.py" test-driver r''' >>> _g.version() '2.0.7' >>> int('gmpy2.c' in _g._cvsid()) 1 ''' import gmpy2 as _g, doctest, sys __test__={} __test__['misc_stuff']=\ r''' >>> print _g.mpfr(3.0) 3.0 >>> _g.mp_limbsize() in (32, 64) True >>> _g.mpz(u"123") mpz(123) >>> _g.mpq(u"12/37") mpq(12,37) >>> _g.mpfr(u"123") mpfr('123.0') >>> _g.next_prime(2357*7069-1) == 2357*7069 False ''' # If the next_prime() test fails, you have encountered a bug in MPIR. Please # see https://code.google.com/p/gmpy/issues/detail?id=76 for more details. try: x = float('inf') except ValueError: pass else: __test__['infinity'] = \ r''' >>> x = float('inf') >>> n = float('nan') >>> _g.mpfr(x) mpfr('inf') >>> _g.mpfr(-x) mpfr('-inf') >>> _g.mpq(x) Traceback (most recent call last): ... OverflowError: 'mpq' does not support Infinity >>> _g.mpq(-x) Traceback (most recent call last): ... OverflowError: 'mpq' does not support Infinity >>> _g.mpz(x) Traceback (most recent call last): ... OverflowError: 'mpz' does not support Infinity >>> _g.mpz(-x) Traceback (most recent call last): ... OverflowError: 'mpz' does not support Infinity >>> _g.mpfr(n) mpfr('nan') >>> _g.mpq(n) Traceback (most recent call last): ... ValueError: 'mpq' does not support NaN >>> _g.mpz(n) Traceback (most recent call last): ... ValueError: 'mpz' does not support NaN ''' __test__['user_errors']=\ r''' >>> _g.version(23) Traceback (most recent call last): ... TypeError: version() takes no arguments (1 given) >>> _g.mp_version(23) Traceback (most recent call last): ... TypeError: mp_version() takes no arguments (1 given) >>> _g.get_cache(23) Traceback (most recent call last): ... TypeError: get_cache() takes no arguments (1 given) >>> _g.set_cache() Traceback (most recent call last): ... TypeError: function takes exactly 2 arguments (0 given) >>> _g.set_cache(200) Traceback (most recent call last): ... TypeError: function takes exactly 2 arguments (1 given) >>> _g.set_cache(200,-23) Traceback (most recent call last): ... ValueError: object size must between 0 and 16384 >>> _g.set_cache(2000,256) Traceback (most recent call last): ... ValueError: cache size must between 0 and 1000 >>> _g.set_cache(-23,256) Traceback (most recent call last): ... ValueError: cache size must between 0 and 1000 >>> _g.set_cache(200,256000) Traceback (most recent call last): ... ValueError: object size must between 0 and 16384 >>> _g.context().precision = -1 Traceback (most recent call last): File "", line 1, in ? ValueError: invalid value for precision >>> _g.mpz('12'+chr(0)+'34') Traceback (most recent call last): File "", line 1, in ? ValueError: string contains NULL characters >>> _g.mpfr('12'+chr(0)+'34') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> _g.mpq('12'+chr(0)+'34') Traceback (most recent call last): File "", line 1, in ? ValueError: string contains NULL characters >>> _g.mpq_from_old_binary('bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid mpq binary (too short) >>> _g.mpq_from_old_binary('bologna') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid mpq binary (num len) >>> _g.mpq_from_old_binary('\001\000\000\000\003\002') mpq(3,2) >>> _g.mpq('ba/bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> print 'ba/bo' ba/bo >>> _g.mpq('1/bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> print '1/bo' 1/bo >>> _g.mpq('1/0') Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: zero denominator in 'mpq' >>> _g.mpfr([]) Traceback (most recent call last): File "", line 1, in ? TypeError: mpfr() requires numeric or string argument >>> _g.mpfr_from_old_binary('bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid mpf binary encoding (too short) >>> _g.mpfr('bo') Traceback (most recent call last): File "", line 1, in ? ValueError: invalid digits >>> int(_g.mpz(1000L*1000*1000*1000*1000*1000*1000)) 1000000000000000000000L >>> _g.bit_scan0(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: starting bit must be >= 0 >>> _g.bit_scan1(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: starting bit must be >= 0 >>> _g.bit_test(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: bit_index must be >= 0 >>> _g.bit_set(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: bit_index must be >= 0 >>> _g.mpz(23).bit_set(12,1,2,3) Traceback (most recent call last): ... TypeError: bit_set() takes exactly one argument (4 given) >>> _g.bit_set(12,1,2,3) Traceback (most recent call last): ... TypeError: bit_set() requires 'mpz','int' arguments >>> _g.iroot(12,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: n must be > 0 >>> _g.iroot(12,0) Traceback (most recent call last): File "", line 1, in ? ValueError: n must be > 0 >>> _g.iroot(-12,2) Traceback (most recent call last): File "", line 1, in ? ValueError: iroot() of negative number >>> _g.digits(3.14) ('31400000000000001', 1, 53) >>> _g.digits(3,'peep') Traceback (most recent call last): ... TypeError: digits() requires 'int' argument for base >>> _g.digits(3.14,'peep') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.digits(3,'peep') Traceback (most recent call last): File "", line 1, in ? TypeError: digits() requires 'int' argument for base >>> _g.mpz(3).digits('bu') Traceback (most recent call last): ... TypeError: digits() requires 'int' argument for base >>> _g.mpfr(3).digits('bu') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.qdiv(3,_g.mpq(1)) mpz(3) >>> _g.qdiv(3,_g.mpz(1)) mpz(3) >>> _g.qdiv(3,_g.mpfr(1)) mpz(3) >>> _g.qdiv(3,1.0) mpz(3) >>> _g.qdiv(3,1L) mpz(3) >>> _g.qdiv(3) mpz(3) >>> _g.qdiv(3,'bu') Traceback (most recent call last): File "", line 1, in ? TypeError: second argument cannot be converted to 'mpq' >>> _g.qdiv(3,4,5) Traceback (most recent call last): File "", line 1, in ? TypeError: function takes at most 2 arguments (3 given) >>> _g.qdiv('bu') Traceback (most recent call last): File "", line 1, in ? TypeError: first argument cannot be converted to 'mpq' >>> _g.qdiv(1.0,1) Traceback (most recent call last): File "", line 1, in ? TypeError: first argument cannot be converted to 'mpq' >>> _g.qdiv(1,0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: division or modulo by zero in qdiv >>> _g.f2q(-1.0) mpz(-1) >>> _g.mpz(1,2,3) Traceback (most recent call last): File "", line 1, in ? TypeError: function takes at most 2 arguments (3 given) >>> _g.mpz('bi','bo') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpz('bi',99) Traceback (most recent call last): File "", line 1, in ? ValueError: base for mpz() must be 0 or in the interval 2 ... 62 >>> _g.mpz(1,2) Traceback (most recent call last): File "", line 1, in ? TypeError: mpz() with non-string argument needs exactly 1 argument >>> _g.mpz(None) Traceback (most recent call last): File "", line 1, in ? TypeError: mpz() requires numeric or string argument >>> _g.mpq(1,2,3) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq() requires 0, 1 or 2 arguments >>> _g.mpq('bi','bo') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpq('bi',99) Traceback (most recent call last): File "", line 1, in ? ValueError: base for mpq() must be 0 or in the interval 2 ... 62 >>> _g.mpq(None) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq() requires numeric or string argument >>> _g.mpq(1,None) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq() requires numeric or string argument >>> _g.mpq(1,0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: zero denominator in 'mpq' >>> _g.mpfr() mpfr('0.0') >>> _g.mpfr(1,'bo') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpfr(1,-1) Traceback (most recent call last): File "", line 1, in ? ValueError: precision for mpfr() must be >= 0 >>> _g.mpfr('ba',0,'bu') Traceback (most recent call last): File "", line 1, in ? TypeError: an integer is required >>> _g.mpfr('ba',0,99) Traceback (most recent call last): File "", line 1, in ? ValueError: base for mpfr() must be 0 or in the interval 2 ... 62 >>> _g.mpfr(1,2,3) Traceback (most recent call last): File "", line 1, in ? TypeError: function takes at most 2 arguments (3 given) >>> +_g.mpz(1) mpz(1) >>> +_g.mpfr(1) mpfr('1.0') >>> +_g.mpq(1) mpq(1,1) >>> _g.mpz(2)**-2 Traceback (most recent call last): File "", line 1, in ? ValueError: pow() exponent cannot be negative >>> _g.mpz(2)**_g.mpz(1000000000000000L*1000000000000000L) Traceback (most recent call last): File "", line 1, in ? ValueError: pow() outrageous exponent >>> pow(_g.mpz(2),3,0) Traceback (most recent call last): File "", line 1, in ? ValueError: pow() 3rd argument cannot be 0 >>> pow(_g.mpz(2),3,-5) mpz(-2) >>> pow(_g.mpq(2),3,-5) Traceback (most recent call last): File "", line 1, in ? TypeError: mpq.pow() no modulo allowed >>> a=10000000000L**2 >>> _g.mpq(2)**a Traceback (most recent call last): File "", line 1, in ? ValueError: mpq.pow() outrageous exponent >>> _g.mpq(2)**_g.mpq(1,a) mpfr('1.0') >>> _g.mpq(2)**0 mpq(1,1) >>> _g.mpq(2)**-1 mpq(1,2) >>> _g.mpq(2)**_g.mpq(1,2) mpfr('1.4142135623730951') >>> _g.mpq(-2)**_g.mpq(1,2) mpfr('nan') >>> _g.mpq(0)**_g.mpq(1,2) mpfr('0.0') >>> _g.mpq(0)**-1 Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: mpq.pow() 0 base to negative exponent >>> _g.mpq(-1)**-1 mpq(-1,1) >>> _g.mpfr(9,100)**2 mpfr('81.0') >>> _g.mpfr(9,100)**0.5 mpfr('3.0') >>> _g.mpfr(9,100)**_g.mpfr(0.5) mpfr('3.0') >>> _g.mpfr(0)**2 mpfr('0.0') >>> pow(_g.mpfr(2),3,-5) Traceback (most recent call last): File "", line 1, in ? TypeError: pow() 3rd argument not allowed unless all arguments are integers >>> _g.mpz(1)+'bu' Traceback (most recent call last): File "", line 1, in ? TypeError: unsupported operand type(s) for +: 'mpz' and 'str' >>> _g.mpz(1)+_g.mpfr(1) mpfr('2.0') >>> _g.mpz(1)+_g.mpq(1) mpq(2,1) >>> _g.mpq(1)+'bu' Traceback (most recent call last): File "", line 1, in ? TypeError: unsupported operand type(s) for +: 'mpq' and 'str' >>> _g.mpfr(1)+'bu' Traceback (most recent call last): File "", line 1, in ? TypeError: unsupported operand type(s) for +: 'mpfr' and 'str' >>> _g.mpfr(1)+_g.mpq(2) mpfr('3.0') >>> divmod(_g.mpz(3),0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: division or modulo by zero >>> divmod(_g.mpz(0),3) (mpz(0), mpz(0)) >>> _g.divm(1,2,0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: not invertible >>> abs(_g.mpq(0)) mpq(0,1) >>> _g.mpz(0)**2 mpz(0) >>> _g.mpq(-2)**0 mpq(1,1) >>> _g.fac(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: fac() of negative number >>> _g.fib(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: Fibonacci of negative number >>> _g.comb(7,-3) Traceback (most recent call last): File "", line 1, in ? ValueError: binomial coefficient with negative k >>> _g.isqrt(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt() of negative number >>> _g.isqrt_rem(-1) Traceback (most recent call last): File "", line 1, in ? ValueError: isqrt_rem() of negative number >>> _g.jacobi(23, -34) Traceback (most recent call last): ... ValueError: y must be odd and >0 >>> _g.legendre(23, -34) Traceback (most recent call last): ... ValueError: y must be odd and >0 >>> # guard against conversion error on 64-bit systems >>> _g.mpz(2**32) != _g.mpz(0) True >>> # test hash properties on 64-bit systems >>> temp = 123456789012345678901234567890 >>> hash(temp) == hash(_g.mpz(temp)) True >>> del temp ''' def _test(chat=None): if chat: print "Unit tests for gmpy2 (extra cover)" print " on Python %s" % sys.version print "Testing gmpy2 {0}".format(_g.version()) print " Mutliple-precision library: {0}".format(_g.mp_version()) print " Floating-point library: {0}".format(_g.mpfr_version()) print " Complex library: {0}".format(_g.mpc_version()) print " Caching Values: (Number) {0}".format(_g.get_cache()[0]) print " Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1]) thismod = sys.modules.get(__name__) doctest.testmod(thismod, report=0, optionflags=doctest.IGNORE_EXCEPTION_DETAIL) if chat: print print "Overall results for cvr:" return doctest.master.summarize(chat) if __name__=='__main__': _test(1) gmpy2-2.0.7/test2/gmpy_test.py0000666000000000000000000000232212204747360014712 0ustar rootrootimport sys import doctest import gmpy2 def writeln(s): sys.stdout.write(s+'\n') if sys.version_info[0] == 3: writeln("Please use 'test3/gmpy_test.py' to test with Python 3.x.") sys.exit(0) if sys.argv[-1] == 'debug': gmpy.set_debug(1) import gmpy_test_cvr #~ import gmpy_test_rnd import gmpy_test_mpf import gmpy_test_mpq import gmpy_test_mpz import gmpy_test_dec test_modules = (gmpy_test_cvr, gmpy_test_mpf, gmpy_test_mpq, gmpy_test_mpz, gmpy_test_dec) _g = gmpy2 writeln("Unit tests for gmpy2") writeln(" on Python %s" % sys.version) writeln("Testing gmpy2 {0}".format(_g.version())) writeln(" Mutliple-precision library: {0}".format(_g.mp_version())) writeln(" Floating-point library: {0}".format(_g.mpfr_version())) writeln(" Complex library: {0}".format(_g.mpc_version())) writeln(" Caching Values: (Number) {0}".format(_g.get_cache()[0])) writeln(" Caching Values: (Size, limbs) {0}".format(_g.get_cache()[1])) pf, pt = 0, 0 for x in test_modules: testit = x._test() failures, tests = testit if tests == 0: continue writeln("%s %3d tests, %d failures" % (x.__name__, tests-pt, failures-pf)) pf, pt = failures, tests doctest.master.summarize(1) gmpy2-2.0.7/test/0000755000000000000000000000000012567136721012245 5ustar rootrootgmpy2-2.0.7/test/test_py32_hash.txt0000666000000000000000000000205012204747346015645 0ustar rootrootTest hash() behavior ==================== This test is only applicable for Python 3.2 and later. >>> import gmpy2 >>> from gmpy2 import mpz, mpq, mpfr >>> from decimal import Decimal >>> gmpy2.set_context(gmpy2.context()) >>> hash(mpfr('123.456')) == hash(float('123.456')) True >>> hash(mpfr('123.5')) == hash(float('123.5')) True >>> hash(mpfr('0')) == hash(float('0')) True >>> hash(mpfr('1')) == hash(float('1')) True >>> hash(mpfr('2')) == hash(float('2')) True >>> hash(mpfr('-1')) == hash(float('-1')) True >>> hash(mpfr('Inf')) == hash(float('Inf')) True >>> hash(mpfr('-Inf')) == hash(float('-Inf')) True >>> hash(mpfr('-0')) == hash(float('-0')) True >>> hash(mpfr('NaN')) == hash(float('NaN')) True >>> hash(mpfr('123.456')) == hash(Decimal('123.456')) False >>> hash(mpfr('123.5')) == hash(Decimal('123.5')) True >>> hash(mpq(123456,1000)) == hash(Decimal('123.456')) True >>> hash(mpz(123)) == hash(Decimal(123)) True gmpy2-2.0.7/test/test_pack.py0000666000000000000000000000133212204747346014576 0ustar rootrootfrom __future__ import print_function import gmpy2 def test_pack_unpack(repeat): """Test gmpy2.pack and gmpy2.unpack.""" r = gmpy2.random_state(42) for counter in range(repeat): for t in (10, 1000, 2000, 10000, 100000): v = gmpy2.mpz_rrandomb(r, t) for b in range(1, max(1001,t)): temp = gmpy2.unpack(v, b) u = gmpy2.pack(temp, b) assert u == v if __name__ == "__main__": import sys try: repeat = abs(int(sys.argv[1])) except: repeat = 1 print("Testing pack/unpack for a large number of values.") print("This test may take a few minutes.") test_pack_unpack(repeat) print("Test successful.") gmpy2-2.0.7/test/test_mpz_to_from_binary.txt0000666000000000000000000000064312204747346017752 0ustar rootrootTesting of gmpy2 mpz to_binary and from_binary ---------------------------------------------- >>> import gmpy2 >>> from gmpy2 import mpz,to_binary,from_binary Test ---- >>> x=mpz(1);x==from_binary(to_binary(x)) True >>> x=mpz(0);x==from_binary(to_binary(x)) True >>> x=mpz(-1);x==from_binary(to_binary(x)) True >>> x=mpz(123456789123456789);x==from_binary(to_binary(x)) True gmpy2-2.0.7/test/test_mpz_template.txt0000666000000000000000000002257212204747346016561 0ustar rootrootMPZ Functionality ================= This file is a template for creating tests of mpz related functionality. >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr >>> a = mpz(123) >>> b = mpz(456) Test elementary operations ========================== Test addition ------------- >>> a+1 mpz(124) >>> a+(-1) mpz(122) >>> (-1)+a mpz(122) >>> 1+a mpz(124) >>> a+b mpz(579) >>> b+a mpz(579) >>> a+'b' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for +: 'mpz' and 'str' >>> 'b'+a #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): File "", line 1, in TypeError: Can't convert 'mpz' object to str implicitly Test subtraction ---------------- >>> a-1 mpz(122) >>> a-(-1) mpz(124) >>> 1-a mpz(-122) >>> (-1)-a mpz(-124) >>> a-b mpz(-333) >>> b-a mpz(333) >>> a-'b' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'mpz' and 'str' >>> 'b'-a Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'str' and 'mpz' Test multiplication ------------------- >>> a*b mpz(56088) >>> b*a mpz(56088) >>> a*'b' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' >>> 'b'*a 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' Test division ------------- >>> a//b mpz(0) >>> a/b mpfr('0.26973684210526316') >>> b//a mpz(3) >>> b/a mpfr('3.7073170731707319') >>> a*b mpz(56088) >>> b*a mpz(56088) >>> a//b mpz(0) >>> b//a mpz(3) >>> a/b mpfr('0.26973684210526316') >>> b/a mpfr('3.7073170731707319') >>> a//0 Traceback (most recent call last): ... ZeroDivisionError: division or modulo by zero >>> a/0 Traceback (most recent call last): ... ZeroDivisionError: division or modulo by zero >>> a%b mpz(123) >>> b%a mpz(87) >>> divmod(a,b) (mpz(0), mpz(123)) >>> divmod(b,a) (mpz(3), mpz(87)) >>> divmod(a,0) Traceback (most recent call last): ... ZeroDivisionError: division or modulo by zero Test modulo ----------- >>> a+True mpz(124) >>> a+False mpz(123) >>> a*False mpz(0) >>> a//True mpz(123) >>> abs(-a)==a True >>> print(pow(a,10)) 792594609605189126649 >>> pow(a,7,b) mpz(99) >>> G.sign(b-a) 1 >>> G.sign(b-b) 0 >>> G.sign(a-b) -1 >>> G.sign(a) 1 >>> G.sign(-a) -1 >>> z=b-b; G.sign(z) 0 Test pickle ----------- >>> import pickle >>> pickle.loads(pickle.dumps(G.mpz(12346789))) mpz(12346789) >>> pickle.loads(pickle.dumps(G.mpz(-12346789))) mpz(-12346789) >>> pickle.loads(pickle.dumps(G.mpz(0))) mpz(0) Test mpz.__index__ ------------------ >>> range(333)[a] 123 >>> range(333)[b] #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (innermost last): ... IndexError: range object index out of range Test operations involving NaN/Inf --------------------------------- >>> a + float('Inf') mpfr('inf') >>> float('Inf') + a mpfr('inf') >>> a + float('-Inf') mpfr('-inf') >>> float('-Inf') + a mpfr('-inf') >>> a + float('nan') mpfr('nan') >>> float('nan') + a mpfr('nan') >>> a - float('Inf') mpfr('-inf') >>> float('Inf') - a mpfr('inf') >>> a - float('-Inf') mpfr('inf') >>> float('-Inf') - a mpfr('-inf') >>> a - float('nan') mpfr('nan') >>> float('nan') - a mpfr('nan') >>> a * float('Inf') mpfr('inf') >>> float('Inf') * a mpfr('inf') >>> a * float('-Inf') mpfr('-inf') >>> float('-Inf') * a mpfr('-inf') >>> -a * float('Inf') mpfr('-inf') >>> float('Inf') * -a mpfr('-inf') >>> -a * float('-Inf') mpfr('inf') >>> float('-Inf') * -a mpfr('inf') >>> a * float('nan') mpfr('nan') >>> float('nan') * a mpfr('nan') >>> G.mpz(0) * float('Inf') mpfr('nan') >>> G.mpz(0) * float('-Inf') mpfr('nan') >>> float('Inf') * G.mpz(0) mpfr('nan') >>> float('-Inf') * G.mpz(0) mpfr('nan') >>> a / float('Inf') mpfr('0.0') >>> -a / float('Inf') mpfr('-0.0') >>> float('Inf') / a mpfr('inf') >>> float('Inf') / -a mpfr('-inf') >>> a / float('-Inf') mpfr('-0.0') >>> -a / float('-Inf') mpfr('0.0') >>> float('-Inf') / a mpfr('-inf') >>> float('-Inf') / -a mpfr('inf') >>> a / float('nan') mpfr('nan') >>> float('nan') / a mpfr('nan') >>> float('nan') / G.mpz(0) mpfr('nan') >>> float('nan') / G.mpz(0) mpfr('nan') >>> a + mpfr('Inf') mpfr('inf') >>> mpfr('Inf') + a mpfr('inf') >>> a + mpfr('-Inf') mpfr('-inf') >>> mpfr('-Inf') + a mpfr('-inf') >>> a + mpfr('nan') mpfr('nan') >>> mpfr('nan') + a mpfr('nan') >>> a - mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') - a mpfr('inf') >>> a - mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') - a mpfr('-inf') >>> a - mpfr('nan') mpfr('nan') >>> mpfr('nan') - a mpfr('nan') >>> a * mpfr('Inf') mpfr('inf') >>> mpfr('Inf') * a mpfr('inf') >>> a * mpfr('-Inf') mpfr('-inf') >>> mpfr('-Inf') * a mpfr('-inf') >>> -a * mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') * -a mpfr('-inf') >>> -a * mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') * -a mpfr('inf') >>> a * mpfr('nan') mpfr('nan') >>> mpfr('nan') * a mpfr('nan') >>> G.mpz(0) * mpfr('Inf') mpfr('nan') >>> G.mpz(0) * mpfr('-Inf') mpfr('nan') >>> mpfr('Inf') * G.mpz(0) mpfr('nan') >>> mpfr('-Inf') * G.mpz(0) mpfr('nan') >>> a / mpfr('Inf') mpfr('0.0') >>> -a / mpfr('Inf') mpfr('-0.0') >>> mpfr('Inf') / a mpfr('inf') >>> mpfr('Inf') / -a mpfr('-inf') >>> a / mpfr('-Inf') mpfr('-0.0') >>> -a / mpfr('-Inf') mpfr('0.0') >>> mpfr('-Inf') / a mpfr('-inf') >>> mpfr('-Inf') / -a mpfr('inf') >>> a / mpfr('nan') mpfr('nan') >>> mpfr('nan') / a mpfr('nan') >>> mpfr('nan') / G.mpz(0) mpfr('nan') >>> mpfr('nan') / G.mpz(0) mpfr('nan') >>> divmod(a, float('Inf')) (mpfr('0.0'), mpfr('123.0')) >>> divmod(a, float('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, float('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, float('-Inf')) (mpfr('0.0'), mpfr('-123.0')) >>> divmod(a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(G.mpz(0), float('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(G.mpz(0), float('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(G.mpz(0), float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(a, mpfr('Inf')) (mpfr('0.0'), mpfr('123.0')) >>> divmod(a, mpfr('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, mpfr('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, mpfr('-Inf')) (mpfr('0.0'), mpfr('-123.0')) >>> divmod(a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(G.mpz(0), mpfr('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(G.mpz(0), mpfr('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(G.mpz(0), mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) Test bit operations ------------------- >>> ~a mpz(-124) >>> a&b mpz(72) >>> a|b mpz(507) >>> a^b mpz(435) >>> a<<1 mpz(246) >>> a>>1 mpz(61) >>> a<<-1 Traceback (innermost last): ... ValueError: negative shift count >>> a>>-2 Traceback (innermost last): ... ValueError: negative shift count >>> a<<0 mpz(123) >>> a>>0 mpz(123) Test conversions ---------------- >>> int(G.mpz(-3)) -3 gmpy2-2.0.7/test/test_mpz_pack_unpack.txt0000666000000000000000000000151612204747346017220 0ustar rootrootTesting of gmpy2 pack and unpack -------------------------------- >>> import gmpy2 as G >>> from gmpy2 import mpz,pack,unpack Test ---- >>> x = mpz(0) >>> all((x == pack(unpack(x,i),i) for i in range(1,100))) True >>> x = mpz(1) >>> all((x == pack(unpack(x,i),i) for i in range(1,100))) True >>> x = mpz(2) >>> all((x == pack(unpack(x,i),i) for i in range(1,100))) True >>> x = mpz(3141592635) >>> all((x == pack(unpack(x,i),i) for i in range(1,100))) True >>> x = mpz(1234567891234567890000000000000000000000000000000000000123) >>> all((x == pack(unpack(x,i),i) for i in range(1,100))) True >>> x = mpz(1) << 500 >>> all((x == pack(unpack(x,i),i) for i in range(1,200))) True >>> x -= 1 >>> all((x == pack(unpack(x,i),i) for i in range(1,200))) True gmpy2-2.0.7/test/test_mpz_io.txt0000666000000000000000000001144612542614506015347 0ustar rootrootMPZ related input/output ======================== >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr, mpc >>> from decimal import Decimal as D >>> from fractions import Fraction as F >>> a = mpz(123) >>> b = mpz(456) Test mpz construction --------------------- >>> mpz(3.14) mpz(3) >>> mpz(mpq(17,3)) mpz(5) >>> mpz(23) mpz(23) >>> mpz(-23) mpz(-23) >>> x=1000*1000*1000*1000*1000*1000*1000 >>> print(mpz(x)) 1000000000000000000000 >>> mpz(0.0) mpz(0) >>> mpz(0.0) mpz(0) >>> mpz(-0.0) mpz(0) >>> mpz(float("nan")) Traceback (most recent call last): File "", line 1, in ValueError: 'mpz' does not support NaN >>> mpz(float("inf")) Traceback (most recent call last): File "", line 1, in OverflowError: 'mpz' does not support Infinity >>> mpz(float("-inf")) Traceback (most recent call last): File "", line 1, in OverflowError: 'mpz' does not support Infinity >>> mpz("0") mpz(0) >>> mpz("-0") mpz(0) >>> mpz("hi") Traceback (most recent call last): File "", line 1, in ValueError: invalid digits >>> mpz("123456", 7) mpz(22875) >>> mpz("123456", base=3) Traceback (most recent call last): File "", line 1, in ValueError: invalid digits >>> mpz() mpz(0) >>> mpz(F(1,2)) mpz(0) >>> mpz(F(-3,2)) mpz(-1) >>> mpz(F(3,2)) mpz(1) >>> mpz(D("0")) mpz(0) >>> mpz(D("-0")) mpz(0) >>> mpz(D("1")) mpz(1) >>> mpz(D("1e10")) == mpz(10000000000) True >>> mpz(D("nan")) Traceback (most recent call last): File "", line 1, in File "/opt/local/lib/python3.2/decimal.py", line 1564, in __int__ raise ValueError("Cannot convert NaN to integer") ValueError: Cannot convert NaN to integer >>> mpz(D("inf")) Traceback (most recent call last): File "", line 1, in File "/opt/local/lib/python3.2/decimal.py", line 1566, in __int__ raise OverflowError("Cannot convert infinity to integer") OverflowError: Cannot convert infinity to integer >>> mpz(D("-inf")) Traceback (most recent call last): File "", line 1, in File "/opt/local/lib/python3.2/decimal.py", line 1566, in __int__ raise OverflowError("Cannot convert infinity to integer") OverflowError: Cannot convert infinity to integer >>> G.mpz('043') mpz(43) >>> G.mpz('43',0) mpz(43) >>> G.mpz('0o43') mpz(35) >>> G.mpz('0x43') mpz(67) >>> G.mpz('0x43',10) Traceback (innermost last): ... ValueError: invalid digits >>> G.mpz('43') mpz(43) Test format ----------- >>> str(a) '123' >>> repr(a) 'mpz(123)' >>> hex(a) '0x7b' >>> oct(a) == ('0o173' if sys.version_info[0] == 3 else '0173') True >>> G.mpz('123') mpz(123) >>> G.mpz('1001001011',2) mpz(587) >>> bin(G.mpz('1001001011',2)) '0b1001001011' >>> '1001001011' == G.mpz('1001001011',2).digits(2) True >>> for i in range(2,63): ... print(a.digits(i)) ... 1111011 11120 1323 443 323 234 173 146 123 102 a3 96 8b 83 7b 74 6f 69 63 5i 5d 58 53 4n 4j 4f 4b 47 43 3u 3r 3o 3l 3i 3f 3C 39 36 33 30 2d 2b 2Z 2X 2V 2T 2R 2P 2N 2L 2J 2H 2F 2D 2B 29 27 25 23 21 1z >>> print(a.digits(63)) Traceback (innermost last): ... ValueError: base must be either 0 or in the interval 2 ... 62 >>> a.__format__() Traceback (most recent call last): File "", line 1, in TypeError: function takes exactly 1 argument (0 given) >>> a.__format__('') '123' >>> a.__format__('d') '123' >>> a.__format__('b') '1111011' >>> a.__format__('o') '173' >>> a.__format__('x') '7b' >>> a.__format__('#x') '0x7b' >>> a.__format__('#X') '0X7B' >>> a.__format__('#o') '0o173' >>> a.__format__('#15o') ' 0o173' >>> a.__format__('<#15o') '0o173 ' >>> a.__format__('^#15o') ' 0o173 ' >>> a.__format__('>#15o') ' 0o173' >>> a.__format__('^ #15o') ' 0o173 ' >>> a.__format__('^#15o') ' 0o173 ' >>> a.__format__('^ #16o') ' 0o173 ' >>> a.__format__('#^16o') Traceback (most recent call last): File "", line 1, in ValueError: Invalid conversion specification >>> a.__format__('^#16o') ' 0o173 ' gmpy2-2.0.7/test/test_mpz_functions.txt0000666000000000000000000003055412204747346016755 0ustar rootrootMPZ Related Functions ===================== >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr >>> a = mpz(123) >>> b = mpz(456) Test gmpy2.add -------------- >>> G.add(a, b) mpz(579) >>> G.add(a, 456) mpz(579) >>> G.add(123, 456) mpz(579) >>> G.add(123, b) mpz(579) Test gmpy2.bincoef ------------------ >>> for i in range(10): ... print(G.bincoef(10,i)) ... 1 10 45 120 210 252 210 120 45 10 Test gmpy2.bit_clear -------------------- >>> a.bit_clear(0) mpz(122) Test gmpy2.bit_flip ------------------- >>> bin(a) '0b1111011' >>> bin(a.bit_flip(1)) '0b1111001' >>> bin(a.bit_flip(2)) '0b1111111' Test gmpy2.bit_length --------------------- >>> G.mpz(0).bit_length() 0 >>> G.mpz(12345).bit_length() 14 Test gmpy2.bit_mask ------------------- >>> G.bit_mask(9) mpz(511) Test gmpy2.bit_scan0 -------------------- >>> [a.bit_scan0(j) for j in range(33)] [2, 2, 2, 7, 7, 7, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> n=G.mpz(-(7+6*16+5*256+7*4092)) >>> [n.bit_scan0(j) for j in range(18)] [1, 1, 3, 3, 6, 6, 6, 8, 8, 10, 10, 12, 12, 13, 14, -1, None, None] >>> del n Test gmpy2.bit_scan1 -------------------- >>> [a.bit_scan1(j) for j in range(10)] [0, 1, 3, 3, 4, 5, 6, None, None, None] >>> n=G.mpz(-(7+6*16+5*256+7*4092)) >>> [n.bit_scan1(j) for j in range(33)] [0, 2, 2, 4, 4, 5, 7, 7, 9, 9, 11, 11, 15, 15, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] >>> del n Test gmpy2.bit_set ------------------ >>> a.bit_set(20) mpz(1048699) Test gmpy2.bit_test ------------------- >>> [a.bit_test(i) for i in range(8)] [True, True, False, True, True, True, True, False] >>> [b.bit_test(i) for i in range(10)] [False, False, False, True, False, False, True, True, True, False] Test gmpy2.c_div ---------------- >>> G.c_div(b,64) mpz(8) >>> G.c_div(b,-64) mpz(-7) >>> G.c_div(-b,64) mpz(-7) >>> G.c_div(-b,-64) mpz(8) Test gmpy2.c_div_2exp --------------------- >>> G.c_div_2exp(b, 6) mpz(8) >>> G.c_div_2exp(b, -6) Traceback (most recent call last): File "", line 1, in OverflowError: can't convert negative value to unsigned int >>> G.c_div_2exp(-b, 6) mpz(-7) Test gmpy2.c_divmod ------------------- >>> G.c_divmod(b,64) (mpz(8), mpz(-56)) >>> G.c_divmod(b,-64) (mpz(-7), mpz(8)) >>> G.c_divmod(-b,64) (mpz(-7), mpz(-8)) >>> G.c_divmod(-b,-64) (mpz(8), mpz(56)) >>> G.c_divmod(17,5) (mpz(4), mpz(-3)) >>> G.c_divmod(-17,5) (mpz(-3), mpz(-2)) >>> G.c_divmod(17,-5) (mpz(-3), mpz(2)) >>> G.c_divmod(-17,-5) (mpz(4), mpz(3)) >>> G.c_divmod(b, 4.0) Traceback (most recent call last): File "", line 1, in TypeError: c_divmod() requires 'mpz','mpz' arguments >>> G.c_divmod('a', b) Traceback (most recent call last): File "", line 1, in TypeError: c_divmod() requires 'mpz','mpz' arguments >>> G.c_divmod(b) Traceback (most recent call last): File "", line 1, in TypeError: c_divmod() requires 'mpz','mpz' arguments Test gmpy2.c_divmod_2exp ------------------------ >>> G.c_divmod_2exp(b, 6) (mpz(8), mpz(-56)) >>> G.c_divmod_2exp(-b, 6) (mpz(-7), mpz(-8)) Test gmpy2.c_mod ---------------- >>> G.c_mod(b,64) mpz(-56) >>> G.c_mod(b,-64) mpz(8) >>> G.c_mod(-b,64) mpz(-8) >>> G.c_mod(-b,-64) mpz(56) Test gmpy2.c_mod_2exp --------------------- >>> G.c_mod_2exp(b, 6) mpz(-56) >>> G.c_mod_2exp(-b, 6) mpz(-8) Test gmpy2.comb --------------- >>> G.comb(3,-1) Traceback (most recent call last): ... ValueError: binomial coefficient with negative k >>> G.comb(8,4) mpz(70) Test gmpy2.divexact ------------------- >>> aa=G.mpz('1234567912345678912345679') >>> bb=G.mpz('789789789789789789789789') >>> cc=aa*bb >>> print(G.divexact(cc,aa)) 789789789789789789789789 >>> del aa,bb,cc Test gmpy2.divm --------------- >>> G.divm(b,a,20) mpz(12) >>> G.divm(a,b,100) Traceback (innermost last): ... ZeroDivisionError: not invertible >>> G.divm(6,12,14) mpz(4) >>> G.divm(0,1,2) mpz(0) >>> G.divm(4,8,20) mpz(3) Test gmpy2.f_div ---------------- Test gmpy2.f_div_2exp --------------------- Test gmpy2.f_divmod ------------------- >>> G.f_divmod(17,5) (mpz(3), mpz(2)) >>> G.f_divmod(-17,5) (mpz(-4), mpz(3)) >>> G.f_divmod(17,-5) (mpz(-4), mpz(-3)) >>> G.f_divmod(-17,-5) (mpz(3), mpz(-2)) >>> G.f_divmod(b,64) (mpz(7), mpz(8)) >>> G.f_divmod(-b,64) (mpz(-8), mpz(56)) >>> G.f_divmod(b,-64) (mpz(-8), mpz(-56)) >>> G.f_divmod(-b,-64) (mpz(7), mpz(-8)) Test gmpy2.f_divmod_2exp ------------------------ >>> G.f_divmod_2exp(b,6) (mpz(7), mpz(8)) >>> G.f_divmod_2exp(-b,6) (mpz(-8), mpz(56)) Test gmpy2.f_mod ---------------- Test gmpy2.f_mod_2exp --------------------- >>> G.f_mod_2exp(a,5) mpz(27) >>> G.f_mod_2exp(b,5) mpz(8) >>> G.f_mod_2exp(b,5) == (b%32) True >>> G.f_mod_2exp(a,5) == (a%32) True Test gmpy2.fac -------------- >>> G.fac(7) mpz(5040) Test gmpy2.fib -------------- >>> G.fib(17) mpz(1597) Test gmpy2.fib2 --------------- >>> G.fib2(17) (mpz(1597), mpz(987)) Test gmpy2.gcd -------------- >>> G.gcd(a,b) mpz(3) Test gmpy2.gcdext ----------------- >>> temp=G.gcdext(a,b) >>> temp[0]==a*temp[1]+b*temp[2] True >>> temp=G.gcdext(123,456) >>> temp[0]==a*temp[1]+b*temp[2] True >>> del temp Test gmpy2.hamdist ------------------ >>> G.hamdist(a,b) 6 >>> G.hamdist(3) Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments >>> G.hamdist(a) Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments >>> G.hamdist(a, 3, 4) Traceback (innermost last): ... TypeError: hamdist() requires 'mpz','mpz' arguments Test gmpy2.invert ----------------- >>> G.invert(a,100) mpz(87) >>> G.invert(b,100) mpz(0) >>> G.invert(3) Traceback (innermost last): ... TypeError: invert() requires 'mpz','mpz' arguments >>> G.invert() Traceback (innermost last): ... TypeError: invert() requires 'mpz','mpz' arguments Test gmpy2.iroot ---------------- >>> for i in range(5): ... print(G.iroot(a,i+1),G.iroot(b,i+1)) ... (mpz(123), True) (mpz(456), True) (mpz(11), False) (mpz(21), False) (mpz(4), False) (mpz(7), False) (mpz(3), False) (mpz(4), False) (mpz(2), False) (mpz(3), False) >>> G.iroot(9,2) (mpz(3), True) Test gmpy2.iroot_rem -------------------- >>> G.iroot_rem(a,2) (mpz(11), mpz(2)) >>> G.iroot_rem(a,3) (mpz(4), mpz(59)) >>> G.iroot_rem(a*a) Traceback (most recent call last): ... TypeError: iroot_rem() requires 'mpz','int' arguments >>> G.iroot_rem(a*a,2) (mpz(123), mpz(0)) Test gmpy2.is_even ------------------ >>> G.is_even(a) False >>> G.is_even(b) True Test gmpy2.is_odd ----------------- >>> G.is_odd(a) True >>> G.is_odd(b) False Test gmpy2.is_power ------------------- >>> G.is_power() Traceback (most recent call last): File "", line 1, in TypeError: is_power() takes exactly one argument (0 given) >>> a.is_power() >>> G.is_power(99*99*99) True >>> G.is_power(99*98) False Test gmpy2.is_prime ------------------- >>> G.is_prime(3,-3) Traceback (most recent call last): ... ValueError: repetition count for is_prime must be positive >>> G.is_prime(12345) False >>> G.is_prime(80**81 + 81**80) True Test gmpy2.is_square -------------------- >>> a.is_square() False >>> G.is_square(99*99) True >>> G.is_square(99*99*99) False >>> G.is_square(0) True >>> G.is_square(-1) False Test gmpy2.isqrt ---------------- >>> print(G.isqrt(a)) 11 >>> print(G.isqrt(b)) 21 >>> G.isqrt(-1) Traceback (most recent call last): ... ValueError: isqrt() of negative number Test gmpy2.isqrt_rem -------------------- >>> print(G.isqrt_rem(a)) (mpz(11), mpz(2)) >>> print(G.isqrt_rem(b)) (mpz(21), mpz(15)) >>> G.isqrt_rem(-1) Traceback (most recent call last): ... ValueError: isqrt_rem() of negative number Test gmpy2.jacobi ----------------- >>> G.jacobi(10,3) 1 >>> G.jacobi(10,-3) Traceback (most recent call last): ... ValueError: jacobi's y must be odd prime > 0 >>> G.jacobi(3) Traceback (innermost last): ... TypeError: jacobi() requires 'mpz','mpz' arguments >>> G.jacobi() Traceback (innermost last): ... TypeError: jacobi() requires 'mpz','mpz' arguments Test gmpy2.kronecker -------------------- >>> G.kronecker(10,3) 1 >>> G.kronecker(10,-3) 1 >>> G.kronecker(3) Traceback (innermost last): ... TypeError: kronecker() requires 'mpz','mpz' arguments >>> G.kronecker() Traceback (innermost last): ... TypeError: kronecker() requires 'mpz','mpz' arguments >>> aaa = 10**20 >>> bbb = aaa+39 >>> G.jacobi(aaa,bbb) 1 >>> G.legendre(aaa,bbb) 1 >>> G.kronecker(aaa,bbb) 1 >>> del aaa,bbb Test gmpy2.lcm -------------- >>> G.lcm(a,b) mpz(18696) Test gmpy2.legendre ------------------- >>> G.legendre(10,3) 1 >>> G.legendre(10,-3) Traceback (most recent call last): ... ValueError: legendre's y must be odd and > 0 >>> G.legendre(3) Traceback (innermost last): ... TypeError: legendre() requires 'mpz','mpz' arguments >>> G.legendre() Traceback (innermost last): ... TypeError: legendre() requires 'mpz','mpz' arguments Test gmpy2.lucas ---------------- Test gmpy2.lucas2 ----------------- Test gmpy2.mul -------------- Test gmpy2.mul_2exp ------------------- Test gmpy2.next_prime --------------------- Test gmpy2.numdigits -------------------- >>> G.numdigits(23) 2 >>> G.numdigits(23,2) 5 >>> G.numdigits(23,99) Traceback (most recent call last): ... ValueError: base must be either 0 or in the interval 2 ... 62 Test gmpy2.pack --------------- Test gmpy2.popcount ------------------- >>> G.popcount(a) 6 >>> G.popcount(b) 4 >>> G.popcount(-7) -1 >>> G.popcount(0) 0 Test gmpy2.remove ----------------- gmpy2.remove factors out multiple copies of a factor from a larger integer. The factor must be greater than or equal to 2. >>> G.remove(a,2) (mpz(123), 0) >>> G.remove(a,3) (mpz(41), 1) >>> G.remove(b,2) (mpz(57), 3) >>> G.remove(b,3) (mpz(152), 1) >>> G.remove(b,1) Traceback (most recent call last): File "", line 1, in ValueError: factor must be > 1 >>> G.remove(b,0) Traceback (most recent call last): File "", line 1, in ValueError: factor must be > 1 >>> G.remove(b,789) (mpz(456), 0) >>> G.remove(b,-3) Traceback (most recent call last): File "", line 1, in ValueError: factor must be > 1 >>> G.remove(b,float('NaN')) Traceback (most recent call last): File "", line 1, in TypeError: remove() requires 'mpz','mpz' arguments >>> G.remove(3,-1) Traceback (most recent call last): ... ValueError: factor must be > 1 >>> G.remove(3) Traceback (innermost last): ... TypeError: remove() requires 'mpz','mpz' arguments >>> G.remove() Traceback (innermost last): ... TypeError: remove() requires 'mpz','mpz' arguments Test gmpy2.t_div ---------------- Test gmpy2.t_div_2exp --------------------- Test gmpy2.t_divmod ------------------- >>> G.t_divmod(17,5) (mpz(3), mpz(2)) >>> G.t_divmod(-17,5) (mpz(-3), mpz(-2)) >>> G.t_divmod(17,-5) (mpz(-3), mpz(2)) >>> G.t_divmod(-17,-5) (mpz(3), mpz(-2)) Test gmpy2.t_divmod_2exp ------------------------ Test gmpy2.t_mod ---------------- Test gmpy2.t_mod_2exp --------------------- gmpy2-2.0.7/test/test_mpz_comp.txt0000666000000000000000000000634212204747346015701 0ustar rootrootMPZ related comparions ====================== >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr >>> a = mpz(123) >>> b = mpz(456) Test comparisons ---------------- >>> c=G.mpz(a) >>> a mpz(123) >>> b mpz(456) >>> c is a True >>> c==a True >>> c>a False >>> c>> a>b False >>> a>> not G.mpz(0) True >>> not a False >>> G.mpz(1) == None False >>> G.mpz(1) == '1' False >>> G.mpz(1) == 'abc' False >>> [G.mpz(23), None].count(None) 1 Test comparisons with NaN/Inf ----------------------------- Note: Tests involving mpfr should be moved to another file. >>> G.context().trap_divzero == False True >>> a == float('Inf') False >>> a != float('Inf') True >>> a > float('Inf') False >>> a >= float('Inf') False >>> a < float('Inf') True >>> a <= float('Inf') True >>> a == float('-Inf') False >>> a != float('-Inf') True >>> a > float('-Inf') True >>> a >= float('-Inf') True >>> a < float('-Inf') False >>> a <= float('-Inf') False >>> a == float('nan') False >>> a != float('nan') True >>> a > float('nan') False >>> a >= float('nan') False >>> a < float('nan') False >>> a <= float('nan') False >>> float('Inf') == a False >>> float('Inf') != a True >>> float('Inf') > a True >>> float('Inf') >= a True >>> float('Inf') < a False >>> float('Inf') <= a False >>> float('-Inf') == a False >>> float('-Inf') != a True >>> float('-Inf') > a False >>> float('-Inf') >= a False >>> float('-Inf') < a True >>> float('-Inf') <= a True >>> float('nan') == a False >>> float('nan') != a True >>> float('nan') > a False >>> float('nan') >= a False >>> float('nan') < a False >>> float('nan') <= a False >>> a == mpfr('Inf') False >>> a != mpfr('Inf') True >>> a > mpfr('Inf') False >>> a >= mpfr('Inf') False >>> a < mpfr('Inf') True >>> a <= mpfr('Inf') True >>> a == mpfr('-Inf') False >>> a != mpfr('-Inf') True >>> a > mpfr('-Inf') True >>> a >= mpfr('-Inf') True >>> a < mpfr('-Inf') False >>> a <= mpfr('-Inf') False >>> a == mpfr('nan') False >>> a != mpfr('nan') True >>> a > mpfr('nan') False >>> a >= mpfr('nan') False >>> a < mpfr('nan') False >>> a <= mpfr('nan') False >>> mpfr('Inf') == a False >>> mpfr('Inf') != a True >>> mpfr('Inf') > a True >>> mpfr('Inf') >= a True >>> mpfr('Inf') < a False >>> mpfr('Inf') <= a False >>> mpfr('-Inf') == a False >>> mpfr('-Inf') != a True >>> mpfr('-Inf') > a False >>> mpfr('-Inf') >= a False >>> mpfr('-Inf') < a True >>> mpfr('-Inf') <= a True >>> mpfr('nan') == a False >>> mpfr('nan') != a True >>> mpfr('nan') > a False >>> mpfr('nan') >= a False >>> mpfr('nan') < a False >>> mpfr('nan') <= a False gmpy2-2.0.7/test/test_mpz_bit.txt0000666000000000000000000000135512204747346015520 0ustar rootrootMPZ Functionality ================= >>> import gmpy2 as G >>> from gmpy2 import mpz >>> a = mpz(123) >>> b = mpz(456) Test bit operations =================== Test bit_clear -------------- Test bit_flip ------------- Test bit_length --------------- Test bit_mask ------------- Test bit_scan0 -------------- Test bit_scan1 -------------- Test bit_set ------------ Test bit_test ------------- Test hamdist ------------ Test popcount ------------- Test __invert__ --------------- Test __lshift__ --------------- Test __or__ ----------- Test __rlshift__ ---------------- Test __ror__ ------------ Test __rrshift__ ---------------- Test __rshift__ --------------- Test __rxor__ ------------- Test __xor__ ------------ gmpy2-2.0.7/test/test_mpz.txt0000666000000000000000000002513512204747346014664 0ustar rootrootMPZ Functionality ================= Testing of mpz functionality is split into multiple files. test_mpz.txt Test basic functionality and stuff not covered anywhere else. test_mpz_functions.txt Test mpz functions, including error messages. test_mpz_io.txt Test input/output and formating. test_mpz_comp.txt Test comparisons. >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr, mpc >>> from decimal import Decimal as D >>> from fractions import Fraction as F >>> a = mpz(123) >>> b = mpz(456) >>> c = 12345678901234567890 Test elementary operations ========================== Test addition ------------- >>> a+1 mpz(124) >>> a+(-1) mpz(122) >>> 1+a mpz(124) >>> (-1)+a mpz(122) >>> a+b mpz(579) >>> b+a mpz(579) >>> a+'b' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for +: 'mpz' and 'str' >>> 'b'+a Traceback (most recent call last): File "", line 1, in TypeError: ** message detail varies ** >>> print(a+c) 12345678901234568013 >>> print(c+a) 12345678901234568013 Test subtraction ---------------- >>> a-1 mpz(122) >>> a-(-1) mpz(124) >>> 1-a mpz(-122) >>> (-1)-a mpz(-124) >>> a-b mpz(-333) >>> b-a mpz(333) >>> a-'b' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'mpz' and 'str' >>> 'b'-a Traceback (most recent call last): File "", line 1, in TypeError: ** message detail varies ** >>> print(a-c) -12345678901234567767 >>> print(c-a) 12345678901234567767 Test multiplication ------------------- >>> a*b mpz(56088) >>> b*a mpz(56088) >>> a*0 mpz(0) >>> 0*a mpz(0) >>> a*123 mpz(15129) >>> 123*a mpz(15129) >>> print(a*c) 1518518504851851850470 >>> print(c*a) 1518518504851851850470 >>> a*'b' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' >>> 'b'*a 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' Test division ------------- >>> a//b mpz(0) >>> a/b mpfr('0.26973684210526316') >>> b//a mpz(3) >>> b/a mpfr('3.7073170731707319') >>> (a*b)//b mpz(123) >>> (a*b)//a mpz(456) >>> a//0 Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division or modulo by zero >>> a/0 Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division or modulo by zero >>> a/0.0 mpfr('inf') >>> print(c//a) 100371373180768844 >>> a**10//c mpz(64) Test modulo ----------- >>> a%b mpz(123) >>> b%a mpz(87) >>> divmod(a,b) (mpz(0), mpz(123)) >>> divmod(b,a) (mpz(3), mpz(87)) >>> divmod(a,0) Traceback (most recent call last): ... ZeroDivisionError: division or modulo by zero >>> divmod(a,mpz(0)) Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division or modulo by zero >>> divmod(123,mpz(0)) Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division or modulo by zero >>> divmod(b,123) (mpz(3), mpz(87)) >>> divmod(a,c) (mpz(0), mpz(123)) >>> divmod(a,int(c)) (mpz(0), mpz(123)) >>> print("%s %s" % divmod(a*(c-1),c)) 122 12345678901234567767 >>> print("%s %s" % divmod(a*(c-1),int(c))) 122 12345678901234567767 >>> divmod(a*(c-1),-c) (mpz(-123), mpz(-123)) >>> divmod(a*(c-1),-int(c)) (mpz(-123), mpz(-123)) >>> print("%s %s" % divmod(int(a*(c-1)),-int(c))) -123 -123 Test miscellaneous ------------------ >>> a+True mpz(124) >>> a+False mpz(123) >>> a*False mpz(0) >>> a//True mpz(123) >>> abs(-a) == a True >>> print(pow(a,10)) 792594609605189126649 >>> pow(a,7,b) mpz(99) >>> G.sign(b-a) 1 >>> G.sign(b-b) 0 >>> G.sign(a-b) -1 >>> G.sign(a) 1 >>> G.sign(-a) -1 >>> z=b-b; G.sign(z) 0 Test pickle ----------- >>> import pickle >>> pickle.loads(pickle.dumps(G.mpz(12346789))) mpz(12346789) >>> pickle.loads(pickle.dumps(G.mpz(-12346789))) mpz(-12346789) >>> pickle.loads(pickle.dumps(G.mpz(0))) mpz(0) Test mpz.__index__ ------------------ >>> range(333)[a] 123 >>> range(333)[b] Traceback (innermost last): ... IndexError: range object index out of range Test operations involving NaN/Inf --------------------------------- >>> a + float('Inf') mpfr('inf') >>> float('Inf') + a mpfr('inf') >>> a + float('-Inf') mpfr('-inf') >>> float('-Inf') + a mpfr('-inf') >>> a + float('nan') mpfr('nan') >>> float('nan') + a mpfr('nan') >>> a - float('Inf') mpfr('-inf') >>> float('Inf') - a mpfr('inf') >>> a - float('-Inf') mpfr('inf') >>> float('-Inf') - a mpfr('-inf') >>> a - float('nan') mpfr('nan') >>> float('nan') - a mpfr('nan') >>> a * float('Inf') mpfr('inf') >>> float('Inf') * a mpfr('inf') >>> a * float('-Inf') mpfr('-inf') >>> float('-Inf') * a mpfr('-inf') >>> -a * float('Inf') mpfr('-inf') >>> float('Inf') * -a mpfr('-inf') >>> -a * float('-Inf') mpfr('inf') >>> float('-Inf') * -a mpfr('inf') >>> a * float('nan') mpfr('nan') >>> float('nan') * a mpfr('nan') >>> G.mpz(0) * float('Inf') mpfr('nan') >>> G.mpz(0) * float('-Inf') mpfr('nan') >>> float('Inf') * G.mpz(0) mpfr('nan') >>> float('-Inf') * G.mpz(0) mpfr('nan') >>> a / float('Inf') mpfr('0.0') >>> -a / float('Inf') mpfr('-0.0') >>> float('Inf') / a mpfr('inf') >>> float('Inf') / -a mpfr('-inf') >>> a / float('-Inf') mpfr('-0.0') >>> -a / float('-Inf') mpfr('0.0') >>> float('-Inf') / a mpfr('-inf') >>> float('-Inf') / -a mpfr('inf') >>> a / float('nan') mpfr('nan') >>> float('nan') / a mpfr('nan') >>> float('nan') / G.mpz(0) mpfr('nan') >>> float('nan') / G.mpz(0) mpfr('nan') >>> a - mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') - a mpfr('inf') >>> a - mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') - a mpfr('-inf') >>> a - mpfr('nan') mpfr('nan') >>> mpfr('nan') - a mpfr('nan') >>> a * mpfr('Inf') mpfr('inf') >>> mpfr('Inf') * a mpfr('inf') >>> a * mpfr('-Inf') mpfr('-inf') >>> mpfr('-Inf') * a mpfr('-inf') >>> -a * mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') * -a mpfr('-inf') >>> -a * mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') * -a mpfr('inf') >>> a * mpfr('nan') mpfr('nan') >>> mpfr('nan') * a mpfr('nan') >>> G.mpz(0) * mpfr('Inf') mpfr('nan') >>> G.mpz(0) * mpfr('-Inf') mpfr('nan') >>> mpfr('Inf') * G.mpz(0) mpfr('nan') >>> mpfr('-Inf') * G.mpz(0) mpfr('nan') >>> a / mpfr('Inf') mpfr('0.0') >>> -a / mpfr('Inf') mpfr('-0.0') >>> mpfr('Inf') / a mpfr('inf') >>> mpfr('Inf') / -a mpfr('-inf') >>> a / mpfr('-Inf') mpfr('-0.0') >>> -a / mpfr('-Inf') mpfr('0.0') >>> mpfr('-Inf') / a mpfr('-inf') >>> mpfr('-Inf') / -a mpfr('inf') >>> a / mpfr('nan') mpfr('nan') >>> mpfr('nan') / a mpfr('nan') >>> mpfr('nan') / G.mpz(0) mpfr('nan') >>> mpfr('nan') / G.mpz(0) mpfr('nan') >>> divmod(a, mpfr('Inf')) (mpfr('0.0'), mpfr('123.0')) >>> divmod(a, mpfr('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, mpfr('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, mpfr('-Inf')) (mpfr('0.0'), mpfr('-123.0')) >>> divmod(a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(G.mpz(0), mpfr('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(G.mpz(0), mpfr('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(G.mpz(0), mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(a, mpfr('Inf')) (mpfr('0.0'), mpfr('123.0')) >>> divmod(a, mpfr('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, mpfr('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, mpfr('-Inf')) (mpfr('0.0'), mpfr('-123.0')) >>> divmod(a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(G.mpz(0), mpfr('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(G.mpz(0), mpfr('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(G.mpz(0), mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) Test bit operations ------------------- >>> ~a mpz(-124) >>> a&b mpz(72) >>> a|b mpz(507) >>> a^b mpz(435) >>> a<<1 mpz(246) >>> a>>1 mpz(61) >>> a<<-1 Traceback (innermost last): ... ValueError: negative shift count >>> a>>-2 Traceback (innermost last): ... ValueError: negative shift count >>> a<<0 mpz(123) >>> a>>0 mpz(123) Test conversions ---------------- >>> int(G.mpz(-3)) -3 gmpy2-2.0.7/test/test_mpq_to_from_binary.txt0000666000000000000000000000065612204747346017745 0ustar rootrootTesting of gmpy2 mpq to_binary and from_binary ---------------------------------------------- >>> import gmpy2 >>> from gmpy2 import mpq,to_binary,from_binary Test ---- >>> x=mpq(0,1);x==from_binary(to_binary(x)) True >>> x=mpq(1,1);x==from_binary(to_binary(x)) True >>> x=mpq(-1,2);x==from_binary(to_binary(x)) True >>> x=mpq(123456789123456789,9876);x==from_binary(to_binary(x)) True gmpy2-2.0.7/test/test_mpq.txt0000666000000000000000000002101612204747346014645 0ustar rootrootMPQ Functionality ================= Testing of mpq functionality is split into multiple files. test_mpq.txt Test basic functionality and stuff not covered anywhere else. test_mpq_io.txt Test input/output and formating. test_mpq_comp.txt Test comparisons. >>> import gmpy2 as G >>> from fractions import Fraction as F >>> from gmpy2 import mpz, mpq, mpfr >>> a = mpq(3,11) >>> b = mpq(1,2) >>> c = F(5,7) Test elementary operations ========================== Test addition ------------- Test subtraction ---------------- >>> a-b mpq(-5,22) >>> b-a mpq(5,22) >>> a-1 mpq(-8,11) >>> 1-a mpq(8,11) >>> a-c mpq(-34,77) >>> c-a mpq(34,77) >>> a-a mpq(0,1) >>> a-mpz(123456) mpq(-1358013,11) >>> mpz(-123456)-a mpq(-1358019,11) >>> a-'b' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'mpq' and 'str' >>> 'b'-a Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'str' and 'mpq' Test multiplication ------------------- >>> a*b mpq(3,22) >>> b*a mpq(3,22) >>> a*0 mpq(0,1) >>> 0*a mpq(0,1) >>> a*-1 mpq(-3,11) >>> -1*a mpq(-3,11) >>> a*mpz(17) mpq(51,11) >>> mpz(17)*a mpq(51,11) >>> a*a mpq(9,121) >>> a*'b' Traceback (most recent call last): File "", line 1, in TypeError: can't multiply sequence by non-int of type 'mpq' >>> 'b'*a Traceback (most recent call last): File "", line 1, in TypeError: can't multiply sequence by non-int of type 'mpq' Test division ------------- >>> a//b mpz(0) >>> b//a mpz(1) >>> a/b mpq(6,11) >>> b/a mpq(11,6) >>> a/0 Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division or modulo by zero >>> a//0 Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division or modulo by zero >>> 0//a mpz(0) >>> 0/a mpq(0,1) Test modulo ----------- >>> a%b mpq(3,11) >>> b%a mpq(5,22) >>> divmod(a,b) (mpz(0), mpq(3,11)) >>> divmod(b,a) (mpz(1), mpq(5,22)) >>> divmod(a,0) Traceback (most recent call last): File "", line 1, in ZeroDivisionError: 'mpq' division or modulo by zero >>> divmod(17,a) (mpz(62), mpq(1,11)) >>> divmod(mpz(17),a) (mpz(62), mpq(1,11)) >>> divmod(a,c) (mpz(0), mpq(3,11)) Test pickle ----------- >>> import pickle >>> pickle.loads(pickle.dumps(G.mpq(1234,6789))) mpq(1234,6789) >>> pickle.loads(pickle.dumps(G.mpq(-1234,6789))) mpq(-1234,6789) >>> pickle.loads(pickle.dumps(G.mpq(0,1))) mpq(0,1) Test operations involving NaN/Inf --------------------------------- >>> a + float('Inf') mpfr('inf') >>> float('Inf') + a mpfr('inf') >>> a + float('-Inf') mpfr('-inf') >>> float('-Inf') + a mpfr('-inf') >>> a + float('nan') mpfr('nan') >>> float('nan') + a mpfr('nan') >>> a - float('Inf') mpfr('-inf') >>> float('Inf') - a mpfr('inf') >>> a - float('-Inf') mpfr('inf') >>> float('-Inf') - a mpfr('-inf') >>> a - float('nan') mpfr('nan') >>> float('nan') - a mpfr('nan') >>> a * float('Inf') mpfr('inf') >>> float('Inf') * a mpfr('inf') >>> a * float('-Inf') mpfr('-inf') >>> float('-Inf') * a mpfr('-inf') >>> -a * float('Inf') mpfr('-inf') >>> float('Inf') * -a mpfr('-inf') >>> -a * float('-Inf') mpfr('inf') >>> float('-Inf') * -a mpfr('inf') >>> a * float('nan') mpfr('nan') >>> float('nan') * a mpfr('nan') >>> G.mpz(0) * float('Inf') mpfr('nan') >>> G.mpz(0) * float('-Inf') mpfr('nan') >>> float('Inf') * G.mpz(0) mpfr('nan') >>> float('-Inf') * G.mpz(0) mpfr('nan') >>> a / float('Inf') mpfr('0.0') >>> -a / float('Inf') mpfr('-0.0') >>> float('Inf') / a mpfr('inf') >>> float('Inf') / -a mpfr('-inf') >>> a / float('-Inf') mpfr('-0.0') >>> -a / float('-Inf') mpfr('0.0') >>> float('-Inf') / a mpfr('-inf') >>> float('-Inf') / -a mpfr('inf') >>> a / float('nan') mpfr('nan') >>> float('nan') / a mpfr('nan') >>> float('nan') / G.mpz(0) mpfr('nan') >>> float('nan') / G.mpz(0) mpfr('nan') >>> a + mpfr('Inf') mpfr('inf') >>> mpfr('Inf') + a mpfr('inf') >>> a + mpfr('-Inf') mpfr('-inf') >>> mpfr('-Inf') + a mpfr('-inf') >>> a + mpfr('nan') mpfr('nan') >>> mpfr('nan') + a mpfr('nan') >>> a - mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') - a mpfr('inf') >>> a - mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') - a mpfr('-inf') >>> a - mpfr('nan') mpfr('nan') >>> mpfr('nan') - a mpfr('nan') >>> a * mpfr('Inf') mpfr('inf') >>> mpfr('Inf') * a mpfr('inf') >>> a * mpfr('-Inf') mpfr('-inf') >>> mpfr('-Inf') * a mpfr('-inf') >>> -a * mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') * -a mpfr('-inf') >>> -a * mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') * -a mpfr('inf') >>> a * mpfr('nan') mpfr('nan') >>> mpfr('nan') * a mpfr('nan') >>> G.mpz(0) * mpfr('Inf') mpfr('nan') >>> G.mpz(0) * mpfr('-Inf') mpfr('nan') >>> mpfr('Inf') * G.mpz(0) mpfr('nan') >>> mpfr('-Inf') * G.mpz(0) mpfr('nan') >>> a / mpfr('Inf') mpfr('0.0') >>> -a / mpfr('Inf') mpfr('-0.0') >>> mpfr('Inf') / a mpfr('inf') >>> mpfr('Inf') / -a mpfr('-inf') >>> a / mpfr('-Inf') mpfr('-0.0') >>> -a / mpfr('-Inf') mpfr('0.0') >>> mpfr('-Inf') / a mpfr('-inf') >>> mpfr('-Inf') / -a mpfr('inf') >>> a / mpfr('nan') mpfr('nan') >>> mpfr('nan') / a mpfr('nan') >>> mpfr('nan') / G.mpz(0) mpfr('nan') >>> mpfr('nan') / G.mpz(0) mpfr('nan') >>> divmod(a, float('Inf')) (mpfr('0.0'), mpfr('0.27272727272727271')) >>> divmod(a, float('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, float('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, float('-Inf')) (mpfr('0.0'), mpfr('-0.27272727272727271')) >>> divmod(a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(G.mpz(0), float('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(G.mpz(0), float('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(G.mpz(0), float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(a, mpfr('Inf')) (mpfr('0.0'), mpfr('0.27272727272727271')) >>> divmod(a, mpfr('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, mpfr('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, mpfr('-Inf')) (mpfr('0.0'), mpfr('-0.27272727272727271')) >>> divmod(a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(G.mpz(0), mpfr('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(G.mpz(0), mpfr('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(G.mpz(0), mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), G.mpz(0)) (mpfr('nan'), mpfr('nan')) gmpy2-2.0.7/test/test_mpfr_trig.txt0000666000000000000000000002762412542614506016050 0ustar rootrootMPFR Functionality ================== >>> import gmpy2 >>> import math >>> from gmpy2 import mpfr, mpq, mpz >>> from fractions import Fraction as F >>> from decimal import Decimal as D >>> def _cmp(x,y): ... return x.as_integer_ratio() == y.as_integer_ratio() ... Test trigonometric operations ============================= Note: gmpy2 returns InvalidOperationError whereas the math module returns ValueError. The test of acos verifies that InvalidOperationError is sub- classed from ValueError. Note: The math module assumes non-signaling NaNs; math.acos(float("nan")) does not raise an exception. But math.acos(float("inf")) and math.acos(float("-inf")) do raise exceptions. MPFR treats NaN as a signaling NaN and raises an exception if trap_invalid is True. Test acos --------- >>> gmpy2.set_context(gmpy2.context()) >>> _cmp(gmpy2.acos(mpfr("0.2")), math.acos(0.2)) True >>> gmpy2.acos() Traceback (most recent call last): File "", line 1, in TypeError: acos() takes exactly one argument (0 given) >>> gmpy2.acos("a") Traceback (most recent call last): File "", line 1, in TypeError: acos() argument type not supported >>> gmpy2.acos(0,0) Traceback (most recent call last): File "", line 1, in TypeError: acos() takes exactly one argument (2 given) >>> gmpy2.acos(0) mpfr('1.5707963267948966') >>> gmpy2.acos(mpz(0)) mpfr('1.5707963267948966') >>> gmpy2.acos(mpq(1,2)) mpfr('1.0471975511965979') >>> gmpy2.acos(F(1,2)) mpfr('1.0471975511965979') >>> gmpy2.acos(D("0.5")) mpfr('1.0471975511965979') >>> gmpy2.acos(mpfr("nan")) mpfr('nan') >>> gmpy2.acos(mpfr("inf")) mpfr('nan') >>> gmpy2.acos(mpfr("-inf")) mpfr('nan') >>> gmpy2.set_context(gmpy2.context(trap_invalid=True)) >>> gmpy2.acos(mpfr("nan")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in acos() >>> gmpy2.acos(mpfr("inf")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in acos() >>> gmpy2.acos(mpfr("-inf")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in acos() >>> gmpy2.set_context(gmpy2.context(precision=100)) >>> gmpy2.acos(mpfr("0.2")) mpfr('1.3694384060045658277761961394221',100) >>> gmpy2.get_context() context(precision=100, 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) Test asin --------- >>> gmpy2.set_context(gmpy2.context()) >>> _cmp(gmpy2.asin(mpfr("0.2")), math.asin(0.2)) True >>> gmpy2.asin() Traceback (most recent call last): File "", line 1, in TypeError: asin() takes exactly one argument (0 given) >>> gmpy2.asin("a") Traceback (most recent call last): File "", line 1, in TypeError: asin() argument type not supported >>> gmpy2.asin(0,0) Traceback (most recent call last): File "", line 1, in TypeError: asin() takes exactly one argument (2 given) >>> gmpy2.asin(0) mpfr('0.0') >>> gmpy2.asin(mpz(0)) mpfr('0.0') >>> gmpy2.asin(mpq(1,2)) mpfr('0.52359877559829893') >>> gmpy2.asin(F(1,2)) mpfr('0.52359877559829893') >>> gmpy2.asin(D("0.5")) mpfr('0.52359877559829893') >>> gmpy2.asin(mpfr("nan")) mpfr('nan') >>> gmpy2.asin(mpfr("inf")) mpfr('nan') >>> gmpy2.asin(mpfr("-inf")) mpfr('nan') >>> gmpy2.set_context(gmpy2.context(trap_invalid=True)) >>> gmpy2.asin(mpfr("nan")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in asin() >>> gmpy2.asin(mpfr("inf")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in asin() >>> gmpy2.asin(mpfr("-inf")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in asin() >>> gmpy2.set_context(gmpy2.context(precision=100)) >>> gmpy2.asin(mpfr("0.2")) mpfr('0.20135792079033079145512555221757',100) >>> gmpy2.get_context() context(precision=100, 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) Test atan --------- >>> gmpy2.set_context(gmpy2.context()) >>> _cmp(gmpy2.atan(mpfr("0.2")), math.atan(0.2)) True >>> _cmp(gmpy2.atan(mpfr("100")), math.atan(100)) True >>> gmpy2.atan() Traceback (most recent call last): File "", line 1, in TypeError: atan() takes exactly one argument (0 given) >>> gmpy2.atan("a") Traceback (most recent call last): File "", line 1, in TypeError: atan() argument type not supported >>> gmpy2.atan(0,0) Traceback (most recent call last): File "", line 1, in TypeError: atan() takes exactly one argument (2 given) >>> gmpy2.atan(0) mpfr('0.0') >>> gmpy2.atan(mpz(0)) mpfr('0.0') >>> gmpy2.atan(mpq(1,2)) mpfr('0.46364760900080609') >>> gmpy2.atan(F(1,2)) mpfr('0.46364760900080609') >>> gmpy2.atan(D("0.5")) mpfr('0.46364760900080609') >>> gmpy2.atan(mpfr("nan")) mpfr('nan') >>> gmpy2.atan(mpfr("inf")) mpfr('1.5707963267948966') >>> gmpy2.atan(mpfr("-inf")) mpfr('-1.5707963267948966') >>> gmpy2.set_context(gmpy2.context(trap_invalid=True)) >>> gmpy2.atan(mpfr("nan")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in atan() >>> gmpy2.set_context(gmpy2.context(precision=100)) >>> gmpy2.atan(mpfr("0.2")) mpfr('0.19739555984988075837004976519484',100) >>> gmpy2.get_context() context(precision=100, 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) Test atan2 ---------- >>> gmpy2.set_context(gmpy2.context()) >>> _cmp(gmpy2.atan2(1,2), math.atan2(1,2)) True >>> _cmp(gmpy2.atan2(-1,2), math.atan2(-1,2)) True >>> _cmp(gmpy2.atan2(1,-2), math.atan2(1,-2)) True >>> _cmp(gmpy2.atan2(-1,-2), math.atan2(-1,-2)) True >>> _cmp(gmpy2.atan2(float("0"),float("0")), math.atan2(float("0"),float("0"))) True >>> _cmp(gmpy2.atan2(float("-0"),float("0")), math.atan2(float("-0"),float("0"))) True >>> _cmp(gmpy2.atan2(float("0"),float("-0")), math.atan2(float("0"),float("-0"))) True >>> _cmp(gmpy2.atan2(float("-0"),float("-0")), math.atan2(float("-0"),float("-0"))) True >>> _cmp(gmpy2.atan2(float("inf"),float("inf")), math.atan2(float("inf"),float("inf"))) True >>> _cmp(gmpy2.atan2(float("-inf"),float("inf")), math.atan2(float("-inf"),float("inf"))) True >>> _cmp(gmpy2.atan2(float("inf"),float("-inf")), math.atan2(float("inf"),float("-inf"))) True >>> _cmp(gmpy2.atan2(float("-inf"),float("-inf")), math.atan2(float("-inf"),float("-inf"))) True Test cos -------- >>> gmpy2.set_context(gmpy2.context()) >>> _cmp(gmpy2.cos(mpfr("0.2")), math.cos(0.2)) True >>> _cmp(gmpy2.cos(mpfr("20")), math.cos(20)) True >>> _cmp(gmpy2.cos(mpfr("2000")), math.cos(2000)) True >>> gmpy2.cos() Traceback (most recent call last): File "", line 1, in TypeError: cos() takes exactly one argument (0 given) >>> gmpy2.cos("a") Traceback (most recent call last): File "", line 1, in TypeError: cos() argument type not supported >>> gmpy2.cos(0,0) Traceback (most recent call last): File "", line 1, in TypeError: cos() takes exactly one argument (2 given) >>> gmpy2.cos(0) mpfr('1.0') >>> gmpy2.cos(mpz(0)) mpfr('1.0') >>> gmpy2.cos(mpq(1,2)) mpfr('0.87758256189037276') >>> gmpy2.cos(F(1,2)) mpfr('0.87758256189037276') >>> gmpy2.cos(D("0.5")) mpfr('0.87758256189037276') >>> gmpy2.cos(mpfr("nan")) mpfr('nan') >>> gmpy2.cos(mpfr("inf")) mpfr('nan') >>> gmpy2.cos(mpfr("-inf")) mpfr('nan') >>> gmpy2.set_context(gmpy2.context(trap_invalid=True)) >>> gmpy2.cos(mpfr("nan")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in cos() >>> gmpy2.cos(mpfr("inf")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in cos() >>> gmpy2.cos(mpfr("-inf")) Traceback (most recent call last): File "", line 1, in InvalidOperationError: 'mpfr' invalid operation in cos() >>> gmpy2.set_context(gmpy2.context(precision=100)) >>> gmpy2.cos(mpfr("0.2")) mpfr('0.98006657784124163112419651674809',100) >>> gmpy2.get_context() context(precision=100, 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) Test cot -------- >>> gmpy2.set_context(gmpy2.context()) >>> _cmp(gmpy2.cot(mpfr("0.2")), 1/math.tan(0.2)) False >>> gmpy2.cot(mpfr("0.2")).as_integer_ratio() == (mpz(173569956714485), mpz(35184372088832)) True >>> (1/math.tan(0.2)).as_integer_ratio() == (5554238614863519, 1125899906842624) True >>> _cmp(gmpy2.cot(gmpy2.const_pi()), 1/math.tan(math.pi)) True >>> gmpy2.cot(1) mpfr('0.64209261593433076') >>> gmpy2.cot(float('0')) mpfr('inf') >>> gmpy2.cot(float('-0')) mpfr('-inf') >>> gmpy2.cot(mpfr('0')) mpfr('inf') >>> gmpy2.cot(mpfr('-0')) mpfr('-inf') Test csc -------- Test degrees ------------ Test radians ------------- Test sec -------- Test sin -------- Test sin_cos ------------ Test tan -------- Test acosh ---------- Test asinh ---------- Test atanh ---------- Test cosh --------- Test coth --------- Test csch --------- Test degrees ------------ Test radians ------------- Test sech --------- Test sinh --------- Test sinh_cosh -------------- Test tanh --------- gmpy2-2.0.7/test/test_mpfr_to_from_binary.txt0000666000000000000000000000233212204747346020105 0ustar rootrootTesting of gmpy2 mpfr to_binary and from_binary ----------------------------------------------- >>> import gmpy2 >>> from gmpy2 import mpfr,to_binary,from_binary Test ---- >>> x=mpfr("0");x==from_binary(to_binary(x)) True >>> x=mpfr("1");x==from_binary(to_binary(x)) True >>> x=mpfr("-1");x==from_binary(to_binary(x)) True >>> x=mpfr("inf");x==from_binary(to_binary(x)) True >>> x=mpfr("-inf");x==from_binary(to_binary(x)) True >>> x=mpfr("nan");gmpy2.is_nan(from_binary(to_binary(x))) True >>> x=mpfr(1.345);x==from_binary(to_binary(x)) True >>> x=mpfr("1.345e1000");x==from_binary(to_binary(x)) True >>> x=gmpy2.const_pi() >>> x.rc -1 >>> y=from_binary(to_binary(x)) >>> x==y True >>> y.rc -1 >>> gmpy2.get_context().precision=100 >>> x=gmpy2.const_pi();x==from_binary(to_binary(x)) True >>> gmpy2.get_context().precision=200 >>> x=mpfr(gmpy2.const_pi());x==from_binary(to_binary(x)) True >>> gmpy2.get_context().precision=200 >>> x=gmpy2.const_pi() >>> gmpy2.get_context().precision=300 >>> x=from_binary(to_binary(x)) >>> x.precision 200 >>> gmpy2.set_context(gmpy2.context()) gmpy2-2.0.7/test/test_mpfr_special.txt0000666000000000000000000000205212204747346016513 0ustar rootrootTest mpfr special functions --------------------------- >>> import gmpy2 >>> from gmpy2 import mpfr Test agm -------- Test ai ------- Test const_catalan ------------------ Test const_euler ---------------- Test const_log2 --------------- Test const_pi ------------- Test digamma ------------ Test eint --------- Test erf -------- Test erfc --------- Test factorial -------------- Test f2q -------- Test fma -------- Test fmod --------- Test fms -------- Test frac --------- Test frexp ---------- Test fsum --------- Test gamma ---------- Test j0 ------- Test j1 ------- Test jn ------- Test lgamma ----------- Test li2 -------- Test lngamma ------------ Test modf --------- Test mul_2exp ------------- Test next_above --------------- Test next_below --------------- Test next_toward ---------------- Test rec_sqrt ------------- Test reldiff ------------ Test remainder -------------- Test remquo ----------- Test root --------- Test sqrt --------- Test y0 ------- Test y1 ------- Test yn ------- Test zeta --------- gmpy2-2.0.7/test/test_mpfr_min_max.txt0000666000000000000000000000223012204747346016521 0ustar rootrootTesting of mpfr maxnum and minnum functions ------------------------------------------- >>> import gmpy2 >>> from gmpy2 import mpz, mpq, mpfr, maxnum, minnum >>> a = mpfr("12.34") >>> b = mpfr("45.67") >>> nan = mpfr("nan") >>> inf = mpfr("inf") >>> minf = mpfr("-inf") Test maxnum ----------- >>> maxnum(a,b) mpfr('45.670000000000002') >>> maxnum(b,a) mpfr('45.670000000000002') >>> maxnum(a,-b) mpfr('12.34') >>> maxnum(a, 123456) mpfr('123456.0') >>> maxnum(12345678901234567890, a) mpfr('1.2345678901234567e+19') >>> maxnum(0, -1) mpfr('0.0') >>> maxnum(1, inf) mpfr('inf') >>> maxnum(1, -inf) mpfr('1.0') >>> maxnum(nan, a) mpfr('12.34') >>> maxnum(a, nan) mpfr('12.34') >>> maxnum(nan, inf) mpfr('inf') >>> maxnum(nan, -inf) mpfr('-inf') >>> maxnum(nan, nan) mpfr('nan') Test minnum ----------- >>> minnum(a,b) mpfr('12.34') >>> minnum(b,a) mpfr('12.34') >>> minnum(1,inf) mpfr('1.0') >>> minnum(minf, a) mpfr('-inf') >>> minnum(nan, inf) mpfr('inf') >>> minnum(nan, nan) mpfr('nan') gmpy2-2.0.7/test/test_mpfr_exp_log.txt0000666000000000000000000000062212204747346016531 0ustar rootrootMPFR Functionality ================== >>> import gmpy2 as G >>> from gmpy2 import mpfr >>> a = mpz(123) >>> b = mpz(456) Test special functions ====================== Test cbrt --------- Test exp -------- Test exp10 ---------- Test exp2 --------- Test expm1 ---------- Test hypot ---------- Test log -------- Test log10 ---------- Test log1p ---------- Test log2 --------- gmpy2-2.0.7/test/test_mpfr_dec.txt0000666000000000000000000000515412204747346015634 0ustar rootrootInteroperability with Decimal ============================= >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr >>> from decimal import Decimal Test comparisons ---------------- Non-trivial comparions between mpfr and Decimal instances are only equal when the fractional can be written at 1/2**n. >>> mpfr('123.456') == Decimal('123.456') False >>> mpfr('123.5') == Decimal('123.5') True >>> mpq(123456,1000) == Decimal('123.456') True >>> mpz(123) == Decimal(123) True >>> mpfr('123.456') > Decimal('123.456') True >>> mpfr('123.456') < Decimal('123.456') False >>> Decimal('123.456') > mpfr('123.456') False >>> Decimal('123.456') < mpfr('123.456') True Test elementary operations -------------------------- >>> mpz(23) == Decimal(23) True >>> mpz(Decimal('123.456')) mpz(123) >>> mpq(Decimal('123.456')) mpq(15432,125) >>> mpfr(Decimal('123.456')) mpfr('123.456') >>> f = mpfr('123.456') >>> q = mpq('789123/1000') >>> z = mpz('234') >>> dd = Decimal('12.34') >>> fd = Decimal('123.456') >>> qd = Decimal('789.123') >>> zd = Decimal('234') >>> f+dd mpfr('135.79599999999999') >>> dd+f mpfr('135.79599999999999') >>> q+dd mpfr('801.46300000000008') >>> dd+q mpfr('801.46300000000008') >>> z+dd mpfr('246.34') >>> dd+z mpfr('246.34') >>> f-dd mpfr('111.116') >>> dd-f mpfr('-111.116') >>> q-dd mpfr('776.78300000000002') >>> dd-q mpfr('-776.78300000000002') >>> z-dd mpfr('221.66') >>> dd-z mpfr('-221.66') >>> f*dd mpfr('1523.44704') >>> dd*f mpfr('1523.44704') >>> q*dd mpfr('9737.7778200000012') >>> dd*q mpfr('9737.7778200000012') >>> z*dd mpfr('2887.5599999999999') >>> dd*z mpfr('2887.5599999999999') >>> f/dd mpfr('10.00453808752026') >>> dd/f mpfr('0.099954639709694135') >>> q/dd mpfr('63.948379254457052') >>> dd/q mpfr('0.015637612894314319') >>> z/dd mpfr('18.962722852512155') >>> dd/z mpfr('0.052735042735042738') >>> G.ceil(dd) mpfr('13.0') >>> G.floor(dd) mpfr('12.0') >>> G.trunc(dd) mpfr('12.0') >>> mpfr(dd).precision 53 >>> G.sin(Decimal("123.456")) mpfr('-0.80393736857282394') >>> G.sqrt(Decimal("123.456")) mpfr('11.111075555498667') >>> G.is_nan(Decimal("123.456")) False >>> G.is_nan(Decimal("NaN")) True >>> G.is_nan(Decimal("Inf")) False >>> G.is_inf(Decimal("Inf")) True >>> G.is_inf(Decimal("-Inf")) True gmpy2-2.0.7/test/test_mpfr.txt0000666000000000000000000002201512204747346015014 0ustar rootrootMPFR Functionality ================== Testing of mpfr functionality is split into multiple files. test_mpfr.txt Test basic functionality and stuff not covered anywhere else. test_mpfr_exp_log.txt Test exponentiation and logarithmic functions. test_mpfr_special.txt Test special functions test_mpfr_io.txt Test input/output and formating. test_mpfr_comp.txt Test comparisons. >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr >>> a = mpfr("12.34") >>> b = mpfr("45.67") >>> c = 12345678901234567890 Test elementary operations ========================== Test addition ------------- >>> a+1 mpfr('13.34') >>> a+1.0 mpfr('13.34') >>> a+mpz(1) mpfr('13.34') >>> a+mpq(1,1) mpfr('13.34') >>> 1+a mpfr('13.34') >>> 1.0+a mpfr('13.34') >>> mpz(1)+a mpfr('13.34') >>> mpq(1,1)+a mpfr('13.34') >>> a+b mpfr('58.010000000000005') >>> a+0 mpfr('12.34') >>> 0+a mpfr('12.34') >>> b+a mpfr('58.010000000000005') >>> a+'b' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for +: 'mpfr' and 'str' >>> 'b'+a Traceback (most recent call last): File "", line 1, in TypeError: Can't convert 'mpfr' object to str implicitly >>> a == 12.34 True >>> b == 45.67 True >>> a+b == 12.34+45.67 True Test subtraction ---------------- >>> a-1 mpfr('11.34') >>> a-1.0 mpfr('11.34') >>> a-(-1) mpfr('13.34') >>> a-(-1.0) mpfr('13.34') >>> a-b mpfr('-33.329999999999998') >>> b-a mpfr('33.329999999999998') >>> a-'b' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'mpfr' and 'str' >>> 'b'-a Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'str' and 'mpfr' >>> a-b==12.34-45.67 True Test multiplication ------------------- >>> a*b mpfr('563.56780000000003') >>> a*0 mpfr('0.0') >>> a*0.0 mpfr('0.0') >>> a*1 mpfr('12.34') >>> a*1.0 mpfr('12.34') >>> a*(-1.0) mpfr('-12.34') >>> 0*a mpfr('0.0') >>> 0.0*a mpfr('0.0') >>> 1*a mpfr('12.34') >>> 1.0*a mpfr('12.34') >>> a*b mpfr('563.56780000000003') >>> a*b==12.34*45.67 True Test division ------------- >>> a//b mpfr('0.0') >>> a/b mpfr('0.27019925552879348') >>> b//a mpfr('3.0') >>> b/a mpfr('3.7009724473257699') >>> a/b==12.34/45.67 True >>> a/0 mpfr('inf') >>> a/(-0.0) mpfr('-inf') >>> a/b==12.34/45.67 True Test modulo ----------- >>> a%1 mpfr('0.33999999999999986') >>> 12.34%1 0.33999999999999986 Test divmod ----------- >>> divmod(12.34, 45.67) (0.0, 12.34) >>> divmod(a,b) (mpfr('0.0'), mpfr('12.34')) >>> divmod(b,a) (mpfr('3.0'), mpfr('8.6500000000000021')) >>> divmod(45.67,12.34)==divmod(b,a) True Test pickle ----------- >>> import pickle >>> pickle.loads(pickle.dumps(a)) mpfr('12.34') >>> pickle.loads(pickle.dumps(mpfr("inf"))) mpfr('inf') >>> pickle.loads(pickle.dumps(mpfr("-inf"))) mpfr('-inf') >>> pickle.loads(pickle.dumps(mpfr("nan"))) mpfr('nan') >>> pickle.loads(pickle.dumps(mpfr(0))) mpfr('0.0') Test operations involving NaN/Inf --------------------------------- >>> a + float('Inf') mpfr('inf') >>> float('Inf') + a mpfr('inf') >>> a + float('-Inf') mpfr('-inf') >>> float('-Inf') + a mpfr('-inf') >>> a + float('nan') mpfr('nan') >>> float('nan') + a mpfr('nan') >>> a - float('Inf') mpfr('-inf') >>> float('Inf') - a mpfr('inf') >>> a - float('-Inf') mpfr('inf') >>> float('-Inf') - a mpfr('-inf') >>> a - float('nan') mpfr('nan') >>> float('nan') - a mpfr('nan') >>> a * float('Inf') mpfr('inf') >>> float('Inf') * a mpfr('inf') >>> a * float('-Inf') mpfr('-inf') >>> float('-Inf') * a mpfr('-inf') >>> -a * float('Inf') mpfr('-inf') >>> float('Inf') * -a mpfr('-inf') >>> -a * float('-Inf') mpfr('inf') >>> float('-Inf') * -a mpfr('inf') >>> a * float('nan') mpfr('nan') >>> float('nan') * a mpfr('nan') >>> mpfr(0) * float('Inf') mpfr('nan') >>> mpfr(0) * float('-Inf') mpfr('nan') >>> float('Inf') * mpfr(0) mpfr('nan') >>> float('-Inf') * mpfr(0) mpfr('nan') >>> a / float('Inf') mpfr('0.0') >>> -a / float('Inf') mpfr('-0.0') >>> float('Inf') / a mpfr('inf') >>> float('Inf') / -a mpfr('-inf') >>> a / float('-Inf') mpfr('-0.0') >>> -a / float('-Inf') mpfr('0.0') >>> float('-Inf') / a mpfr('-inf') >>> float('-Inf') / -a mpfr('inf') >>> a / float('nan') mpfr('nan') >>> float('nan') / a mpfr('nan') >>> float('nan') / mpfr(0) mpfr('nan') >>> float('nan') / mpfr(0) mpfr('nan') >>> a + mpfr('Inf') mpfr('inf') >>> mpfr('Inf') + a mpfr('inf') >>> a + mpfr('-Inf') mpfr('-inf') >>> mpfr('-Inf') + a mpfr('-inf') >>> a + mpfr('nan') mpfr('nan') >>> mpfr('nan') + a mpfr('nan') >>> a - mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') - a mpfr('inf') >>> a - mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') - a mpfr('-inf') >>> a - mpfr('nan') mpfr('nan') >>> mpfr('nan') - a mpfr('nan') >>> a * mpfr('Inf') mpfr('inf') >>> mpfr('Inf') * a mpfr('inf') >>> a * mpfr('-Inf') mpfr('-inf') >>> mpfr('-Inf') * a mpfr('-inf') >>> -a * mpfr('Inf') mpfr('-inf') >>> mpfr('Inf') * -a mpfr('-inf') >>> -a * mpfr('-Inf') mpfr('inf') >>> mpfr('-Inf') * -a mpfr('inf') >>> a * mpfr('nan') mpfr('nan') >>> mpfr('nan') * a mpfr('nan') >>> G.mpz(0) * mpfr('Inf') mpfr('nan') >>> G.mpz(0) * mpfr('-Inf') mpfr('nan') >>> mpfr('Inf') * mpfr(0) mpfr('nan') >>> mpfr('-Inf') * mpfr(0) mpfr('nan') >>> a / mpfr('Inf') mpfr('0.0') >>> -a / mpfr('Inf') mpfr('-0.0') >>> mpfr('Inf') / a mpfr('inf') >>> mpfr('Inf') / -a mpfr('-inf') >>> a / mpfr('-Inf') mpfr('-0.0') >>> -a / mpfr('-Inf') mpfr('0.0') >>> mpfr('-Inf') / a mpfr('-inf') >>> mpfr('-Inf') / -a mpfr('inf') >>> a / mpfr('nan') mpfr('nan') >>> mpfr('nan') / a mpfr('nan') >>> mpfr('nan') / mpfr(0) mpfr('nan') >>> mpfr('nan') / mpfr(0) mpfr('nan') >>> divmod(a, float('Inf')) (mpfr('0.0'), mpfr('12.34')) >>> divmod(a, float('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, float('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, float('-Inf')) (mpfr('0.0'), mpfr('-12.34')) >>> divmod(a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr(0), float('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(mpfr(0), float('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(mpfr(0), float('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(float('Inf'), mpfr(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('-Inf'), mpfr(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(float('nan'), mpfr(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(a, mpfr('Inf')) (mpfr('0.0'), mpfr('12.34')) >>> divmod(a, mpfr('-Inf')) (mpfr('-1.0'), mpfr('-inf')) >>> divmod(-a, mpfr('Inf')) (mpfr('-1.0'), mpfr('inf')) >>> divmod(-a, mpfr('-Inf')) (mpfr('0.0'), mpfr('-12.34')) >>> divmod(a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(-a, mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr(0), mpfr('Inf')) (mpfr('0.0'), mpfr('0.0')) >>> divmod(mpfr(0), mpfr('-Inf')) (mpfr('-0.0'), mpfr('-0.0')) >>> divmod(mpfr(0), mpfr('nan')) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), -a) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('Inf'), mpfr(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('-Inf'), mpfr(0)) (mpfr('nan'), mpfr('nan')) >>> divmod(mpfr('nan'), mpfr(0)) (mpfr('nan'), mpfr('nan')) gmpy2-2.0.7/test/test_mpc_trig.txt0000666000000000000000000000077212204747346015662 0ustar rootrootMPC Functionality ================= >>> import gmpy2 as G >>> from gmpy2 import mpc >>> a = mpz(123) >>> b = mpz(456) Test trigonometric operations ============================= Test acos --------- Test asin --------- Test atan --------- Test cos -------- Test sin -------- Test sin_cos ------------ Test tan -------- Test acosh ---------- Test asinh ---------- Test atanh ---------- Test cosh --------- Test sinh --------- Test sinh_cosh -------------- Test tanh --------- gmpy2-2.0.7/test/test_mpc_to_from_binary.txt0000666000000000000000000000360212204747346017721 0ustar rootrootTesting of gmpy2 mpc to_binary and from_binary ---------------------------------------------- >>> import gmpy2 >>> from gmpy2 import mpc,to_binary,from_binary Test ---- >>> x=mpc("0+0j");x==from_binary(to_binary(x)) True >>> x=mpc("1+0j");x==from_binary(to_binary(x)) True >>> x=mpc("-1+0j");x==from_binary(to_binary(x)) True >>> x=mpc("0+1j");x==from_binary(to_binary(x)) True >>> x=mpc("0-1j");x==from_binary(to_binary(x)) True >>> x=mpc("inf+0j");x==from_binary(to_binary(x)) True >>> x=mpc("0+infj");x==from_binary(to_binary(x)) True >>> x=mpc("inf-infj");x==from_binary(to_binary(x)) True >>> x=mpc("inf+nanj") >>> y=from_binary(to_binary(x)) >>> x.real==y.real True >>> gmpy2.is_nan(y.imag) True >>> x=mpc("-inf+0j");x==from_binary(to_binary(x)) True >>> x=mpc("0-infj");x==from_binary(to_binary(x)) True >>> x=mpc("-inf-infj");x==from_binary(to_binary(x)) True >>> x=mpc("-inf+nanj") >>> y=from_binary(to_binary(x)) >>> x.real==y.real True >>> gmpy2.is_nan(y.imag) True >>> x=mpc("nan+0j") >>> y=from_binary(to_binary(x)) >>> x.imag==y.imag True >>> gmpy2.is_nan(y.real) True >>> x=mpc("0+nanj") >>> y=from_binary(to_binary(x)) >>> x.real==y.real True >>> gmpy2.is_nan(y.imag) True >>> x=mpc("nan-infj") >>> y=from_binary(to_binary(x)) >>> x.imag==y.imag True >>> gmpy2.is_nan(y.real) True >>> x=mpc("nan+nanj") >>> y=from_binary(to_binary(x)) >>> gmpy2.is_nan(y.real) True >>> gmpy2.is_nan(y.imag) True >>> gmpy2.get_context().real_prec=100 >>> gmpy2.get_context().imag_prec=110 >>> from_binary(to_binary(mpc("1.3-4.7j"))) mpc('1.2999999999999999999999999999994-4.7000000000000000000000000000000025j',(100,110)) >>> gmpy2.set_context(gmpy2.context()) gmpy2-2.0.7/test/test_mpc_exp_log.txt0000666000000000000000000000041012204747346016337 0ustar rootrootMPFR Functionality ================== >>> import gmpy2 as G >>> from gmpy2 import mpfr >>> a = mpz(123) >>> b = mpz(456) Test special functions ====================== Test exp -------- Test log -------- Test sqrt --------- Test pow -------- gmpy2-2.0.7/test/test_mpc.txt0000666000000000000000000000764012204747346014636 0ustar rootrootTest mpc elementary operations ------------------------------ >>> import gmpy2 as G >>> from gmpy2 import mpz, mpq, mpfr, mpc >>> from fractions import Fraction as F >>> from decimal import Decimal as D >>> a = mpz(123) >>> b = mpz(456) >>> c = 12345678901234567890 >>> af = mpfr("12.34") >>> bf = mpfr("45.67") >>> aq = mpq(3,11) >>> bq = mpq(17,2) >>> aj = mpc(1+2j) >>> bj = mpc(4+5j) Test addition ------------- >>> aj + bj mpc('5.0+7.0j') >>> bj + aj mpc('5.0+7.0j') >>> aj + a mpc('124.0+2.0j') >>> a + aj mpc('124.0+2.0j') >>> aj + 1 mpc('2.0+2.0j') >>> 1 + aj mpc('2.0+2.0j') >>> aj + 0 mpc('1.0+2.0j') >>> 0 + aj mpc('1.0+2.0j') >>> -1 + aj mpc('0.0+2.0j') >>> aj - 1 mpc('0.0+2.0j') >>> aj + 1.2 == 2.2 + 2j True Test subtraction ---------------- >>> aj - bj mpc('-3.0-3.0j') >>> bj - aj mpc('3.0+3.0j') >>> aj - a mpc('-122.0+2.0j') >>> a - aj mpc('122.0-2.0j') >>> aj - 1 mpc('0.0+2.0j') >>> 1 - aj mpc('0.0-2.0j') >>> 0 - aj mpc('-1.0-2.0j') >>> aj - 0 mpc('1.0+2.0j') >>> aj - -1 mpc('2.0+2.0j') >>> -1 - aj mpc('-2.0-2.0j') >>> aj - 1.2 == (1+2j) - 1.2 True Test multiplication ------------------- >>> aj * bj mpc('-6.0+13.0j') >>> bj * aj mpc('-6.0+13.0j') >>> aj * a mpc('123.0+246.0j') >>> a * aj mpc('123.0+246.0j') >>> aj * -1 mpc('-1.0-2.0j') >>> aj * (0.0+1j) mpc('-2.0+1.0j') Test division ------------- >>> aj / bj mpc('0.34146341463414637+0.073170731707317069j') >>> aj // bj Traceback (most recent call last): File "", line 1, in TypeError: can't take floor of complex number. >>> aj / a mpc('0.008130081300813009+0.016260162601626018j') >>> a / aj mpc('24.600000000000001-49.200000000000003j') >>> aj / 0 mpc('inf+infj') Test modulo ----------- >>> aj % bj Traceback (most recent call last): File "", line 1, in TypeError: can't mod complex numbers >>> aj % a Traceback (most recent call last): File "", line 1, in TypeError: can't mod complex numbers >>> a % aj Traceback (most recent call last): File "", line 1, in TypeError: can't mod complex numbers >>> divmod(aj, bj) Traceback (most recent call last): File "", line 1, in TypeError: can't take floor or mod of complex number. Test operations involving NaN/Inf --------------------------------- >>> aj + float('inf') mpc('inf+2.0j') >>> aj + float('-inf') mpc('-inf+2.0j') >>> aj + float('nan') mpc('nan+2.0j') >>> float('inf') - aj mpc('inf-2.0j') >>> aj - float('inf') mpc('-inf+2.0j') >>> aj - float('-inf') mpc('inf+2.0j') >>> aj - float('nan') mpc('nan+2.0j') >>> aj * float('inf') mpc('inf+infj') >>> aj * float('-inf') mpc('-inf-infj') >>> aj * float('nan') mpc('nan+nanj') >>> mpc(0,0) * float('inf') mpc('nan+nanj') >>> mpc(0,0) * float('-inf') mpc('nan+nanj') >>> mpc(0,0) * float('nan') mpc('nan+nanj') >>> aj / float('inf') mpc('0.0+0.0j') >>> aj / float('-inf') mpc('-0.0-0.0j') >>> float('inf') / aj mpc('inf-infj') >>> float('-inf') / aj mpc('-inf+infj') Test is_XXX ----------- >>> G.is_zero(mpc("0+0j")) True >>> G.is_zero(mpc("1+0j")) False >>> G.is_zero(mpc("1+1j")) False >>> G.is_zero(mpc("0+1j")) False >>> G.is_nan(mpc("nan+1j")) True >>> G.is_nan(mpc("1+nanj")) True >>> G.is_nan(mpc("nan+nanj")) True >>> G.is_nan(mpc("1+1j")) False >>> G.is_infinite(mpc("inf+1j")) True >>> G.is_infinite(mpc("-inf+1j")) True >>> G.is_infinite(mpc("1+infj")) True >>> G.is_infinite(mpc("1-infj")) True >>> G.is_infinite(mpc("inf-infj")) True >>> G.is_infinite(mpc("1+1j")) False >>> G.is_finite(mpc("0+0j")) True >>> G.is_finite(mpc("nan+0j")) False >>> G.is_finite(mpc("0+nanj")) False >>> G.is_finite(mpc("0+infj")) False >>> G.is_finite(mpc("inf+3j")) False gmpy2-2.0.7/test/test_misc.txt0000666000000000000000000000143212564432250014775 0ustar rootrootMiscellaneous Functions ----------------------- >>> import gmpy2 >>> gmpy2.version() '2.0.7' >>> gmpy2.mp_limbsize() in (32,64) True >>> gmpy2.mp_version().split()[0] in ['GMP', 'MPIR'] True >>> check_gmp = gmpy2.mp_version().startswith('GMP') and '5.0.0' <= gmpy2.mp_version().split()[1] >>> check_mpir = gmpy2.mp_version().startswith('MPIR') and '2.4.0' <= gmpy2.mp_version().split()[1] >>> check_gmp or check_mpir True >>> gmpy2.mpfr_version() and gmpy2.mpfr_version().startswith('MPFR') True >>> gmpy2.mpfr_version() and '3.1.0' <= gmpy2.mpfr_version().split()[1] True >>> gmpy2.mpc_version() and gmpy2.mpc_version().startswith('MPC') True >>> gmpy2.mpc_version() and '1.0' <= gmpy2.mpc_version().split()[1] True gmpy2-2.0.7/test/test_context.txt0000666000000000000000000002653312204747346015545 0ustar rootrootTest context handling --------------------- >>> import gmpy2 >>> from gmpy2 import mpfr,mpc,get_context,set_context,ieee,context,local_context Test ieee() ----------- >>> ieee(32) context(precision=24, real_prec=Default, imag_prec=Default, round=RoundToNearest, real_round=Default, imag_round=Default, emax=128, emin=-148, subnormalize=True, 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) >>> ieee(64) context(precision=53, real_prec=Default, imag_prec=Default, round=RoundToNearest, real_round=Default, imag_round=Default, emax=1024, emin=-1073, subnormalize=True, 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) >>> ieee(128) context(precision=113, real_prec=Default, imag_prec=Default, round=RoundToNearest, real_round=Default, imag_round=Default, emax=16384, emin=-16493, subnormalize=True, 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) >>> set_context(ieee(32)) >>> gmpy2.const_pi().digits(2) ('110010010000111111011011', 2, 24) >>> set_context(ieee(64)) >>> gmpy2.const_pi().digits(2) ('11001001000011111101101010100010001000010110100011000', 2, 53) >>> set_context(ieee(128)) >>> gmpy2.const_pi().digits(2) ('11001001000011111101101010100010001000010110100011000010001101001100010011000110011000101000101110000000110111000', 2, 113) Test context() -------------- >>> 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) >>> context(precision=100) context(precision=100, 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) >>> context(real_prec=100) context(precision=53, real_prec=100, 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) >>> 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=False, trap_invalid=False, invalid=False, trap_erange=False, erange=False, trap_divzero=False, divzero=False, trap_expbound=False, allow_complex=False) Test get_context() ------------------ >>> set_context(context()) >>> 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) >>> a=get_context() >>> a.precision=100 >>> a context(precision=100, 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) >>> get_context() context(precision=100, 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) >>> b=a.copy() >>> b.precision=200 >>> b 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=False, trap_invalid=False, invalid=False, trap_erange=False, erange=False, trap_divzero=False, divzero=False, trap_expbound=False, allow_complex=False) >>> a context(precision=100, 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) >>> get_context() context(precision=100, 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) Test local_context() -------------------- >>> set_context(context()) >>> with local_context() as ctx: ... print(ctx.precision) ... ctx.precision+=20 ... print(ctx.precision) ... 53 73 >>> 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) >>> with local_context(ieee(64)) as ctx: ... print(ctx) ... context(precision=53, real_prec=Default, imag_prec=Default, round=RoundToNearest, real_round=Default, imag_round=Default, emax=1024, emin=-1073, subnormalize=True, 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) >>> 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) >>> with get_context() as ctx: ... print(ctx.precision) ... ctx.precision+=100 ... print(ctx.precision) ... 53 153 >>> 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) >>> with local_context(precision=200) as ctx: ... print(ctx.precision) ... ctx.precision+=100 ... print(ctx.precision) ... 200 300 >>> 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) gmpy2-2.0.7/test/runtests.py0000666000000000000000000000721512341422132014477 0ustar rootrootfrom __future__ import print_function, division import sys import doctest import gmpy2 # ***************************************************************************** # Test strategy # ------------- # Tests are divided into two different categories: # # 1) The 'txt' files contain doctest style tests. These tests should cover # basic functionality for all functions/types. # 2) The 'py' files contain Python code that perform extensive tests, but # may not test every function. # # If run by a debug build of Python, the test suite can be repeated multiple # times to search for memory leaks. # # NOTE: IF THE LAST TEST IN A BLOCK OF TESTS GENERATES AN EXCEPTION, THE # REFERENCE COUNTING IN A DEBUG BUILD GETS CONFUSED. ALWAYS ENSURE THAT # AT LEAST ONE VALID TEST IS PERFORMED AFTER AN EXCEPTION IS RAISED! # # ***************************************************************************** # Check if this is a debug build of Python. try: sys.gettotalrefcount() debug = True except AttributeError: debug = False # Change repeat to the number of times to repeat each test. Combined with a # debug build, this can help identify memory leaks. if debug: try: repeat = abs(int(sys.argv[1])) except: repeat = 1 else: repeat = 1 print() print("Unit tests for gmpy2 {0} with Python {1}".format(gmpy2.version(), sys.version.split()[0])) print(" Mutliple-precision library: {0}".format(gmpy2.mp_version())) print(" Floating-point library: {0}".format(gmpy2.mpfr_version())) print(" Complex library: {0}".format(gmpy2.mpc_version())) print(" Caching Values: (Cache size) {0}".format(gmpy2.get_cache()[0])) print(" Caching Values: (Size in limbs) {0}".format(gmpy2.get_cache()[1])) print() if sys.version.startswith('3.1'): print("Due to differences in formatting of exceptions and Python 3.x, there") print("will be test failures for exception handling when the tests are run") print("with Python 3.1. The doctest module in Python 3.2 and later does not") print("have this issue.") print() input("Press ENTER to continue.. ") print() # The following tests should pass on all builds. mpz_doctests = ["test_mpz.txt", "test_mpz_io.txt", "test_mpz_pack_unpack.txt", "test_mpz_to_from_binary.txt"] mpq_doctests = ["test_mpq.txt", "test_mpq_to_from_binary.txt"] # The following tests require MPFR support. mpfr_doctests = ["test_mpfr.txt", "test_mpfr_trig.txt", "test_mpfr_min_max.txt", "test_mpfr_to_from_binary.txt", "test_context.txt"] # The following tests require MPC support. mpc_doctests = ["test_mpc.txt", "test_mpc_to_from_binary.txt"] # The following tests will only pass on Python 3.2+. py32_doctests = ["test_py32_hash.txt"] failed = 0 attempted = 0 all_doctests = ["test_misc.txt"] + mpz_doctests + mpq_doctests if gmpy2.mpfr_version(): all_doctests += mpfr_doctests if gmpy2.mpc_version(): all_doctests += mpc_doctests if sys.version >= "3.2": all_doctests += py32_doctests for test in sorted(all_doctests): for r in range(repeat): result = doctest.testfile(test, globs=globals(), optionflags=doctest.IGNORE_EXCEPTION_DETAIL) print("Results for: {0:24}".format(test.split(".")[0]), end="") print(" Attempted: {1:4d} Failed: {0:4d}".format(*result), end="") if debug: print(" RefCount: {0:6d}".format(sys.gettotalrefcount())) else: print() failed += result[0] attempted += result[1] print() print(" Summary - Attempted: {0:4d} Failed: {1:4d}".format(attempted, failed)) if failed: sys.exit(1) else: sys.exit(0) gmpy2-2.0.7/test/gmpy_test.py0000666000000000000000000000055412204747346014641 0ustar rootrootfrom __future__ import print_function import sys print("\nImportant test information!\n") print("Please use 'test/runtests.py' to run the new test suite.\n") if sys.version_info[0] == 3: print("Please use 'test3/gmpy_test.py' to run legacy tests with Python 3.x.\n") else: print("Please use 'test2/gmpy_test.py' to run legacy tests with Python 2.x.\n") gmpy2-2.0.7/src/0000755000000000000000000000000012567136721012055 5ustar rootrootgmpy2-2.0.7/src/py3intcompat.c0000666000000000000000000002204612204747346014662 0ustar rootroot/* This file contains source code copied from Python's source code. "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Python Software Foundation; All Rights Reserved" For the full text of the license, see http://www.python.org/psf/license/. ======================================= This file provides support to older versions of Python for several new C API functions introduced in Python 2.7, Python 3.0, or Python 3.2. PyLong_AsLongAndOverflow accepts a PyLong object and either returns a C long or sets an overflow flag. A PyInt is also accepted on Python 2.x so the macro PyIntOrLong_Check() is defined in gmpy.c to accept either type of integer. Actually, PyLong_AsLongAndOverflow will try to convert almost any object to an integer if it is not already a PyInt or PyLong. If you don't verify the object is either a PyInt or PyLong first, you MUST check for an error in the return value. PyLong_AsLongLongAndOverflow behaves similarly except it returns a C long long. Example ------- #if PY_MAJOR_VERSION == 3 #define PyIntOrLong_Check(op) PyLong_Check(op) #else #define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op)) #endif #include "py3intcompat.c" ...... long temp; int overflow; ...... if(PyIntOrLong_Check(obj)) { temp = PyLong_AsLongAndOverflow(obj, &overflow); if(overflow) { obj is a PyLong that won't fit into a C long. } else { Process a PyInt or a PyLong that will fit into a C long. } } ...... # Don't check the object type first. temp = PyLong_AsLongAndOverflow(obj, &overflow); if (temp == -1 && PyErr_Occurred()) { raise an error message } else if (overflow) { obj is a PyLong that won't fit into a C long. } else { Process a PyInt or a PyLong that will fit into a C long. } */ #include "longintrepr.h" /* Get a C long int from a long int object. Returns -1 and sets an error condition if overflow occurs. */ #if (PY_VERSION_HEX < 0x02070000) #ifndef PyLong_SHIFT #define PyLong_SHIFT SHIFT #endif #ifndef PyLong_MASK #define PyLong_MASK MASK #endif #define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN) typedef short sdigit; static long PyLong_AsLongAndOverflow(PyObject *vv, int *overflow) { /* This version by Tim Peters */ register PyLongObject *v; unsigned long x, prev; long res; Py_ssize_t i; int sign; int do_decref = 0; /* if nb_int was called */ *overflow = 0; if (vv == NULL) { PyErr_BadInternalCall(); return -1; } if(PyInt_Check(vv)) return PyInt_AsLong(vv); if (!PyLong_Check(vv)) { PyNumberMethods *nb; nb = vv->ob_type->tp_as_number; if (nb == NULL || nb->nb_int == NULL) { PyErr_SetString(PyExc_TypeError, "an integer is required"); return -1; } vv = (*nb->nb_int) (vv); if (vv == NULL) return -1; do_decref = 1; if(PyInt_Check(vv)) { res = PyInt_AsLong(vv); goto exit; } if (!PyLong_Check(vv)) { Py_DECREF(vv); PyErr_SetString(PyExc_TypeError, "nb_int should return int object"); return -1; } } res = -1; v = (PyLongObject *)vv; i = Py_SIZE(v); switch (i) { case -1: res = -(sdigit)v->ob_digit[0]; break; case 0: res = 0; break; case 1: res = v->ob_digit[0]; break; default: sign = 1; x = 0; if (i < 0) { sign = -1; i = -(i); } while (--i >= 0) { prev = x; x = (x << PyLong_SHIFT) + v->ob_digit[i]; if ((x >> PyLong_SHIFT) != prev) { *overflow = Py_SIZE(v) > 0 ? 1 : -1; goto exit; } } /* Haven't lost any bits, but casting to long requires extra care * (see comment above). */ if (x <= (unsigned long)LONG_MAX) { res = (long)x * sign; } else if (sign < 0 && x == PY_ABS_LONG_MIN) { res = LONG_MIN; } else { *overflow = sign; /* res is already set to -1 */ } } exit: if (do_decref) { Py_DECREF(vv); } return res; } #endif /* if (PY_VERSION_HEX < 0x02070000) */ #ifdef _WIN64 #if HAVE_LONG_LONG #if (PY_VERSION_HEX < 0x02070000) #define PY_ABS_LLONG_MIN (0-(unsigned PY_LONG_LONG)PY_LLONG_MIN) static PY_LONG_LONG PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow) { /* This version by Tim Peters */ register PyLongObject *v; unsigned PY_LONG_LONG x, prev; PY_LONG_LONG res; Py_ssize_t i; int sign; int do_decref = 0; /* if nb_int was called */ *overflow = 0; if (vv == NULL) { PyErr_BadInternalCall(); return -1; } if(PyInt_Check(vv)) return PyInt_AsLong(vv); if (!PyLong_Check(vv)) { PyNumberMethods *nb; nb = vv->ob_type->tp_as_number; if (nb == NULL || nb->nb_int == NULL) { PyErr_SetString(PyExc_TypeError, "an integer is required"); return -1; } vv = (*nb->nb_int) (vv); if (vv == NULL) return -1; do_decref = 1; if(PyInt_Check(vv)) { res = PyInt_AsLong(vv); goto exit; } if (!PyLong_Check(vv)) { Py_DECREF(vv); PyErr_SetString(PyExc_TypeError, "nb_int should return int object"); return -1; } } res = -1; v = (PyLongObject *)vv; i = Py_SIZE(v); switch (i) { case -1: res = -(sdigit)v->ob_digit[0]; break; case 0: res = 0; break; case 1: res = v->ob_digit[0]; break; default: sign = 1; x = 0; if (i < 0) { sign = -1; i = -(i); } while (--i >= 0) { prev = x; x = (x << PyLong_SHIFT) + v->ob_digit[i]; if ((x >> PyLong_SHIFT) != prev) { *overflow = sign; goto exit; } } /* Haven't lost any bits, but casting to long requires extra * care (see comment above). */ if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) { res = (PY_LONG_LONG)x * sign; } else if (sign < 0 && x == PY_ABS_LLONG_MIN) { res = PY_LLONG_MIN; } else { *overflow = sign; /* res is already set to -1 */ } } exit: if (do_decref) { Py_DECREF(vv); } return res; } #endif /* if (PY_VERSION_HEX < 0x02070000) */ #if ((PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION < 2)) #define PY_ABS_LLONG_MIN (0-(unsigned PY_LONG_LONG)PY_LLONG_MIN) static PY_LONG_LONG PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow) { /* This version by Tim Peters */ register PyLongObject *v; unsigned PY_LONG_LONG x, prev; PY_LONG_LONG res; Py_ssize_t i; int sign; int do_decref = 0; /* if nb_int was called */ *overflow = 0; if (vv == NULL) { PyErr_BadInternalCall(); return -1; } if (!PyLong_Check(vv)) { PyNumberMethods *nb; nb = vv->ob_type->tp_as_number; if (nb == NULL || nb->nb_int == NULL) { PyErr_SetString(PyExc_TypeError, "an integer is required"); return -1; } vv = (*nb->nb_int) (vv); if (vv == NULL) return -1; do_decref = 1; if (!PyLong_Check(vv)) { Py_DECREF(vv); PyErr_SetString(PyExc_TypeError, "nb_int should return int object"); return -1; } } res = -1; v = (PyLongObject *)vv; i = Py_SIZE(v); switch (i) { case -1: res = -(sdigit)v->ob_digit[0]; break; case 0: res = 0; break; case 1: res = v->ob_digit[0]; break; default: sign = 1; x = 0; if (i < 0) { sign = -1; i = -(i); } while (--i >= 0) { prev = x; x = (x << PyLong_SHIFT) + v->ob_digit[i]; if ((x >> PyLong_SHIFT) != prev) { *overflow = sign; goto exit; } } /* Haven't lost any bits, but casting to long requires extra * care (see comment above). */ if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) { res = (PY_LONG_LONG)x * sign; } else if (sign < 0 && x == PY_ABS_LLONG_MIN) { res = PY_LLONG_MIN; } else { *overflow = sign; /* res is already set to -1 */ } } exit: if (do_decref) { Py_DECREF(vv); } return res; } #endif /* if (PY_VERSION_HEX < 0x03020000) */ #endif /* if HAVE_LONG_LONG */ #endif /* ifdef _WIN64 */ gmpy2-2.0.7/src/mpz_pylong.c0000666000000000000000000001613512204747346014430 0ustar rootroot/* mpz <-> pylong conversion and "pythonhash" for mpz * * Originally written for sage (http://sagemath.org) by Gonzalo Tornari­a * . If you improve on these functions, please * contribute them back to sage by posting to sage-devel@googlegroups.com * or by sending an email to the original author. * * Integration with gmpy2 by Case Van Horsen . * * License: LGPL v2 or later * */ /* This file created by merging mpn_pylong and mpz_pylong. Permission * was granted by the original author to make this code available under * the LGPLv2+ license. */ /* This code assumes that SHIFT < GMP_NUMB_BITS */ #if PyLong_SHIFT >= GMP_NUMB_BITS #error "Python limb larger than GMP limb !!!" #endif #ifndef ABS #define ABS(a) (((a) < 0) ? -(a) : (a)) #endif /* Use these "portable" (I hope) sizebits functions. * We could implement this in terms of count_leading_zeros from GMP, * but it is not exported! */ static const unsigned char __sizebits_tab[128] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }; #if GMP_LIMB_BITS > 64 #error "word size > 64 unsupported" #endif static inline size_t mpn_sizebits(mp_ptr up, size_t un) { size_t cnt; mp_limb_t x; if (un==0) return 0; cnt = (un - 1) * GMP_NUMB_BITS; x = up[un - 1]; #if GMP_LIMB_BITS > 32 if ((x >> 32) != 0) { x >>= 32; cnt += 32; } #endif #if GMP_LIMB_BITS > 16 if ((x >> 16) != 0) { x >>= 16; cnt += 16; } #endif #if GMP_LIMB_BITS > 8 if ((x >> 8) != 0) { x >>= 8; cnt += 8; } #endif return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]); } static inline size_t pylong_sizebits(digit *digits, size_t size) { size_t cnt; digit x; if (size==0) return 0; cnt = (size - 1) * PyLong_SHIFT; x = digits[size - 1]; #if PyLong_SHIFT > 32 if ((x >> 32) != 0) { x >>= 32; cnt += 32; } #endif #if PyLong_SHIFT > 16 if ((x >> 16) != 0) { x >>= 16; cnt += 16; } #endif #if PyLong_SHIFT > 8 if ((x >> 8) != 0) { x >>= 8; cnt += 8; } #endif return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]); } /* mpn -> pylong conversion */ size_t mpn_pylong_size (mp_ptr up, size_t un) { return (mpn_sizebits(up, un) + PyLong_SHIFT - 1) / PyLong_SHIFT; } /* this is based from GMP code in mpn/get_str.c */ /* Assume digits points to a chunk of size size * where size >= mpn_pylong_size(up, un) */ void mpn_get_pylong (digit *digits, size_t size, mp_ptr up, size_t un) { mp_limb_t n1, n0; size_t i; ssize_t bit_pos; /* point past the allocated chunk */ digit * s = digits + size; /* input length 0 is special ! */ if (un == 0) { while (size) digits[--size]=0; return; } i = un - 1; n1 = up[i]; bit_pos = size * PyLong_SHIFT - i * GMP_NUMB_BITS; for (;;) { bit_pos -= PyLong_SHIFT; while (bit_pos >= 0) { *--s = (n1 >> bit_pos) & PyLong_MASK; bit_pos -= PyLong_SHIFT; } if (i == 0) break; n0 = (n1 << -bit_pos) & PyLong_MASK; n1 = up[--i]; bit_pos += GMP_NUMB_BITS; *--s = (digit)(n0 | (n1 >> bit_pos)); } } /* pylong -> mpn conversion */ size_t mpn_size_from_pylong (digit *digits, size_t size) { return (pylong_sizebits(digits, size) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS; } void mpn_set_pylong (mp_ptr up, size_t un, digit *digits, size_t size) { mp_limb_t n1, d; size_t i; ssize_t bit_pos; /* point past the allocated chunk */ digit * s = digits + size; /* input length 0 is special ! */ if (size == 0) { while (un) up[--un]=0; return; } i = un - 1; n1 = 0; bit_pos = size * PyLong_SHIFT - i * GMP_NUMB_BITS; for (;;) { bit_pos -= PyLong_SHIFT; while (bit_pos >= 0) { d = (mp_limb_t) *--s; n1 |= (d << bit_pos) & GMP_NUMB_MASK; bit_pos -= PyLong_SHIFT; } if (i == 0) break; d = (mp_limb_t) *--s; /* add some high bits of d; maybe none if bit_pos=-SHIFT */ up[i--] = n1 | (d & PyLong_MASK) >> -bit_pos; bit_pos += GMP_NUMB_BITS; n1 = (d << bit_pos) & GMP_NUMB_MASK; } up[0] = n1; } /************************************************************/ /* Hashing functions */ #define LONG_BIT_SHIFT (8*sizeof(long) - PyLong_SHIFT) /* * for an mpz, this number has to be multiplied by the sign * also remember to catch -1 and map it to -2 ! */ long mpn_pythonhash (mp_ptr up, mp_size_t un) { mp_limb_t n1, n0; mp_size_t i; ssize_t bit_pos; long x = 0; /* input length 0 is special ! */ if (un == 0) return 0; i = un - 1; n1 = up[i]; { size_t bits; bits = mpn_sizebits(up, un) + PyLong_SHIFT - 1; bits -= bits % PyLong_SHIFT; /* position of the MSW in base 2^SHIFT, counted from the MSW in * the GMP representation (in base 2^GMP_NUMB_BITS) */ bit_pos = bits - i * GMP_NUMB_BITS; } for (;;) { while (bit_pos >= 0) { /* Force a native long #-bits (32 or 64) circular shift */ x = ((x << PyLong_SHIFT) & ~(long)PyLong_MASK) | ((x >> LONG_BIT_SHIFT) & (long)PyLong_MASK); /* Shifting to the right by more than wordsize bits actually shifts by (wordsize % 32) bits -- which is *not* the intended behavior here. */ if (bit_pos <= 8*sizeof(mp_limb_t)) x += (n1 >> bit_pos) & (long)PyLong_MASK; bit_pos -= PyLong_SHIFT; } i--; if (i < 0) break; n0 = (n1 << -bit_pos) & (long)PyLong_MASK; n1 = up[i]; bit_pos += GMP_NUMB_BITS; /* Force a native long #-bits (32 or 64) circular shift */ x = ((x << PyLong_SHIFT) & ~(long)PyLong_MASK) | ((x >> LONG_BIT_SHIFT) & (long)PyLong_MASK); x += (long)(n0 | (n1 >> bit_pos)); bit_pos -= PyLong_SHIFT; } return x; } /* mpz python hash */ long mpz_pythonhash(mpz_srcptr z) { long x = mpn_pythonhash(z->_mp_d, ABS(z->_mp_size)); if (z->_mp_size < 0) x = -x; if (x == -1) x = -2; return x; } /* mpz -> pylong conversion */ PyObject * mpz_get_PyLong(mpz_srcptr z) { size_t size = mpn_pylong_size(z->_mp_d, ABS(z->_mp_size)); PyLongObject *lptr = PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size); if (lptr != NULL) { mpn_get_pylong(lptr->ob_digit, size, z->_mp_d, ABS(z->_mp_size)); if (z->_mp_size < 0) Py_SIZE(lptr) = -(Py_SIZE(lptr)); } return (PyObject *) lptr; } /* pylong -> mpz conversion */ int mpz_set_PyIntOrLong(mpz_ptr z, PyObject * lsrc) { register PyLongObject * lptr = (PyLongObject *) lsrc; ssize_t size; #ifdef PY2 if (PyInt_Check(lsrc)) { mpz_set_si(z, PyInt_AS_LONG(lsrc)); return 1; } #endif if (lptr==NULL || !PyLong_Check(lptr)) { PyErr_BadInternalCall(); return -1; } size = (ssize_t)mpn_size_from_pylong(lptr->ob_digit, ABS(Py_SIZE(lptr))); if (z->_mp_alloc < size) _mpz_realloc (z, (mp_size_t)size); mpn_set_pylong(z->_mp_d, size, lptr->ob_digit, ABS(Py_SIZE(lptr))); z->_mp_size = (int)(Py_SIZE(lptr) < 0 ? -size : size); return (int)size; } gmpy2-2.0.7/src/gmpy_xmpz_inplace.h0000666000000000000000000000563412542614506015762 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_xmpz_inplace.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_XMPZ_INPLACE_H #define GMPY_XMPZ_INPLACE_H #ifdef __cplusplus extern "C" { #endif static PyObject * Pyxmpz_inplace_add(PyObject *a, PyObject *b); static PyObject * Pyxmpz_inplace_sub(PyObject *a, PyObject *b); static PyObject * Pyxmpz_inplace_mul(PyObject *a, PyObject *b); static PyObject * Pyxmpz_inplace_floordiv(PyObject *a, PyObject *b); static PyObject * Pyxmpz_inplace_rem(PyObject *a, PyObject *b); static PyObject * Pyxmpz_inplace_rshift(PyObject *a, PyObject *b); static PyObject * Pyxmpz_inplace_lshift(PyObject *a, PyObject *b); static PyObject * Pyxmpz_inplace_pow(PyObject *in_b, PyObject *in_e, PyObject *in_m); static PyObject * Pyxmpz_inplace_and(PyObject *self, PyObject *other); static PyObject * Pyxmpz_inplace_xor(PyObject *self, PyObject *other); static PyObject * Pyxmpz_inplace_ior(PyObject *self, PyObject *other); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_xmpz_inplace.c0000666000000000000000000002730512542614506015754 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_xmpz_inplace.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Provides inplace mutating operations for xmpz. */ #include /* Inplace xmpz addition. */ static PyObject * Pyxmpz_inplace_add(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; /* Try to make mpz + small_int faster */ if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_add(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si >= 0) { mpz_add_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else { mpz_sub_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { mpz_add(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace mpz subtraction. */ static PyObject * Pyxmpz_inplace_sub(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_sub(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si >= 0) { mpz_sub_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else { mpz_add_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { mpz_sub(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace xmpz multiplication. */ static PyObject * Pyxmpz_inplace_mul(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_mul(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else { mpz_mul_si(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { mpz_mul(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; } /* Pympany_floordiv follows the // semantics from Python 3.x. The result is * an mpz when the arguments are mpz or mpq, but the result is an mpf when * the arguments are mpf. */ static PyObject * Pyxmpz_inplace_floordiv(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_q(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } else if(temp_si > 0) { mpz_fdiv_q_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else { mpz_cdiv_q_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); mpz_neg(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a)); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pyxmpz_AS_MPZ(b)) == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } mpz_fdiv_q(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace xmpz remainder. */ static PyObject * Pyxmpz_inplace_rem(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_r(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si > 0) { mpz_fdiv_r_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else if(temp_si == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } else { mpz_cdiv_r_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { if(mpz_sgn(Pyxmpz_AS_MPZ(b)) == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } mpz_fdiv_r(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace xmpz rshift. */ static PyObject * Pyxmpz_inplace_rshift(PyObject *a, PyObject *b) { mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { OVERFLOW_ERROR("outrageous shift count"); return NULL; } else if(temp_si >= 0) { mpz_fdiv_q_2exp(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); Py_INCREF(a); return a; } else { VALUE_ERROR("negative shift count"); return NULL; } } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pyxmpz_AS_MPZ(b)) < 0) { VALUE_ERROR("negative shift count"); return NULL; } if (!mpz_fits_si_p(Pyxmpz_AS_MPZ(b))) { OVERFLOW_ERROR("outrageous shift count"); return NULL; } temp_si = mpz_get_si(Pyxmpz_AS_MPZ(b)); mpz_fdiv_q_2exp(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace xmpz lshift. */ static PyObject * Pyxmpz_inplace_lshift(PyObject *a, PyObject *b) { mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { OVERFLOW_ERROR("outrageous shift count"); return NULL; } else if(temp_si >= 0) { mpz_mul_2exp(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else { VALUE_ERROR("negative shift count"); return NULL; } } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pyxmpz_AS_MPZ(b)) < 0) { VALUE_ERROR("negative shift count"); return NULL; } if (!mpz_fits_si_p(Pyxmpz_AS_MPZ(b))) { OVERFLOW_ERROR("outrageous shift count"); return NULL; } temp_si = mpz_get_si(Pyxmpz_AS_MPZ(b)); mpz_mul_2exp(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace xmpz_pow. */ static PyObject * Pyxmpz_inplace_pow(PyObject *in_b, PyObject *in_e, PyObject *in_m) { PympzObject *e = 0; mpir_ui el; if (!Pyxmpz_Check(in_b)) { PyErr_SetString(PyExc_TypeError, "base must be an Integer"); return NULL; } if (in_m != Py_None) { SYSTEM_ERROR("modulo not expected"); return NULL; } e = Pympz_From_Integer(in_e); if (!e) { TYPE_ERROR("expected an integer exponent"); return NULL; } if (mpz_sgn(e->z) < 0) { VALUE_ERROR("xmpz.pow with negative power"); Py_DECREF((PyObject*)e); return NULL; } if (!mpz_fits_ui_p(e->z)) { VALUE_ERROR("xmpz.pow outrageous exponent"); Py_DECREF((PyObject*)e); return NULL; } el = mpz_get_ui(e->z); mpz_pow_ui(Pyxmpz_AS_MPZ(in_b), Pyxmpz_AS_MPZ(in_b), el); Py_DECREF((PyObject*)e); Py_INCREF((PyObject*)in_b); return (PyObject*)in_b; } /* Inplace xmpz and. */ static PyObject * Pyxmpz_inplace_and(PyObject *self, PyObject *other) { mpz_t tempz; if (CHECK_MPZANY(other)) { mpz_and(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(other)); Py_INCREF(self); return self; } if (PyIntOrLong_Check(other)) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_and(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), tempz); mpz_cloc(tempz); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace xmpz xor. */ static PyObject * Pyxmpz_inplace_xor(PyObject *self, PyObject *other) { mpz_t tempz; if(CHECK_MPZANY(other)) { mpz_xor(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(other)); Py_INCREF(self); return self; } if(PyIntOrLong_Check(other)) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_xor(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), tempz); mpz_cloc(tempz); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; } /* Inplace xmpz or. */ static PyObject * Pyxmpz_inplace_ior(PyObject *self, PyObject *other) { mpz_t tempz; if(CHECK_MPZANY(other)) { mpz_ior(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(other)); Py_INCREF(self); return self; } if(PyIntOrLong_Check(other)) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_ior(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), tempz); mpz_cloc(tempz); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; } gmpy2-2.0.7/src/gmpy_xmpz.h0000666000000000000000000000713312542614506014263 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_xmpz.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_XMPZ_H #define GMPY_XMPZ_H #ifdef __cplusplus extern "C" { #endif typedef struct { PyObject_HEAD mpz_t z; } PyxmpzObject; #define Pyxmpz_AS_MPZ(obj) (((PyxmpzObject *)(obj))->z) static PyTypeObject Pyxmpz_Type; #define Pyxmpz_Check(v) (((PyObject*)v)->ob_type == &Pyxmpz_Type) #define CHECK_MPZANY(v) (Pympz_Check(v) || Pyxmpz_Check(v)) typedef struct { PyObject_HEAD PyxmpzObject *bitmap; Py_ssize_t start, stop; int iter_type; } GMPYIterObject; static PyTypeObject GMPYIter_Type; #define GMPyIter_Check(v) (((PyObject*)v)->ob_type == &GMPYIter_Type) static PyObject * Pygmpy_xmpz(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pyxmpz_digits(PyObject *self, PyObject *args); static PyObject * Pyxmpz_xbit_mask(PyObject *self, PyObject *other); static PyObject * Pyxmpz_abs(PyxmpzObject *x); static PyObject * Pyxmpz_neg(PyxmpzObject *x); static PyObject * Pyxmpz_pos(PyxmpzObject *x); static int Pyxmpz_nonzero(PyxmpzObject *x); static PyObject * Pyxmpz_com(PyxmpzObject *x); #if PY_MAJOR_VERSION < 3 /* hex/oct formatting (mpz-only) */ static PyObject * Pyxmpz_oct(PyxmpzObject *self); static PyObject * Pyxmpz_hex(PyxmpzObject *self); #endif static PyObject * Pyxmpz_make_mpz(PyObject *self, PyObject *other); static PyObject * Pyxmpz_copy(PyObject *self, PyObject *other); static Py_ssize_t Pyxmpz_nbits(PyxmpzObject *obj); static PyObject * Pyxmpz_subscript(PyxmpzObject* self, PyObject* item); static int Pyxmpz_assign_subscript(PyxmpzObject* self, PyObject* item, PyObject* value); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_xmpz.c0000666000000000000000000007323612542614506014265 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_xmpz.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ PyDoc_STRVAR(doc_xmpz, "xmpz() -> xmpz(0)\n\n" " If no argument is given, return xmpz(0).\n\n" "xmpz(n) -> xmpz\n\n" " Return an 'xmpz' object with a numeric value 'n' (truncating n\n" " to its integer part if it's a Fraction, 'mpq', Decimal, float\n" " or 'mpfr').\n\n" "xmpz(s[, base=0]):\n\n" " Return an 'xmpz' object from a string 's' made of digits in the\n" " given base. If base=0, binary, octal, or hex Python strings\n" " are recognized by leading 0b, 0o, or 0x characters, otherwise\n" " the string is assumed to be decimal. Values for base can range\n" " between 2 and 62.\n\n" " Note: 'xmpz' is a mutable integer. It can be faster for when\n" " used for augmented assignment (+=, *=, etc.). 'xmpz' objects\n" " cannot be used as dictionary keys. The use of 'mpz' objects is\n" " recommended in most cases."); static PyObject * Pygmpy_xmpz(PyObject *self, PyObject *args, PyObject *keywds) { PyxmpzObject *result = 0; PyObject *n = 0; int base = 0; Py_ssize_t argc; static char *kwlist[] = {"n", "base", NULL }; /* Optimize the most common use case */ argc = PyTuple_Size(args); if (argc == 0) { if ((result = (PyxmpzObject*)Pyxmpz_new())) { mpz_set_ui(result->z, 0); } return (PyObject*)result; } if (argc == 1) { n = PyTuple_GetItem(args, 0); #ifdef WITHMPFR if (isReal(n) && !keywds) { #else if ((isRational(n) || PyFloat_Check(n)) && !keywds) { #endif result = Pyxmpz_From_Number(n); if (!result && !PyErr_Occurred()) TYPE_ERROR("xmpz() requires numeric or string argument"); return (PyObject*)result; } } if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) return NULL; if ((base!=0) && ((base<2)||(base>62))) { VALUE_ERROR("base for xmpz() must be 0 or in the " "interval 2 ... 62"); return NULL; } if (PyStrOrUnicode_Check(n)) { /* build-from-string (ascii or unicode) */ result = Pyxmpz_From_PyStr(n, base); } else { if (argc==2 || (argc == 1 && keywds)) TYPE_ERROR("xmpz() with non-string argument needs exactly " "1 argument"); else { result = Pyxmpz_From_Number(n); if (!result && !PyErr_Occurred()) TYPE_ERROR("xmpz() requires numeric or string argument"); } } return (PyObject*)result; } /* For many xmpz_functions, the doc-strings are in gmpy_mpz.c. */ static PyObject * Pyxmpz_digits(PyObject *self, PyObject *args) { long base = 10; PyObject *result; PARSE_ONE_MPZ_OPT_CLONG(&base, "digits() requires 'int' argument for base"); if ((base < 2) || (base > 62)) { VALUE_ERROR("base must be in the interval 2 ... 62"); Py_DECREF(self); return NULL; } result = Pyxmpz_To_PyStr((PyxmpzObject*)self, (int)base, 0); Py_DECREF(self); return result; } PyDoc_STRVAR(doc_xbit_maskg, "xbit_mask(n) -> xmpz\n\n" "Return an 'xmpz' exactly n bits in length with all bits set.\n"); static PyObject * Pyxmpz_xbit_mask(PyObject *self, PyObject *other) { Py_ssize_t i = 0; PyxmpzObject* result; i = ssize_t_From_Integer(other); if (i == -1 && PyErr_Occurred()) { TYPE_ERROR("xbit_mask() requires 'int' argument"); return NULL; } if (i < 0) { VALUE_ERROR("mask length must be >= 0"); return NULL; } if (!(result = (PyxmpzObject*)Pyxmpz_new())) return NULL; mpz_set_ui(result->z, 1); mpz_mul_2exp(result->z, result->z, i); mpz_sub_ui(result->z, result->z, 1); return (PyObject*)result; } static PyObject * Pyxmpz_abs(PyxmpzObject *x) { mpz_abs(x->z, x->z); Py_RETURN_NONE; } static PyObject * Pyxmpz_neg(PyxmpzObject *x) { mpz_neg(x->z, x->z); Py_RETURN_NONE; } static PyObject * Pyxmpz_pos(PyxmpzObject *x) { Py_RETURN_NONE; } static int Pyxmpz_nonzero(PyxmpzObject *x) { return mpz_sgn(x->z) != 0; } /* BIT OPERATIONS */ static PyObject * Pyxmpz_com(PyxmpzObject *x) { mpz_com(x->z, x->z); Py_RETURN_NONE; } #if PY_MAJOR_VERSION < 3 /* hex/oct formatting (mpz-only) */ static PyObject * Pyxmpz_oct(PyxmpzObject *self) { return Pyxmpz_To_PyStr(self, 8, 0); } static PyObject * Pyxmpz_hex(PyxmpzObject *self) { return Pyxmpz_To_PyStr(self, 16, 0); } #endif PyDoc_STRVAR(doc_make_mpzm, "xmpz.make_mpz() -> mpz\n\n" "Return an mpz by converting an 'xmpz' to an 'mpz' as quickly as\n" "possible.\n\n" "NOTE: Optimized for speed so the original xmpz is set to 0!."); static PyObject * Pyxmpz_make_mpz(PyObject *self, PyObject *other) { PympzObject* result; if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_swap(result->z, Pympz_AS_MPZ(self)); mpz_set_ui(Pympz_AS_MPZ(self), 0); return (PyObject*)result; } PyDoc_STRVAR(doc_xmpz_copy, "xmpz.copy() -> xmpz\n\n" "Return a copy of an xmpz."); static PyObject * Pyxmpz_copy(PyObject *self, PyObject *other) { return (PyObject*)Pyxmpz_From_Pyxmpz(self); } /* * Add mapping support to xmpz objects. */ static Py_ssize_t Pyxmpz_nbits(PyxmpzObject *obj) { return mpz_sizeinbase(obj->z, 2); } static PyObject * Pyxmpz_subscript(PyxmpzObject* self, PyObject* item) { if (PyIndex_Check(item)) { Py_ssize_t i; i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; if (i < 0) i += mpz_sizeinbase(self->z, 2); return PyIntOrLong_FromLong(mpz_tstbit(self->z, i)); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, cur, i; PyObject* result; #if PY_VERSION_HEX > 0x030200A4 if (PySlice_GetIndicesEx(item, #else if (PySlice_GetIndicesEx((PySliceObject*)item, #endif mpz_sizeinbase(self->z, 2), &start, &stop, &step, &slicelength) < 0) { return NULL; } if ((step < 0 && start < stop) || (step > 0 && start > stop)) stop = start; if (!(result = (PyObject*)Pympz_new())) return NULL; mpz_set_ui(Pympz_AS_MPZ(result), 0); if (slicelength > 0) { for (cur = start, i = 0; i < slicelength; cur += step, i++) { if (mpz_tstbit(self->z, cur)) { mpz_setbit(Pympz_AS_MPZ(result), i); } } } return result; } else { TYPE_ERROR("bit positions must be integers"); return NULL; } } static int Pyxmpz_assign_subscript(PyxmpzObject* self, PyObject* item, PyObject* value) { if (PyIndex_Check(item)) { Py_ssize_t bit_value, i; i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return -1; if (i < 0) i += mpz_sizeinbase(self->z, 2); bit_value = PyNumber_AsSsize_t(value, PyExc_ValueError); if (bit_value == -1 && PyErr_Occurred()) { VALUE_ERROR("bit value must be 0 or 1"); return -1; } if (bit_value == 1) { mpz_setbit(self->z, i); return 0; } else if (bit_value == 0) { mpz_clrbit(self->z, i); return 0; } else { VALUE_ERROR("bit value must be 0 or 1"); return -1; } } else if (PySlice_Check(item)) { Py_ssize_t cur, i, seq_len, start, stop, step, slicelength, temp; seq_len = mpz_sizeinbase(self->z, 2); if (((PySliceObject*)item)->stop != Py_None) { /* If a fixed endpoint is specified, and the endpoint is greater * than the length of the xmpz object, allow the underlying xmpz * object to be made larger. */ temp = PyIntOrLong_AsSsize_t(((PySliceObject*)item)->stop); if (temp == -1 && PyErr_Occurred()) return 0; if (temp > seq_len) seq_len = temp; } #if PY_VERSION_HEX > 0x030200A4 if (PySlice_GetIndicesEx(item, #else if (PySlice_GetIndicesEx((PySliceObject*)item, #endif seq_len, &start, &stop, &step, &slicelength) < 0) { return -1; } if ((step < 0 && start < stop) || (step > 0 && start > stop)) stop = start; if (value == NULL) { TYPE_ERROR("deleting bits not supported"); return -1; } /* Special recognition of True/False for setting /clearing a slice of * bits has been removed. To clear a slice of bits, just use 0. To set * a slice of bits, use either ~0 or -1. else if (value == Py_True) { for (cur = start + (slicelength-1) * step, i = 0; i < slicelength; cur -= step, i++) { mpz_setbit(self->z, cur); } } else if (value == Py_False) { for (cur = start, i = 0; i < slicelength; cur += step, i++) { mpz_clrbit(self->z, cur); } } */ else { int bit; PympzObject *tempx; if (!(tempx = Pympz_From_Integer(value))) { VALUE_ERROR("must specify bit sequence as an integer"); return -1; } if (mpz_sgn(tempx->z) == 0) { for (cur = start, i = 0; i < slicelength; cur += step, i++) { mpz_clrbit(self->z, cur); } } else if (!(mpz_cmp_si(tempx->z, -1))) { for (cur = start + (slicelength-1) * step, i = 0; i < slicelength; cur -= step, i++) { mpz_setbit(self->z, cur); } } else { for (cur = start, i = 0; i < slicelength; cur += step, i++) { bit = mpz_tstbit(tempx->z, i); if (bit) mpz_setbit(self->z, cur); else mpz_clrbit(self->z, cur); } } Py_DECREF((PyObject*)tempx); } return 0; } else { TYPE_ERROR("bit positions must be integers"); return -1; } return -1; } /* Implement a multi-purpose iterator object that iterates over the bits in * an xmpz. Three different iterators can be created: * 1) xmpz.iter_bits(start=0, stop=-1) will return True/False for each bit * position in the xmpz, beginning with bit 'start'. If stop is specified, * the xmpz will be padded with 0-bits (False) until stop is reached. * 2) xmpz.iter_set(start=0, stop=-1, scale=1, offset=0) will return * (scale*bit_position + offset) when bit_position is set, beginning at * 'start', ending at 'stop'. * 3) xmpz.iter_clear(start=0, stop=-1, scale=1, offset=0) will return * (scale*bit_position + offset) when bit_position is clear, beginning at * 'start', ending at 'stop'. * */ static GMPYIterObject * GMPYIter_New(void) { GMPYIterObject *result; if ((result = PyObject_New(GMPYIterObject, &GMPYIter_Type))) { result->bitmap = NULL; result->start = 0; result->stop = -1; result->iter_type = 1; } return result; }; static void GMPYIter_Dealloc(GMPYIterObject *self) { Py_XDECREF((PyObject*)self->bitmap); PyObject_Del(self); }; static PyObject * GMPYIter_Next(GMPYIterObject *self) { PyObject *result = 0; mpir_si temp; Py_ssize_t current_stop; if (self->stop < 0) current_stop = mpz_sizeinbase(self->bitmap->z, 2); else current_stop = self->stop; switch (self->iter_type) { case 1: if (self->start >= current_stop) PyErr_SetNone(PyExc_StopIteration); else { temp = mpz_tstbit(self->bitmap->z, self->start); self->start += 1; result = temp ? Py_True : Py_False; Py_INCREF(result); } break; case 2: if (self->start >= current_stop) PyErr_SetNone(PyExc_StopIteration); else { temp = mpz_scan1(self->bitmap->z, self->start); if (temp < 0) PyErr_SetNone(PyExc_StopIteration); else { self->start = temp + 1; result = PyIntOrLong_FromSsize_t(temp); } } break; case 3: if (self->start >= current_stop) PyErr_SetNone(PyExc_StopIteration); else { temp = mpz_scan0(self->bitmap->z, self->start); if (temp >= current_stop) PyErr_SetNone(PyExc_StopIteration); else { self->start = temp + 1; result = PyIntOrLong_FromSsize_t(temp); } } break; default: SYSTEM_ERROR("Illegal iter_type in gmpy2.Iterator."); } return result; } static PyObject * GMPYIter_Repr(GMPYIterObject *self) { return Py_BuildValue("s", ""); }; PyDoc_STRVAR(doc_xmpz_iter_bits, "xmpz.iter_bits(start=0, stop=-1) -> iterator\n\n" "Return True or False for each bit position in 'xmpz' beginning at\n" "'start'. If a positive value is specified for 'stop', iteration is\n" "continued until 'stop' is reached. If a negative value is speci-\n" "fied, iteration is continued until the last 1-bit. Note: the value\n" "of the underlying xmpz object can change during iteration."); static PyObject * Pyxmpz_iter_bits(PyObject *self, PyObject *args, PyObject *kwargs) { GMPYIterObject *result; Py_ssize_t start = 0, stop = -1; static char *kwlist[] = {"start", "stop", NULL }; if (!(result = GMPYIter_New())) return NULL; if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) { Py_XDECREF((PyObject*)result); return NULL; } result->iter_type = 1; result->bitmap = (PyxmpzObject*)self; Py_INCREF(self); result->start = start; result->stop = stop; return (PyObject*)result; } PyDoc_STRVAR(doc_xmpz_iter_set, "xmpz.iter_set(start=0, stop=-1) -> iterator\n\n" "Return an iterator yielding the bit position for every bit that\n" "is set in 'xmpz', beginning at 'start'. If a positive value is\n" "specified for 'stop', iteration is continued until 'stop' is\n" "reached. To match the behavior of slicing, 'stop' is not included.\n" "If a negative value is specified, iteration is continued until\n" "the last 1-bit. Note: the value of the underlying xmpz object can\n" "change during iteration."); static PyObject * Pyxmpz_iter_set(PyObject *self, PyObject *args, PyObject *kwargs) { GMPYIterObject *result; Py_ssize_t start = 0, stop = -1; static char *kwlist[] = {"start", "stop", NULL }; if (!(result = GMPYIter_New())) return NULL; if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) { Py_XDECREF((PyObject*)result); return NULL; } result->iter_type = 2; result->bitmap = (PyxmpzObject*)self; Py_INCREF(self); result->start = start; result->stop = stop; return (PyObject*)result; } PyDoc_STRVAR(doc_xmpz_iter_clear, "xmpz.iter_clear(start=0, stop=-1, scale=1, offset=0) -> iterator\n\n" "Return (scale*bit_position + offset) for every bit position that\n" "is clear in 'xmpz', beginning at 'start'. If a positive value is\n" "specified for 'stop', iteration is continued until 'stop' is\n" "reached. If a negative value is specified, iteration is continued\n" "until the last 1-bit. 'scale' and 'offset' can be used to create\n" "a segmented bitmap or sieve. Note: the value of the underlying\n" "xmpz object can change during iteration."); static PyObject * Pyxmpz_iter_clear(PyObject *self, PyObject *args, PyObject *kwargs) { GMPYIterObject *result; Py_ssize_t start = 0, stop = -1; static char *kwlist[] = {"start", "stop", NULL }; if (!(result = GMPYIter_New())) return NULL; if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) { Py_XDECREF((PyObject*)result); return NULL; } result->iter_type = 3; result->bitmap = (PyxmpzObject*)self; Py_INCREF(self); result->start = start; result->stop = stop; return (PyObject*)result; } PyDoc_STRVAR(doc_xmpz_sizeof, "x.__sizeof__()\n\n" "Returns the amount of memory consumed by x. Note: deleted xmpz objects\n" "are reused and may or may not be resized when a new value is assigned."); static PyObject * Pyxmpz_sizeof(PyObject *self, PyObject *other) { return PyIntOrLong_FromSize_t(sizeof(PyxmpzObject) + \ (Pympz_AS_MPZ(self)->_mp_alloc * sizeof(mp_limb_t))); } static PyTypeObject GMPYIter_Type = { #ifdef PY3 PyVarObject_HEAD_INIT(0, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "gmpy2 iterator", /* tp_name */ sizeof(GMPYIterObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) GMPYIter_Dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) GMPYIter_Repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "GMPY2 Iterator Object", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ PyObject_SelfIter, /* tp_iter */ (iternextfunc)GMPYIter_Next, /* tp_iternext */ }; #ifdef PY3 static PyNumberMethods xmpz_number_methods = { (binaryfunc) Pybasic_add, /* nb_add */ (binaryfunc) Pybasic_sub, /* nb_subtract */ (binaryfunc) Pybasic_mul, /* nb_multiply */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pyxmpz_neg, /* nb_negative */ (unaryfunc) Pyxmpz_pos, /* nb_positive */ (unaryfunc) Pyxmpz_abs, /* nb_absolute */ (inquiry) Pyxmpz_nonzero, /* nb_bool */ (unaryfunc) Pyxmpz_com, /* nb_invert */ (binaryfunc) Pympz_lshift, /* nb_lshift */ (binaryfunc) Pympz_rshift, /* nb_rshift */ (binaryfunc) Pympz_and, /* nb_and */ (binaryfunc) Pympz_xor, /* nb_xor */ (binaryfunc) Pympz_ior, /* nb_or */ (unaryfunc) Pympz_To_PyLong, /* nb_int */ 0, /* nb_reserved */ (unaryfunc) Pympz_To_PyFloat, /* nb_float */ (binaryfunc) Pyxmpz_inplace_add, /* nb_inplace_add */ (binaryfunc) Pyxmpz_inplace_sub, /* nb_inplace_subtract */ (binaryfunc) Pyxmpz_inplace_mul, /* nb_inplace_multiply */ (binaryfunc) Pyxmpz_inplace_rem, /* nb_inplace_remainder */ (ternaryfunc) Pyxmpz_inplace_pow, /* nb_inplace_power */ (binaryfunc) Pyxmpz_inplace_lshift, /* nb_inplace_lshift */ (binaryfunc) Pyxmpz_inplace_rshift, /* nb_inplace_rshift */ (binaryfunc) Pyxmpz_inplace_and, /* nb_inplace_and */ (binaryfunc) Pyxmpz_inplace_xor, /* nb_inplace_xor */ (binaryfunc) Pyxmpz_inplace_ior, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pybasic_truediv, /* nb_true_divide */ (binaryfunc) Pyxmpz_inplace_floordiv,/* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ (unaryfunc) Pyxmpz_To_PyIntOrLong, /* nb_index */ }; #else static PyNumberMethods xmpz_number_methods = { (binaryfunc) Pybasic_add, /* nb_add */ (binaryfunc) Pybasic_sub, /* nb_subtract */ (binaryfunc) Pybasic_mul, /* nb_multiply */ (binaryfunc) Pybasic_div2, /* nb_divide */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pyxmpz_neg, /* nb_negative */ (unaryfunc) Pyxmpz_pos, /* nb_positive */ (unaryfunc) Pyxmpz_abs, /* nb_absolute */ (inquiry) Pyxmpz_nonzero, /* nb_bool */ (unaryfunc) Pyxmpz_com, /* nb_invert */ (binaryfunc) Pympz_lshift, /* nb_lshift */ (binaryfunc) Pympz_rshift, /* nb_rshift */ (binaryfunc) Pympz_and, /* nb_and */ (binaryfunc) Pympz_xor, /* nb_xor */ (binaryfunc) Pympz_ior, /* nb_or */ 0, /* nb_coerce */ (unaryfunc) Pympz_To_PyIntOrLong, /* nb_int */ (unaryfunc) Pympz_To_PyLong, /* nb_long */ (unaryfunc) Pympz_To_PyFloat, /* nb_float */ (unaryfunc) Pyxmpz_oct, /* nb_oct */ (unaryfunc) Pyxmpz_hex, /* nb_hex */ (binaryfunc) Pyxmpz_inplace_add, /* nb_inplace_add */ (binaryfunc) Pyxmpz_inplace_sub, /* nb_inplace_subtract */ (binaryfunc) Pyxmpz_inplace_mul, /* nb_inplace_multiply */ 0, /* nb_inplace_divide */ (binaryfunc) Pyxmpz_inplace_rem, /* nb_inplace_remainder */ (ternaryfunc) Pyxmpz_inplace_pow, /* nb_inplace_power */ (binaryfunc) Pyxmpz_inplace_lshift, /* nb_inplace_lshift */ (binaryfunc) Pyxmpz_inplace_rshift, /* nb_inplace_rshift */ (binaryfunc) Pyxmpz_inplace_and, /* nb_inplace_and */ (binaryfunc) Pyxmpz_inplace_xor, /* nb_inplace_xor */ (binaryfunc) Pyxmpz_inplace_ior, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pybasic_truediv, /* nb_true_divide */ (binaryfunc) Pyxmpz_inplace_floordiv,/* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ (unaryfunc) Pyxmpz_To_PyIntOrLong, /* nb_index */ }; #endif static PyMappingMethods xmpz_mapping_methods = { (lenfunc)Pyxmpz_nbits, (binaryfunc)Pyxmpz_subscript, (objobjargproc)Pyxmpz_assign_subscript }; static PyMethodDef Pyxmpz_methods [] = { { "__format__", Pympz_format, METH_VARARGS, doc_mpz_format }, { "__sizeof__", Pyxmpz_sizeof, METH_NOARGS, doc_xmpz_sizeof }, { "bit_clear", Pympz_bit_clear, METH_O, doc_bit_clearm }, { "bit_flip", Pympz_bit_flip, METH_O, doc_bit_flipm }, { "bit_length", Pympz_bit_length, METH_NOARGS, doc_bit_lengthm }, { "bit_scan0", Pympz_bit_scan0, METH_VARARGS, doc_bit_scan0m }, { "bit_scan1", Pympz_bit_scan1, METH_VARARGS, doc_bit_scan1m }, { "bit_set", Pympz_bit_set, METH_O, doc_bit_setm }, { "bit_test", Pympz_bit_test, METH_O, doc_bit_testm }, { "copy", Pyxmpz_copy, METH_NOARGS, doc_xmpz_copy }, { "digits", Pyxmpz_digits, METH_VARARGS, doc_mpz_digits }, { "iter_bits", (PyCFunction)Pyxmpz_iter_bits, METH_VARARGS | METH_KEYWORDS, doc_xmpz_iter_bits }, { "iter_clear", (PyCFunction)Pyxmpz_iter_clear, METH_VARARGS | METH_KEYWORDS, doc_xmpz_iter_clear }, { "iter_set", (PyCFunction)Pyxmpz_iter_set, METH_VARARGS | METH_KEYWORDS, doc_xmpz_iter_set }, { "make_mpz", Pyxmpz_make_mpz, METH_NOARGS, doc_make_mpzm }, { "num_digits", Pympz_num_digits, METH_VARARGS, doc_num_digitsm }, { NULL, NULL, 1 } }; static PyTypeObject Pyxmpz_Type = { /* PyObject_HEAD_INIT(&PyType_Type) */ #ifdef PY3 PyVarObject_HEAD_INIT(0, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "xmpz", /* tp_name */ sizeof(PyxmpzObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor) Pyxmpz_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) Pyxmpz_To_Repr, /* tp_repr */ &xmpz_number_methods, /* tp_as_number */ 0, /* tp_as_sequence */ &xmpz_mapping_methods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ (reprfunc) Pyxmpz_To_Str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ #ifdef PY3 Py_TPFLAGS_DEFAULT, /* tp_flags */ #else Py_TPFLAGS_HAVE_INDEX|Py_TPFLAGS_HAVE_RICHCOMPARE| \ Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_CLASS| \ Py_TPFLAGS_HAVE_INPLACEOPS, #endif "Multiple precision integer", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)&mpany_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ Pyxmpz_methods, /* tp_methods */ }; gmpy2-2.0.7/src/gmpy_random.h0000666000000000000000000000612012542614506014540 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_random.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_RANDOM_H #define GMPY_RANDOM_H #ifdef __cplusplus extern "C" { #endif /* gmpy_random C API extension header file. * * Provide support random number state. * * Version 2.00, December 2011 (created) casevh * * This file is expected to be included from gmpy.h */ typedef struct { PyObject_HEAD gmp_randstate_t state; } GMPYRandomStateObject; static PyTypeObject GMPYRandomState_Type; #define PyObj_AS_STATE(obj) (((GMPYRandomStateObject *)(obj))->state) #define GMPYRandomState_Check(v) (((PyObject*)v)->ob_type == &GMPYRandomState_Type) static GMPYRandomStateObject * GMPYRandomState_New(void); static void GMPYRandomState_Dealloc(GMPYRandomStateObject *self); static PyObject * GMPYRandomState_Repr(GMPYRandomStateObject *self); static PyObject * GMPY_random_state(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_urandomb(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_rrandomb(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_random(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_random.c0000666000000000000000000002641112542614506014540 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_random.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static GMPYRandomStateObject * GMPYRandomState_New(void) { GMPYRandomStateObject *result; if ((result = PyObject_New(GMPYRandomStateObject, &GMPYRandomState_Type))) { gmp_randinit_default(result->state); } return result; }; static void GMPYRandomState_Dealloc(GMPYRandomStateObject *self) { gmp_randclear(self->state); PyObject_Del(self); }; static PyObject * GMPYRandomState_Repr(GMPYRandomStateObject *self) { return Py_BuildValue("s", ""); }; PyDoc_STRVAR(doc_random_state, "random_state([seed]) -> object\n\n" "Return new object containing state information for the random number\n" "generator. An optional integer can be specified as the seed value."); static PyObject * GMPY_random_state(PyObject *self, PyObject *args) { GMPYRandomStateObject *result; PympzObject *temp; if (!(result = GMPYRandomState_New())) return NULL; if (PyTuple_GET_SIZE(args) == 0) { gmp_randseed_ui(result->state, 0); } else if (PyTuple_GET_SIZE(args) == 1) { if (!(temp = Pympz_From_Integer(PyTuple_GET_ITEM(args,0)))) { Py_DECREF((PyObject*)result); TYPE_ERROR("seed must be an integer"); return NULL; } gmp_randseed(result->state, temp->z); Py_DECREF((PyObject*)temp); } else { Py_DECREF((PyObject*)result); TYPE_ERROR("random_state() requires 0 or 1 integer arguments"); return NULL; } return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_urandomb, "mpz_urandomb(random_state, bit_count) -> mpz\n\n" "Return uniformly distributed random integer between 0 and\n" "2**bit_count-1."); static PyObject * GMPY_mpz_urandomb(PyObject *self, PyObject *args) { PympzObject *result; mp_bitcnt_t len; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("mpz_urandomb() requires 2 arguments"); return NULL; } if (!GMPYRandomState_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments"); return NULL; } len = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (len == (mp_bitcnt_t)-1 && PyErr_Occurred()) { TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments"); return NULL; } if ((result = (PympzObject*)Pympz_new())) { mpz_urandomb(Pympz_AS_MPZ(result), PyObj_AS_STATE(PyTuple_GET_ITEM(args, 0)), len); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_rrandomb, "mpz_rrandomb(random_state, bit_count) -> mpz\n\n" "Return a random integer between 0 and 2**bit_count-1 with long\n" "sequences of zeros and one in its binary representation."); static PyObject * GMPY_mpz_rrandomb(PyObject *self, PyObject *args) { PympzObject *result; mp_bitcnt_t len; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("mpz_rrandomb() requires 2 arguments"); return NULL; } if (!GMPYRandomState_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments"); return NULL; } len = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (len == (mp_bitcnt_t)-1 && PyErr_Occurred()) { TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments"); return NULL; } if ((result = (PympzObject*)Pympz_new())) { mpz_rrandomb(Pympz_AS_MPZ(result), PyObj_AS_STATE(PyTuple_GET_ITEM(args, 0)), len); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_random, "mpz_random(random_state, int) -> mpz\n\n" "Return uniformly distributed random integer between 0 and n-1."); static PyObject * GMPY_mpz_random(PyObject *self, PyObject *args) { PympzObject *result, *temp; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("mpz_random() requires 2 arguments"); return NULL; } if (!GMPYRandomState_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments"); return NULL; } if (!(temp = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)))) { TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments"); return NULL; } if ((result = (PympzObject*)Pympz_new())) { mpz_urandomm(Pympz_AS_MPZ(result), PyObj_AS_STATE(PyTuple_GET_ITEM(args, 0)), Pympz_AS_MPZ(temp)); } Py_DECREF((PyObject*)temp); return (PyObject*)result; } #ifdef WITHMPFR PyDoc_STRVAR(doc_mpfr_random, "mpfr_random(random_state) -> mpfr\n\n" "Return uniformly distributed number between [0,1]."); static PyObject * GMPY_mpfr_random(PyObject *self, PyObject *args) { PympfrObject *result; if (PyTuple_GET_SIZE(args) != 1) { TYPE_ERROR("mpfr_random() requires 1 argument"); return NULL; } if (!GMPYRandomState_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("mpfr_random() requires 'random_state' argument"); return NULL; } if ((result = (PympfrObject*)Pympfr_new(0))) { mpfr_urandom(Pympfr_AS_MPFR(result), PyObj_AS_STATE(PyTuple_GET_ITEM(args, 0)), context->ctx.mpfr_round); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpfr_grandom, "mpfr_grandom(random_state) -> (mpfr, mpfr)\n\n" "Return two random numbers with gaussian distribution."); static PyObject * GMPY_mpfr_grandom(PyObject *self, PyObject *args) { PympfrObject *result1, *result2; PyObject *result; if (PyTuple_GET_SIZE(args) != 1) { TYPE_ERROR("mpfr_grandom() requires 1 argument"); return NULL; } if (!GMPYRandomState_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("mpfr_grandom() requires 'random_state' argument"); return NULL; } result1 = (PympfrObject*)Pympfr_new(0); result2 = (PympfrObject*)Pympfr_new(0); if (!result1 || !result2) { Py_XDECREF((PyObject*)result1); Py_XDECREF((PyObject*)result2); return NULL; } mpfr_grandom(Pympfr_AS_MPFR(result1), Pympfr_AS_MPFR(result2), PyObj_AS_STATE(PyTuple_GET_ITEM(args, 0)), context->ctx.mpfr_round); result = Py_BuildValue("(NN)", (PyObject*)result1, (PyObject*)result2); if (!result) { Py_DECREF((PyObject*)result1); Py_DECREF((PyObject*)result2); } return result; } #endif #ifdef WITHMPC PyDoc_STRVAR(doc_mpc_random, "mpfc_random(random_state) -> mpc\n\n" "Return uniformly distributed number in the unit square [0,1]x[0,1]."); static PyObject * GMPY_mpc_random(PyObject *self, PyObject *args) { PympcObject *result; if (PyTuple_GET_SIZE(args) != 1) { TYPE_ERROR("mpfc_random() requires 1 argument"); return NULL; } if (!GMPYRandomState_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("mpc_random() requires 'random_state' argument"); return NULL; } if ((result = (PympcObject*)Pympc_new(0,0))) { mpc_urandom(Pympc_AS_MPC(result), PyObj_AS_STATE(PyTuple_GET_ITEM(args, 0))); } return (PyObject*)result; } #endif static PyTypeObject GMPYRandomState_Type = { #ifdef PY3 PyVarObject_HEAD_INIT(0, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "gmpy2 random status", /* tp_name */ sizeof(GMPYRandomStateObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) GMPYRandomState_Dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) GMPYRandomState_Repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "GMPY2 Random number generator state", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ }; gmpy2-2.0.7/src/gmpy_mpz_prp.h0000666000000000000000000000525412542614506014756 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_prp.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2012, 2013, 2014, 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_PRP_H #define GMPY_PRP_H #ifdef __cplusplus extern "C" { #endif static PyObject * GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_stronglucas_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_selfridge_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_bpsw_prp(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpz_prp.c0000666000000000000000000012366112542614506014754 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_prp.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2011 David Cleaver * * * * Copyright 2012, 2013, 2014, 2015 Case Van Horsen * * * * The original file is available at: * * * * * * Modified by Case Van Horsen for inclusion into GMPY2. * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ****************************************************************** * mpz_prp: (also called a Fermat probable prime) * A "probable prime" to the base a is a number n such that, * (a,n)=1 and a^(n-1) = 1 mod n * ******************************************************************/ PyDoc_STRVAR(doc_mpz_is_fermat_prp, "is_fermat_prp(n,a) -> boolean\n\n" "Return True if n is a Fermat probable prime to the base a.\n" "Assuming:\n" " gcd(n,a) == 1\n" "Then a Fermat probable prime requires:\n" " a**(n-1) == 1 (mod n)"); static PyObject * GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args) { PympzObject *a = NULL, *n = NULL; PyObject *result = NULL; mpz_t res, nm1; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); return NULL; } /* Allocate the temporary values early to allow a single cleanup section * to be used. */ mpz_inoc(res); mpz_inoc(nm1); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); a = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); if (!a || !n) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); goto cleanup; } /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_fermat_prp() requires 'a' greater than or equal to 2"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ /* Should n even raise an exception? */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,n) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { result = Py_False; goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); mpz_powm(res, a->z, nm1, n->z); if (mpz_cmp_ui(res, 1) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_cloc(res); mpz_cloc(nm1); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; } /* ************************************************************************* * mpz_euler_prp: (also called a Solovay-Strassen probable prime) * An "Euler probable prime" to the base a is an odd composite number n with, * (a,n)=1 such that a^((n-1)/2)=(a/n) mod n [(a/n) is the Jacobi symbol] * *************************************************************************/ PyDoc_STRVAR(doc_mpz_is_euler_prp, "is_euler_prp(n,a) -> boolean\n\n" "Return True if n is an Euler (also known as Solovay-Strassen)\n" "probable prime to the base a.\n" "Assuming:\n" " gcd(n,a) == 1\n" " n is odd\n" "Then an Euler probable prime requires:\n" " a**((n-1)/2) == 1 (mod n)"); static PyObject * GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args) { PympzObject *a = NULL, *n = NULL; PyObject *result = NULL; mpz_t res, exp; int ret; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(res); mpz_inoc(exp); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); a = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); if (!a || !n) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); goto cleanup; } /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_euler_prp() requires 'a' greater than or equal to 2"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,b) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { result = Py_False; goto cleanup; } mpz_set(exp, n->z); mpz_sub_ui(exp, exp, 1); mpz_divexact_ui(exp, exp, 2); mpz_powm(res, a->z, exp, n->z); /* reuse exp to calculate jacobi(a,n) mod n */ ret = mpz_jacobi(a->z,n->z); mpz_set(exp, n->z); if (ret == -1) mpz_sub_ui(exp, exp, 1); else if (ret == 1) mpz_add_ui(exp, exp, 1); mpz_mod(exp, exp, n->z); if (mpz_cmp(res, exp) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_cloc(res); mpz_cloc(exp); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; } /* ********************************************************************************************* * mpz_sprp: (also called a Miller-Rabin probable prime) * A "strong probable prime" to the base a is an odd composite n = (2^r)*s+1 with s odd such that * either a^s == 1 mod n, or a^((2^t)*s) == -1 mod n, for some integer t, with 0 <= t < r. * *********************************************************************************************/ PyDoc_STRVAR(doc_mpz_is_strong_prp, "is_strong_prp(n,a) -> boolean\n\n" "Return True if n is an strong (also known as Miller-Rabin)\n" "probable prime to the base a.\n" "Assuming:\n" " gcd(n,a) == 1\n" " n is odd\n" " n = s*(2**r) + 1, with s odd\n" "Then a strong probable prime requires one of the following is true:\n" " a**s == 1 (mod n)\n" " or\n" " a**(s*(2**t)) == -1 (mod n) for some t, 0 <= t < r."); static PyObject * GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args) { PympzObject *a = NULL, *n = NULL; PyObject *result = NULL; mpz_t s, nm1, mpz_test; mpir_ui r = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(s); mpz_inoc(nm1); mpz_inoc(mpz_test); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); a = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); if (!a || !n) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); goto cleanup; } /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_strong_prp() requires 'a' greater than or equal to 2"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); /* Find s and r satisfying: n-1=(2^r)*s, s odd */ r = mpz_scan1(nm1, 0); mpz_fdiv_q_2exp(s, nm1, r); /* Check a^((2^t)*s) mod n for 0 <= t < r */ mpz_powm(mpz_test, a->z, s, n->z); if ((mpz_cmp_ui(mpz_test, 1) == 0) || (mpz_cmp(mpz_test, nm1) == 0)) { result = Py_True; goto cleanup; } while (--r) { /* mpz_test = mpz_test^2%n */ mpz_mul(mpz_test, mpz_test, mpz_test); mpz_mod(mpz_test, mpz_test, n->z); if (mpz_cmp(mpz_test, nm1) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_cloc(s); mpz_cloc(nm1); mpz_cloc(mpz_test); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; } /* ************************************************************************* * mpz_fibonacci_prp: * A "Fibonacci probable prime" with parameters (P,Q), P > 0, Q=+/-1, is a * composite n for which V_n == P mod n * [V is the Lucas V sequence with parameters P,Q] * *************************************************************************/ PyDoc_STRVAR(doc_mpz_is_fibonacci_prp, "is_fibonacci_prp(n,p,q) -> boolean\n\n" "Return True if n is an Fibonacci probable prime with parameters (p,q).\n" "Assuming:\n" " n is odd\n" " p > 0, q = +/-1\n" " p*p - 4*q != 0\n" "Then a Fibonacci probable prime requires:\n" " lucasv(p,q,n) == p (mod n)."); static PyObject * GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args) { PympzObject *n = NULL, *p = NULL, *q = NULL; PyObject *result = NULL; mpz_t pmodn, zP; /* used for calculating the Lucas V sequence */ mpz_t vl, vh, ql, qh, tmp; size_t s = 0, j = 0; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(pmodn); mpz_inoc(zP); mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); if (!n || !p || !q) { TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()"); goto cleanup; } /* Verify q = +/-1 */ if ((mpz_cmp_si(q->z, 1) && mpz_cmp_si(q->z, -1)) || (mpz_sgn(p->z) <= 0)) { VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } mpz_set(zP, p->z); mpz_mod(pmodn, zP, n->z); /* mpz_lucasvmod(res, p, q, n, n); */ mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(n->z, 0); for (j = mpz_sizeinbase(n->z,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(n->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } /* vl contains our return value */ mpz_mod(vl, vl, n->z); if (mpz_cmp(vl, pmodn) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_cloc(pmodn); mpz_cloc(zP); mpz_cloc(vl); mpz_cloc(vh); mpz_cloc(ql); mpz_cloc(qh); mpz_cloc(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; } /* ******************************************************************************* * mpz_lucas_prp: * A "Lucas probable prime" with parameters (P,Q) is a composite n with D=P^2-4Q, * (n,2QD)=1 such that U_(n-(D/n)) == 0 mod n [(D/n) is the Jacobi symbol] * *******************************************************************************/ PyDoc_STRVAR(doc_mpz_is_lucas_prp, "is_lucas_prp(n,p,q) -> boolean\n\n" "Return True if n is a Lucas probable prime with parameters (p,q).\n" "Assuming:\n" " n is odd\n" " D = p*p - 4*q, D != 0\n" " gcd(n, 2*q*D) == 1\n" "Then a Lucas probable prime requires:\n" " lucasu(p,q,n - Jacobi(D,n)) == 0 (mod n)"); static PyObject * GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args) { PympzObject *n= NULL, *p = NULL, *q = NULL; PyObject *result = NULL; mpz_t zD, res, index; /* used for calculating the Lucas U sequence */ mpz_t uh, vl, vh, ql, qh, tmp; size_t s = 0, j = 0; int ret; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(zD); mpz_inoc(res); mpz_inoc(index); mpz_inoc(uh); mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); if (!n || !p || !q) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(zD, p->z, p->z); mpz_mul_ui(tmp, q->z, 4); mpz_sub(zD, zD, tmp); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid values for p,q in is_lucas_prp()"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check GCD */ mpz_mul(res, zD, q->z); mpz_mul_ui(res, res, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { result = Py_False; goto cleanup; } /* index = n-(D/n), where (D/n) is the Jacobi symbol */ mpz_set(index, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(index, index, 1); else if (ret == 1) mpz_sub_ui(index, index, 1); /* mpz_lucasumod(res, p, q, index, n); */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(index, 0); for (j = mpz_sizeinbase(index,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(index,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* uh = uh*vl (mod n) */ mpz_mul(uh, uh, vl); mpz_mod(uh, uh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } /* uh contains our return value */ mpz_mod(res, uh, n->z); if (mpz_cmp_ui(res, 0) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(res); mpz_clear(index); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; } /* ********************************************************************************************* * mpz_stronglucas_prp: * A "strong Lucas probable prime" with parameters (P,Q) is a composite n = (2^r)*s+(D/n), where * s is odd, D=P^2-4Q, and (n,2QD)=1 such that either U_s == 0 mod n or V_((2^t)*s) == 0 mod n * for some t, 0 <= t < r. [(D/n) is the Jacobi symbol] * *********************************************************************************************/ PyDoc_STRVAR(doc_mpz_is_stronglucas_prp, "is_strong_lucas_prp(n,p,q) -> boolean\n\n" "Return True if n is a strong Lucas probable prime with parameters (p,q).\n" "Assuming:\n" " n is odd\n" " D = p*p - 4*q, D != 0\n" " gcd(n, 2*q*D) == 1\n" " n = s*(2**r) + Jacobi(D,n), s odd\n" "Then a strong Lucas probable prime requires:\n" " lucasu(p,q,s) == 0 (mod n)\n" " or\n" " lucasv(p,q,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r"); static PyObject * GMPY_mpz_is_stronglucas_prp(PyObject *self, PyObject *args) { PympzObject *n = NULL, *p = NULL, *q = NULL; PyObject *result = NULL; mpz_t zD, s, nmj, res; /* these are needed for the LucasU and LucasV part of this function */ mpz_t uh, vl, vh, ql, qh, tmp; mpir_ui r = 0; int ret = 0; mpir_ui j = 0; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_strong_lucas_prp() requires 3 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(zD); mpz_inoc(s); mpz_inoc(nmj); mpz_inoc(res); mpz_inoc(uh); mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); if (!n || !p || !q) { TYPE_ERROR("is_strong_lucas_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(zD, p->z, p->z); mpz_mul_ui(tmp, q->z, 4); mpz_sub(zD, zD, tmp); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid values for p,q in is_strong_lucas_prp()"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check GCD */ mpz_mul(res, zD, q->z); mpz_mul_ui(res, res, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { result = Py_False; goto cleanup; } /* nmj = n - (D/n), where (D/n) is the Jacobi symbol */ mpz_set(nmj, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(nmj, nmj, 1); else if (ret == 1) mpz_sub_ui(nmj, nmj, 1); r = mpz_scan1(nmj, 0); mpz_fdiv_q_2exp(s, nmj, r); /* make sure U_s == 0 mod n or V_((2^t)*s) == 0 mod n, for some t, 0 <= t < r */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(s,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); mpz_mod(uh, uh, n->z); mpz_mod(vl, vl, n->z); /* uh contains LucasU_s and vl contains LucasV_s */ if ((mpz_cmp_ui(uh, 0) == 0) || (mpz_cmp_ui(vl, 0) == 0)) { result = Py_True; goto cleanup; } for (j = 1; j < r; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); if (mpz_cmp_ui(vl, 0) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; } /* ******************************************************************************************* * mpz_extrastronglucas_prp: * Let U_n = LucasU(p,1), V_n = LucasV(p,1), and D=p^2-4. * An "extra strong Lucas probable prime" to the base p is a composite n = (2^r)*s+(D/n), where * s is odd and (n,2D)=1, such that either U_s == 0 mod n or V_s == +/-2 mod n, or * V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 [(D/n) is the Jacobi symbol] * *******************************************************************************************/ PyDoc_STRVAR(doc_mpz_is_extrastronglucas_prp, "is_extra_strong_lucas_prp(n,p) -> boolean\n\n" "Return True if n is an extra strong Lucas probable prime with parameters\n" "(p,1). Assuming:\n" " n is odd\n" " D = p*p - 4, D != 0\n" " gcd(n, 2*D) == 1\n" " n = s*(2**r) + Jacobi(D,n), s odd\n" "Then an extra strong Lucas probable prime requires:\n" " (lucasu(p,1,s) == 0 (mod n)\n" " and\n" " lucasv(p,1,s) == +/-2 (mod n))\n" " or\n" " lucasv(p,1,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r"); static PyObject * GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args) { PympzObject *n = NULL, *p = NULL; PyObject *result = NULL; mpz_t zD, s, nmj, nm2, res; /* these are needed for the LucasU and LucasV part of this function */ mpz_t uh, vl, vh, ql, qh, tmp; mpir_ui r = 0; mpir_si q = 1; int ret = 0; size_t j = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(zD); mpz_inoc(s); mpz_inoc(nmj); mpz_inoc(nm2); mpz_inoc(res); mpz_inoc(uh); mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); if (!n || !p) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); goto cleanup; } /* Check if p*p - 4 == 0. */ mpz_mul(zD, p->z, p->z); mpz_sub_ui(zD, zD, 4); if (mpz_sgn(zD) == 0) { VALUE_ERROR("is_extra_strong_lucas_prp() requires p*p-4 != 0"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check GCD */ mpz_mul_ui(res, zD, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { result = Py_False; goto cleanup; } /* nmj = n - (D/n), where (D/n) is the Jacobi symbol */ mpz_set(nmj, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(nmj, nmj, 1); else if (ret == 1) mpz_sub_ui(nmj, nmj, 1); r = mpz_scan1(nmj, 0); mpz_fdiv_q_2exp(s, nmj, r); /* (-2 mod n) is needed for one of the tests. */ mpz_sub_ui(nm2, n->z, 2); /* make sure that either U_s == 0 mod n and V_s == +/-2 mod n, or */ /* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(s,j) == 1) { /* qh = ql*q */ mpz_mul_si(qh, ql, q); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_set(qh, ql); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); mpz_mod(uh, uh, n->z); mpz_mod(vl, vl, n->z); /* uh contains LucasU_s and vl contains LucasV_s */ if ((mpz_cmp_ui(uh, 0) == 0) && ((mpz_cmp(vl, nm2) == 0) || (mpz_cmp_si(vl, 2) == 0))) { result = Py_True; goto cleanup; } for (j = 1; j < r-1; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); if (mpz_cmp_ui(vl, 0) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(nm2); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)n); return result; } /* *********************************************************************************************** * mpz_selfridge_prp: * A "Lucas-Selfridge probable prime" n is a "Lucas probable prime" using Selfridge parameters of: * Find the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) = -1 * Then use P=1 and Q=(1-D)/4 in the Lucas probable prime test. * Make sure n is not a perfect square, otherwise the search for D will only stop when D=n. * ***********************************************************************************************/ PyDoc_STRVAR(doc_mpz_is_selfridge_prp, "is_selfridge_prp(n) -> boolean\n\n" "Return True if n is a Lucas probable prime with Selfidge parameters\n" "(p,q). The Selfridge parameters are chosen by finding the first\n" "element D in the sequence {5, -7, 9, -11, 13, ...} such that\n" "Jacobi(D,n) == -1. Then let p=1 and q = (1-D)/4. Then perform\n" "a Lucas probable prime test."); static PyObject * GMPY_mpz_is_selfridge_prp(PyObject *self, PyObject *args) { PympzObject *n = NULL; PyObject *result = NULL, *temp = NULL; long d = 5, p = 1, q = 0, max_d = 1000000; int jacobi = 0; mpz_t zD; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_selfridge_prp() requires 1 integer argument"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(zD); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); if (!n) { TYPE_ERROR("is_selfridge_prp() requires 1 integer argument"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } mpz_set_ui(zD, d); while (1) { jacobi = mpz_jacobi(zD, n->z); /* if jacobi == 0, d is a factor of n, therefore n is composite... */ /* if d == n, then either n is either prime or 9... */ if (jacobi == 0) { if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) { result = Py_True; goto cleanup; } else { result = Py_False; goto cleanup; } } if (jacobi == -1) break; /* if we get to the 5th d, make sure we aren't dealing with a square... */ if (d == 13) { if (mpz_perfect_square_p(n->z)) { result = Py_False; goto cleanup; } } if (d < 0) { d *= -1; d += 2; } else { d += 2; d *= -1; } /* make sure we don't search forever */ if (d >= max_d) { VALUE_ERROR("appropriate value for D cannot be found in is_selfridge_prp()"); goto cleanup; } mpz_set_si(zD, d); } q = (1-d)/4; /* Since "O" is used, the refcount for n is incremented so deleting * temp will not delete n. */ temp = Py_BuildValue("Oll", n, p, q); if (!temp) goto cleanup; result = GMPY_mpz_is_lucas_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: mpz_cloc(zD); Py_XDECREF((PyObject*)n); return result; } /* ********************************************************************************************************* * mpz_strongselfridge_prp: * A "strong Lucas-Selfridge probable prime" n is a "strong Lucas probable prime" using Selfridge parameters of: * Find the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) = -1 * Then use P=1 and Q=(1-D)/4 in the strong Lucase probable prime test. * Make sure n is not a perfect square, otherwise the search for D will only stop when D=n. * **********************************************************************************************************/ PyDoc_STRVAR(doc_mpz_is_strongselfridge_prp, "is_strong_selfridge_prp(n) -> boolean\n\n" "Return True if n is a strong Lucas probable prime with Selfidge\n" "parameters (p,q). The Selfridge parameters are chosen by finding\n" "the first element D in the sequence {5, -7, 9, -11, 13, ...} such\n" "that Jacobi(D,n) == -1. Then let p=1 and q = (1-D)/4. Then perform\n" "a strong Lucas probable prime test."); static PyObject * GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args) { PympzObject *n = NULL; PyObject *result = NULL, *temp = NULL; long d = 5, p = 1, q = 0, max_d = 1000000; int jacobi = 0; mpz_t zD; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(zD); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); if (!n) { TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument"); goto cleanup; } if (mpz_cmp_ui(n->z, 2) < 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } mpz_set_ui(zD, d); while (1) { jacobi = mpz_jacobi(zD, n->z); /* if jacobi == 0, d is a factor of n, therefore n is composite... */ /* if d == n, then either n is either prime or 9... */ if (jacobi == 0) { if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) { result = Py_True; goto cleanup; } else { result = Py_False; goto cleanup; } } if (jacobi == -1) break; /* if we get to the 5th d, make sure we aren't dealing with a square... */ if (d == 13) { if (mpz_perfect_square_p(n->z)) { result = Py_False; goto cleanup; } } if (d < 0) { d *= -1; d += 2; } else { d += 2; d *= -1; } /* make sure we don't search forever */ if (d >= max_d) { VALUE_ERROR("appropriate value for D cannot be found in is_strong_selfridge_prp()"); goto cleanup; } mpz_set_si(zD, d); } q = (1-d)/4; /* Since "O" is used, the refcount for n is incremented so deleting * temp will not delete n. */ temp = Py_BuildValue("Oll", n, p, q); if (!temp) goto cleanup; result = GMPY_mpz_is_stronglucas_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: mpz_cloc(zD); Py_XDECREF((PyObject*)n); return result; } /* ********************************************************************************** * mpz_bpsw_prp: * A "Baillie-Pomerance-Selfridge-Wagstaff probable prime" is a composite n such that * n is a strong probable prime to the base 2 and * n is a Lucas probable prime using the Selfridge parameters. * **********************************************************************************/ PyDoc_STRVAR(doc_mpz_is_bpsw_prp, "is_bpsw_prp(n) -> boolean\n\n" "Return True if n is a Baillie-Pomerance-Selfridge-Wagstaff probable \n" "prime. A BPSW probable prime passes the is_strong_prp() test with base\n" "2 and the is_selfridge_prp() test.\n"); static PyObject * GMPY_mpz_is_bpsw_prp(PyObject *self, PyObject *args) { PympzObject *n = NULL; PyObject *result = NULL, *temp = NULL; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_bpsw_prp() requires 1 integer argument"); return NULL; } n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); if (!n) { TYPE_ERROR("is_bpsw_prp() requires 1 integer argument"); goto cleanup; } /* "O" is used to increment the reference to n so deleting temp won't * delete n. */ temp = Py_BuildValue("Oi", n, 2); if (!temp) goto cleanup; result = GMPY_mpz_is_strong_prp(NULL, temp); Py_DECREF(temp); if (result == Py_False) goto return_result; /* Remember to ignore the preceding result */ Py_DECREF(result); temp = Py_BuildValue("(O)", n); if (!temp) goto cleanup; result = GMPY_mpz_is_selfridge_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: Py_XDECREF((PyObject*)n); return result; } /* **************************************************************************************** * mpz_strongbpsw_prp: * A "strong Baillie-Pomerance-Selfridge-Wagstaff probable prime" is a composite n such that * n is a strong probable prime to the base 2 and * n is a strong Lucas probable prime using the Selfridge parameters. * ****************************************************************************************/ PyDoc_STRVAR(doc_mpz_is_strongbpsw_prp, "is_strong_bpsw_prp(n) -> boolean\n\n" "Return True if n is a strong Baillie-Pomerance-Selfridge-Wagstaff\n" "probable prime. A strong BPSW probable prime passes the is_strong_prp()\n" "test with base 2 and the is_strong_selfridge_prp() test.\n"); static PyObject * GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args) { PympzObject *n; PyObject *result = 0, *temp = 0; if (PyTuple_Size(args) != 1) { TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument"); return NULL; } n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); if (!n) { TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument"); goto cleanup; } /* "O" is used to increment the reference to n so deleting temp won't * delete n. */ temp = Py_BuildValue("Oi", n, 2); if (!temp) goto cleanup; result = GMPY_mpz_is_strong_prp(NULL, temp); Py_DECREF(temp); if (result == Py_False) goto return_result; /* Remember to ignore the preceding result */ Py_DECREF(result); temp = Py_BuildValue("(O)", n); if (!temp) goto cleanup; result = GMPY_mpz_is_strongselfridge_prp(NULL, temp); Py_DECREF(temp); goto return_result; cleanup: Py_XINCREF(result); return_result: Py_XDECREF((PyObject*)n); return result; } gmpy2-2.0.7/src/gmpy_mpz_lucas.h0000666000000000000000000000424012542614506015256 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_lucas.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2012, 2013, 2014, 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_LUCAS_H #define GMPY_LUCAS_H #ifdef __cplusplus extern "C" { #endif static PyObject * GMPY_mpz_lucasu(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_lucasu_mod(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_lucasv(PyObject *self, PyObject *args); static PyObject * GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpz_lucas.c0000666000000000000000000004433712542614506015264 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_lucas.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2011 David Cleaver * * * * Copyright 2012, 2013, 2014, 2015 Case Van Horsen * * * * The original file is available at: * * * * * * Modified by Case Van Horsen for inclusion into GMPY2. * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ PyDoc_STRVAR(doc_mpz_lucasu, "lucasu(p,q,k) -> mpz\n\n" "Return the k-th element of the Lucas U sequence defined by p,q.\n" "p*p - 4*q must not equal 0; k must be greater than or equal to 0."); static PyObject * GMPY_mpz_lucasu(PyObject *self, PyObject *args) { /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf * calculate u[k] of Lucas U sequence for p,q. * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!! */ PympzObject *result = 0, *p, *q, *k; size_t s = 0, j = 0; mpz_t uh, vl, vh, ql, qh, tmp; if (PyTuple_Size(args) != 3) { TYPE_ERROR("lucasu() requires 3 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(uh); mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); k = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); if (!p || !q || !k) { TYPE_ERROR("lucasu() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in lucasu()"); goto cleanup; } /* Check if k < 0. */ if (mpz_sgn(k->z) < 0) { VALUE_ERROR("invalid value for k in lucasu()"); goto cleanup; } mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp, 0); s = mpz_scan1(k->z, 0); for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) { /* ql = ql*qh */ mpz_mul(ql, ql, qh); if (mpz_tstbit(k->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vh */ mpz_mul(uh, uh, vh); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* vh = vh*vh - 2*qh */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vh = vh*vl - p*ql */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); /* vl = vl*vl - 2*ql */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* uh = uh*vl */ mpz_mul(uh, uh, vl); /* vl = vl*vl - 2*ql */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); /* ql = ql*ql */ mpz_mul(ql, ql, ql); } if (!(result = (PympzObject*)Pympz_new())) goto cleanup; /* uh contains our return value */ mpz_set(result->z, uh); cleanup: mpz_cloc(uh); mpz_cloc(vl); mpz_cloc(vh); mpz_cloc(ql); mpz_cloc(qh); mpz_cloc(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)k); return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_lucasu_mod, "lucasu_mod(p,q,k,n) -> mpz\n\n" "Return the k-th element of the Lucas U sequence defined by p,q (mod n).\n" "p*p - 4*q must not equal 0; k must be greater than or equal to 0;\n" "n must be greater than 0."); static PyObject * GMPY_mpz_lucasu_mod(PyObject *self, PyObject *args) { /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf * calculate u[k] (modulo n) of Lucas U sequence for p,q. * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!! */ PympzObject *result = 0, *p, *q, *k, *n; size_t s = 0, j = 0; mpz_t uh, vl, vh, ql, qh, tmp; if (PyTuple_Size(args) != 4) { TYPE_ERROR("lucasu_mod() requires 4 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(uh); mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); k = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 3)); if (!p || !q || !k || !n) { TYPE_ERROR("lucasu_mod() requires 4 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in lucasu_mod()"); goto cleanup; } /* Check if k < 0. */ if (mpz_sgn(k->z) < 0) { VALUE_ERROR("invalid value for k in lucasu_mod()"); goto cleanup; } /* Check if n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("invalid value for n in lucasu_mod()"); goto cleanup; } mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp, 0); s = mpz_scan1(k->z, 0); for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(k->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* uh = uh*vl (mod n) */ mpz_mul(uh, uh, vl); mpz_mod(uh, uh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } if (!(result = (PympzObject*)Pympz_new())) goto cleanup; /* uh contains our return value */ mpz_mod(result->z, uh, n->z); cleanup: mpz_cloc(uh); mpz_cloc(vl); mpz_cloc(vh); mpz_cloc(ql); mpz_cloc(qh); mpz_cloc(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)k); Py_XDECREF((PyObject*)n); return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_lucasv, "lucasv(p,q,k) -> mpz\n\n" "Return the k-th element of the Lucas V sequence defined by p,q.\n" "p*p - 4*q must not equal 0; k must be greater than or equal to 0."); static PyObject * GMPY_mpz_lucasv(PyObject *self, PyObject *args) { /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf * calculate v[k] of Lucas V sequence for p,q. * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!! */ PympzObject *result = 0, *p, *q, *k; size_t s = 0, j = 0; mpz_t vl, vh, ql, qh, tmp; if (PyTuple_Size(args) != 3) { TYPE_ERROR("lucasv() requires 3 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); k = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); if (!p || !q || !k) { TYPE_ERROR("lucasv() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in lucasv()"); goto cleanup; } /* Check if k < 0. */ if (mpz_sgn(k->z) < 0) { VALUE_ERROR("invalid value for k in lucasv()"); goto cleanup; } mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(k->z, 0); for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) { /* ql = ql*qh */ mpz_mul(ql, ql, qh); if (mpz_tstbit(k->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* vh = vh*vh - 2*qh */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); /* vl = vl*vl - 2*ql */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); /* ql = ql*ql */ mpz_mul(ql, ql, ql); } if (!(result = (PympzObject*)Pympz_new())) goto cleanup; /* vl contains our return value */ mpz_set(result->z, vl); cleanup: mpz_cloc(vl); mpz_cloc(vh); mpz_cloc(ql); mpz_cloc(qh); mpz_cloc(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)k); return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_lucasv_mod, "lucasv_mod(p,q,k,n) -> mpz\n\n" "Return the k-th element of the Lucas V sequence defined by p,q (mod n).\n" "p*p - 4*q must not equal 0; k must be greater than or equal to 0;\n" "n must be greater than 0."); static PyObject * GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args) { /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf * calculate v[k] (modulo n) of Lucas V sequence for p,q. * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!! */ PympzObject *result = 0, *p, *q, *k, *n; size_t s = 0, j = 0; mpz_t vl, vh, ql, qh, tmp; if (PyTuple_Size(args) != 4) { TYPE_ERROR("lucasv_mod() requires 4 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); k = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 3)); if (!p || !q || !k || !n) { TYPE_ERROR("lucasv_mod() requires 4 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in lucasv_mod()"); goto cleanup; } /* Check if k < 0. */ if (mpz_sgn(k->z) < 0) { VALUE_ERROR("invalid value for k in lucasv_mod()"); goto cleanup; } /* Check if n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("invalid value for n in lucasv_mod()"); goto cleanup; } mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(k->z, 0); for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(k->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } if (!(result = (PympzObject*)Pympz_new())) goto cleanup; /* vl contains our return value */ mpz_mod(result->z, vl, n->z); cleanup: mpz_cloc(vl); mpz_cloc(vh); mpz_cloc(ql); mpz_cloc(qh); mpz_cloc(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)k); Py_XDECREF((PyObject*)n); return (PyObject*)result; } gmpy2-2.0.7/src/gmpy_mpz_inplace.h0000666000000000000000000000535612542614506015573 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_inplace.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MPZ_INPLACE_H #define GMPY_MPZ_INPLACE_H #ifdef __cplusplus extern "C" { #endif static PyObject * Pympz_inplace_add(PyObject *self, PyObject *other); static PyObject * Pympz_inplace_sub(PyObject *self, PyObject *other); static PyObject * Pympz_inplace_mul(PyObject *self, PyObject *other); static PyObject * Pympz_inplace_floordiv(PyObject *self, PyObject *other); static PyObject * Pympz_inplace_rem(PyObject *self, PyObject *other); static PyObject * Pympz_inplace_rshift(PyObject *self, PyObject *other); static PyObject * Pympz_inplace_lshift(PyObject *self, PyObject *other); static PyObject * Pympz_inplace_pow(PyObject *self, PyObject *other, PyObject *mod); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpz_inplace.c0000666000000000000000000002457312542614506015570 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_inplace.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Provides inplace operations for mpz. */ #include static PyObject * Pympz_inplace_add(PyObject *self, PyObject *other) { PympzObject *rz; mpz_t tempz; mpir_si temp_si; int overflow; if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(other)) { mpz_add(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { temp_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_add(rz->z, Pympz_AS_MPZ(self), tempz); mpz_cloc(tempz); } else if(temp_si >= 0) { mpz_add_ui(rz->z, Pympz_AS_MPZ(self), temp_si); } else { mpz_sub_ui(rz->z, Pympz_AS_MPZ(self), -temp_si); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; } static PyObject * Pympz_inplace_sub(PyObject *self, PyObject *other) { PympzObject *rz; mpz_t tempz; mpir_si temp_si; int overflow; if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(other)) { mpz_sub(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { temp_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_sub(rz->z, Pympz_AS_MPZ(self), tempz); mpz_cloc(tempz); } else if(temp_si >= 0) { mpz_sub_ui(rz->z, Pympz_AS_MPZ(self), temp_si); } else { mpz_add_ui(rz->z, Pympz_AS_MPZ(self), -temp_si); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; } static PyObject * Pympz_inplace_mul(PyObject *self, PyObject *other) { PympzObject *rz; mpz_t tempz; mpir_si temp_si; int overflow; if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(other)) { mpz_mul(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { temp_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_mul(rz->z, Pympz_AS_MPZ(self), tempz); mpz_cloc(tempz); } else { mpz_mul_si(rz->z, Pympz_AS_MPZ(self), temp_si); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; } /* Pympany_floordiv follows the // semantics from Python 3.x. The result is * an mpz when the arguments are mpz or mpq, but the result is an mpf when * the arguments are mpf. */ static PyObject * Pympz_inplace_floordiv(PyObject *self, PyObject *other) { PympzObject *rz; mpz_t tempz; mpir_si temp_si; int overflow; if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(other)) { if (mpz_sgn(Pympz_AS_MPZ(other)) == 0) { ZERO_ERROR("mpz division by zero"); return NULL; } mpz_fdiv_q(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { temp_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_fdiv_q(rz->z, Pympz_AS_MPZ(self), tempz); mpz_cloc(tempz); } else if(temp_si == 0) { ZERO_ERROR("mpz division by zero"); return NULL; } else if(temp_si > 0) { mpz_fdiv_q_ui(rz->z, Pympz_AS_MPZ(self), temp_si); } else { mpz_cdiv_q_ui(rz->z, Pympz_AS_MPZ(self), -temp_si); mpz_neg(rz->z, rz->z); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; } static PyObject * Pympz_inplace_rem(PyObject *self, PyObject *other) { PympzObject *rz; mpz_t tempz; mpir_si temp_si; int overflow; if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(other)) { if (mpz_sgn(Pympz_AS_MPZ(other)) == 0) { ZERO_ERROR("mpz modulo by zero"); return NULL; } mpz_fdiv_r(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { temp_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_fdiv_r(rz->z, Pympz_AS_MPZ(self), tempz); mpz_cloc(tempz); } else if(temp_si > 0) { mpz_fdiv_r_ui(rz->z, Pympz_AS_MPZ(self), temp_si); } else if(temp_si == 0) { ZERO_ERROR("mpz modulo by zero"); return NULL; } else { mpz_cdiv_r_ui(rz->z, Pympz_AS_MPZ(self), -temp_si); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; } static PyObject * Pympz_inplace_rshift(PyObject *self, PyObject *other) { PympzObject *rz; mpir_si temp_si; int overflow; if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(other)) { if (mpz_sgn(Pympz_AS_MPZ(other)) < 0) { VALUE_ERROR("negative shift count"); Py_DECREF((PyObject*)rz); return NULL; } if (!mpz_fits_si_p(Pympz_AS_MPZ(other))) { OVERFLOW_ERROR("outrageous shift count"); Py_DECREF((PyObject*)rz); return NULL; } temp_si = mpz_get_si(Pympz_AS_MPZ(other)); mpz_fdiv_q_2exp(rz->z, Pympz_AS_MPZ(self), temp_si); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { temp_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { VALUE_ERROR("outrageous shift count"); Py_DECREF((PyObject*)rz); return NULL; } else if(temp_si >= 0) { mpz_fdiv_q_2exp(rz->z, Pympz_AS_MPZ(self), temp_si); return (PyObject *)rz; } else { VALUE_ERROR("negative shift count"); Py_DECREF((PyObject*)rz); return NULL; } } Py_RETURN_NOTIMPLEMENTED; } static PyObject * Pympz_inplace_lshift(PyObject *self, PyObject *other) { PympzObject *rz; mpir_si temp_si; int overflow; if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(other)) { if (mpz_sgn(Pympz_AS_MPZ(other)) < 0) { VALUE_ERROR("negative shift count"); Py_DECREF((PyObject*)rz); return NULL; } if (!mpz_fits_si_p(Pympz_AS_MPZ(other))) { OVERFLOW_ERROR("outrageous shift count"); Py_DECREF((PyObject*)rz); return NULL; } temp_si = mpz_get_si(Pympz_AS_MPZ(other)); mpz_mul_2exp(rz->z, Pympz_AS_MPZ(self), temp_si); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { temp_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { VALUE_ERROR("outrageous shift count"); Py_DECREF((PyObject*)rz); return NULL; } else if(temp_si >= 0) { mpz_mul_2exp(rz->z, Pympz_AS_MPZ(self), temp_si); return (PyObject *)rz; } else { VALUE_ERROR("negative shift count"); Py_DECREF((PyObject*)rz); return NULL; } } Py_RETURN_NOTIMPLEMENTED; } static PyObject * Pympz_inplace_pow(PyObject *self, PyObject *other, PyObject *mod) { PympzObject *r, *e = 0; mpir_ui el; if (mod != Py_None) { Py_RETURN_NOTIMPLEMENTED; } if (!(e = Pympz_From_Integer(other))) { PyErr_Clear(); Py_RETURN_NOTIMPLEMENTED; } if (mpz_sgn(e->z) < 0) { PyErr_Clear(); Py_DECREF((PyObject*)e); Py_RETURN_NOTIMPLEMENTED; } if (!mpz_fits_ui_p(e->z)) { PyErr_Clear(); Py_DECREF((PyObject*)e); Py_RETURN_NOTIMPLEMENTED; } if (!(r = (PympzObject*)Pympz_new())) { Py_DECREF((PyObject*)e); return NULL; } el = mpz_get_ui(e->z); mpz_pow_ui(r->z, Pympz_AS_MPZ(self), el); Py_DECREF((PyObject*)e); return (PyObject*)r; } gmpy2-2.0.7/src/gmpy_mpz_divmod2exp.h0000666000000000000000000000564012542614506016235 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_divmod2exp.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MPZ_DIVMOD2EXP_H #define GMPY_MPZ_DIVMOD2EXP_H #ifdef __cplusplus extern "C" { #endif static PyObject * Pygmpy_c_divmod_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_c_div_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_c_mod_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_f_divmod_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_f_div_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_f_mod_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_t_divmod_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_t_div_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_t_mod_2exp(PyObject *self, PyObject *args); static PyObject * Pygmpy_pack(PyObject *self, PyObject *args); static PyObject * Pygmpy_unpack(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpz_divmod2exp.c0000666000000000000000000005020712542614506016227 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_divmod2exp.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file contains functions related to division and remainder by a power * of two. */ /* ************************************************************************** * Ceiling division and remainder by power of two. ************************************************************************** */ PyDoc_STRVAR(doc_gmpy_c_divmod_2exp, "c_divmod_2exp(x ,n) -> (quotient, remainder)\n\n" "Return the quotient and remainder of x divided by 2**n. The quotient\n" "is rounded towards +Inf (ceiling rounding) and the remainder will\n" "be negative. x must be an integer. n must be >0."); static PyObject * Pygmpy_c_divmod_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x, *result; PympzObject *q, *r, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_divmod_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); CREATE_TWO_MPZ_TUPLE(q, r, result); if (CHECK_MPZANY(x)) { mpz_cdiv_q_2exp(q->z, Pympz_AS_MPZ(x), nbits); mpz_cdiv_r_2exp(r->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("c_divmod_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_cdiv_q_2exp(q->z, tempx->z, nbits); mpz_cdiv_r_2exp(r->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } PyTuple_SET_ITEM(result, 0, (PyObject*)q); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; } PyDoc_STRVAR(doc_gmpy_c_div_2exp, "c_div_2exp(x, n) -> quotient\n\n" "Returns the quotient of x divided by 2**n. The quotient is rounded\n" "towards +Inf (ceiling rounding). x must be an integer. n must be >0."); static PyObject * Pygmpy_c_div_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x; PympzObject *result, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_div_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); if (!(result = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x)) { mpz_cdiv_q_2exp(result->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("c_div_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)result); return NULL; } mpz_cdiv_q_2exp(result->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } return (PyObject*)result; } PyDoc_STRVAR(doc_gmpy_c_mod_2exp, "c_mod_2exp(x, n) -> remainder\n\n" "Return the remainder of x divided by 2**n. The remainder will be\n" "negative. x must be an integer. n must be >0."); static PyObject * Pygmpy_c_mod_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x; PympzObject *result, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_mod_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); if (!(result = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x)) { mpz_cdiv_r_2exp(result->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("c_mod_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)result); return NULL; } mpz_cdiv_r_2exp(result->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } return (PyObject*)result; } /* ************************************************************************** * Floor division and remainder by power of two. ************************************************************************** */ PyDoc_STRVAR(doc_gmpy_f_divmod_2exp, "f_divmod_2exp(x, n) -> (quotient, remainder)\n\n" "Return quotient and remainder after dividing x by 2**n. The quotient\n" "is rounded towards -Inf (floor rounding) and the remainder will be\n" "positive. x must be an integer. n must be >0."); static PyObject * Pygmpy_f_divmod_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x, *result; PympzObject *q, *r, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("f_divmod_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); CREATE_TWO_MPZ_TUPLE(q, r, result); if (CHECK_MPZANY(x)) { mpz_fdiv_q_2exp(q->z, Pympz_AS_MPZ(x), nbits); mpz_fdiv_r_2exp(r->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("f_divmod_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_fdiv_q_2exp(q->z, tempx->z, nbits); mpz_fdiv_r_2exp(r->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } PyTuple_SET_ITEM(result, 0, (PyObject*)q); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; } PyDoc_STRVAR(doc_gmpy_f_div_2exp, "f_div_2exp(x, n) -? quotient\n\n" "Return the quotient of x divided by 2**n. The quotient is rounded\n" "towards -Inf (floor rounding). x must be an integer. n must be >0."); static PyObject * Pygmpy_f_div_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x; PympzObject *result, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("f_div_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); if (!(result = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x)) { mpz_fdiv_q_2exp(result->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("f_div_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_q_2exp(result->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } return (PyObject*)result; } PyDoc_STRVAR(doc_gmpy_f_mod_2exp, "f_mod_2exp(x, n) -> remainder\n\n" "Return remainder of x divided by 2**n. The remainder will be\n" "positive. x must be an integer. n must be >0."); static PyObject * Pygmpy_f_mod_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x; PympzObject *result, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("f_mod_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); if (!(result = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x)) { mpz_fdiv_r_2exp(result->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("f_mod_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_r_2exp(result->z, Pympz_AS_MPZ(tempx), nbits); Py_DECREF((PyObject*)tempx); } return (PyObject*)result; } /* ************************************************************************** * Truncating division and remainder by power of two. ************************************************************************** */ PyDoc_STRVAR(doc_gmpy_t_divmod_2exp, "t_divmod_2exp(x, n) -> (quotient, remaidner)\n\n" "Return the quotient and remainder of x divided by 2**n. The quotient\n" "is rounded towards zero (truncation) and the remainder will have the\n" "same sign as x. x must be an integer. n must be >0."); static PyObject * Pygmpy_t_divmod_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x, *result; PympzObject *q, *r, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("t_divmod_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); CREATE_TWO_MPZ_TUPLE(q, r, result); if (CHECK_MPZANY(x)) { mpz_tdiv_q_2exp(q->z, Pympz_AS_MPZ(x), nbits); mpz_tdiv_r_2exp(r->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("t_divmod_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_tdiv_q_2exp(q->z, tempx->z, nbits); mpz_tdiv_r_2exp(r->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } PyTuple_SET_ITEM(result, 0, (PyObject*)q); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; } PyDoc_STRVAR(doc_gmpy_t_div_2exp, "t_div_2exp(x, n) -> quotient\n\n" "Return the quotient of x divided by 2**n. The quotient is rounded\n" "towards zero (truncation). n must be >0."); static PyObject * Pygmpy_t_div_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x; PympzObject *result, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("t_div_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); if (!(result = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x)) { mpz_tdiv_q_2exp(result->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("t_div_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)result); return NULL; } mpz_tdiv_q_2exp(result->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } return (PyObject*)result; } PyDoc_STRVAR(doc_gmpy_t_mod_2exp, "t_mod_2exp(x, n) -> remainder\n\n" "Return the remainder of x divided by 2**n. The remainder will have\n" "the same sign as x. x must be an integer. n must be >0."); static PyObject * Pygmpy_t_mod_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; PyObject *x; PympzObject *result, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("t_mod_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) { return NULL; } x = PyTuple_GET_ITEM(args, 0); if (!(result = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x)) { mpz_tdiv_r_2exp(result->z, Pympz_AS_MPZ(x), nbits); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("t_mod_2exp() requires 'mpz','int' arguments"); Py_DECREF((PyObject*)result); return NULL; } mpz_tdiv_r_2exp(result->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); } return (PyObject*)result; } /* ************************************************************************** * pack and unpack methods * * Both pack and unpack use a devious trick when stuffing values into the * internal structure of an mpz_t. By setting a bit beyond the range of * interest, we are guaranteed that memory will remain available. When * the bit is cleared, it also triggers normalization of the value by * accounting for leading bits that are zero. ************************************************************************** */ PyDoc_STRVAR(doc_gmpy_pack, "pack(lst, n) -> mpz\n\n" "Pack a list of integers 'lst' into a single 'mpz' by concatenating\n" "each integer element of 'lst' after padding to length n bits. Raises\n" "an error if any integer is negative or greater than n bits in\n" "length."); static PyObject * Pygmpy_pack(PyObject *self, PyObject *args) { Py_ssize_t nbits, total_bits, index, lst_count, i, temp_bits, limb_count, tempx_bits; PyObject *lst; mpz_t temp; PympzObject *result, *tempx = 0; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("pack() requires 'list','int' arguments"); return NULL; } nbits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (nbits == -1 && PyErr_Occurred()) { TYPE_ERROR("pack() requires 'list','int' arguments"); return NULL; } if (nbits <= 0) { VALUE_ERROR("pack() requires n > 0"); return NULL; } if (!PyList_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("pack() requires 'list','int' arguments"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; lst = PyTuple_GET_ITEM(args, 0); lst_count = PyList_GET_SIZE(lst); total_bits = nbits * lst_count; mpz_set_ui(result->z, 0); mpz_setbit(result->z, total_bits + (mp_bits_per_limb * 2)); mpz_inoc(temp); mpz_set_ui(temp, 0); limb_count = 0; tempx_bits = 0; for (index = 0; index < lst_count; index++) { if (!(tempx = Pympz_From_Integer(PyList_GetItem(lst, index))) || (mpz_sgn(tempx->z) < 0) || (mpz_sizeinbase(tempx->z,2) > (size_t)nbits)) { TYPE_ERROR("pack() requires list elements be positive integers < 2^n bits"); mpz_cloc(temp); Py_XDECREF((PyObject*)tempx); Py_DECREF((PyObject*)result); return NULL; } mpz_mul_2exp(tempx->z, tempx->z, tempx_bits); mpz_add(temp, temp, tempx->z); tempx_bits += nbits; i = 0; temp_bits = mpz_sizeinbase(temp, 2) * mpz_sgn(temp); while (tempx_bits >= mp_bits_per_limb) { if (temp_bits > 0) { result->z->_mp_d[limb_count] = mpz_getlimbn(temp, i); } i += 1; tempx_bits -= mp_bits_per_limb; limb_count += 1; temp_bits -= mp_bits_per_limb; } if (temp_bits > 0) { mpz_tdiv_q_2exp(temp, temp, mp_bits_per_limb * i); } else { mpz_set_ui(temp, 0); } Py_DECREF((PyObject*)tempx); } result->z->_mp_d[limb_count] = mpz_getlimbn(temp, 0); mpz_clrbit(result->z, total_bits + (mp_bits_per_limb * 2)); mpz_cloc(temp); return (PyObject*)result; } PyDoc_STRVAR(doc_gmpy_unpack, "unpack(x, n) -> list\n\n" "Unpack an integer 'x' into a list of n-bit values. Equivalent to\n" "repeated division by 2**n. Raises error if 'x' is negative."); static PyObject * Pygmpy_unpack(PyObject *self, PyObject *args) { Py_ssize_t nbits, total_bits, index = 0, lst_count, i, temp_bits = 0, extra_bits = 0; Py_ssize_t guard_bit, lst_ptr = 0; PyObject *result; mpz_t temp; mp_limb_t extra = 0; PympzObject *item, *tempx = 0; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("unpack() requires 'int','int' arguments"); return NULL; } nbits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (nbits == -1 && PyErr_Occurred()) { TYPE_ERROR("unpack() requires 'int','int' arguments"); return NULL; } if (nbits <= 0) { VALUE_ERROR("unpack() requires n > 0"); return NULL; } if (!(tempx = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)))) { TYPE_ERROR("unpack() requires 'int','int' arguments"); return NULL; } if (mpz_sgn(tempx->z) < 0) { VALUE_ERROR("unpack() requires x >= 0"); return NULL; } total_bits = mpz_sizeinbase(tempx->z, 2) * mpz_sgn(tempx->z); lst_count = total_bits / nbits; if ((total_bits % nbits) || !lst_count) lst_count += 1; if (!(result = PyList_New(lst_count))) { Py_DECREF((PyObject*)tempx); return NULL; } if (mpz_sgn(tempx->z) == 0) { if (!(item = (PympzObject*)Pympz_new())) { Py_DECREF((PyObject*)tempx); Py_DECREF(result); return NULL; } mpz_set_ui(item->z, 0); PyList_SET_ITEM(result, 0, (PyObject*)item); Py_DECREF((PyObject*)tempx); return result; } mpz_inoc(temp); guard_bit = nbits + (2 * mp_bits_per_limb); while (lst_ptr < lst_count) { i = 0; temp_bits = 0; mpz_set_ui(temp, 0); mpz_setbit(temp, guard_bit); while (temp_bits + extra_bits < nbits) { temp->_mp_d[i++] = mpz_getlimbn(tempx->z, index++); temp_bits += mp_bits_per_limb; } mpz_clrbit(temp, guard_bit); mpz_mul_2exp(temp, temp, extra_bits); if (mpz_sgn(temp) == 0 && extra != 0) { mpz_set_ui(temp, 1); temp->_mp_d[0] = extra; } else { mpn_add_1(temp->_mp_d, temp->_mp_d, mpz_size(temp), extra); } temp_bits += extra_bits; while ((lst_ptr < lst_count) && (temp_bits >= nbits)) { if(!(item = (PympzObject*)Pympz_new())) { mpz_cloc(temp); Py_DECREF((PyObject*)tempx); Py_DECREF(result); return NULL; } mpz_tdiv_r_2exp(item->z, temp, nbits); PyList_SET_ITEM(result, lst_ptr++, (PyObject*)item); mpz_tdiv_q_2exp(temp, temp, nbits); temp_bits -= nbits; } extra = mpz_getlimbn(temp, 0); extra_bits = temp_bits; } Py_DECREF((PyObject*)tempx); mpz_cloc(temp); return result; } gmpy2-2.0.7/src/gmpy_mpz_divmod.h0000666000000000000000000000535312542614506015437 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_divmod.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MPZ_DIVMOD_H #define GMPY_MPZ_DIVMOD_H #ifdef __cplusplus extern "C" { #endif static PyObject * Pygmpy_c_divmod(PyObject *self, PyObject *args); static PyObject * Pygmpy_c_div(PyObject *self, PyObject *args); static PyObject * Pygmpy_c_mod(PyObject *self, PyObject *args); static PyObject * Pygmpy_f_divmod(PyObject *self, PyObject *args); static PyObject * Pygmpy_f_div(PyObject *self, PyObject *args); static PyObject * Pygmpy_f_mod(PyObject *self, PyObject *args); static PyObject * Pygmpy_t_divmod(PyObject *self, PyObject *args); static PyObject * Pygmpy_t_div(PyObject *self, PyObject *args); static PyObject * Pygmpy_t_mod(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpz_divmod.c0000666000000000000000000004355612542614506015441 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz_divmod.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file contains functions related to division and remainder. */ /* ************************************************************************** * Ceiling division and remainder. ************************************************************************** */ PyDoc_STRVAR(doc_gmpy_c_divmod, "c_divmod(x, y) -> (quotient, remainder)\n\n" "Return the quotient and remainder of x divided by y. The quotient\n" "is rounded towards +Inf (ceiling rounding) and the remainder will\n" "have the opposite sign of y. x and y must be integers."); static PyObject * Pygmpy_c_divmod(PyObject *self, PyObject *args) { PyObject *x, *y, *result; PympzObject *q, *r, *tempx, *tempy; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_divmod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); CREATE_TWO_MPZ_TUPLE(q, r, result); if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if(mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("c_divmod() division by 0"); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_cdiv_qr(q->z, r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("c_divmod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("c_divmod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_cdiv_qr(q->z, r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } PyTuple_SET_ITEM(result, 0, (PyObject*)q); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; } PyDoc_STRVAR(doc_gmpy_c_div, "c_div(x, y) -> quotient\n\n" "Return the quotient of x divided by y. The quotient is rounded\n" "towards +Inf (ceiling rounding). x and y must be integers."); static PyObject * Pygmpy_c_div(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *q, *tempx, *tempy; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_div() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(q = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("c_div() division by 0"); Py_DECREF((PyObject*)q); return NULL; } mpz_cdiv_q(q->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("c_div() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("c_div() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } mpz_cdiv_q(q->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)q; } PyDoc_STRVAR(doc_gmpy_c_mod, "c_mod(x, y) -> remainder\n\n" "Return the remainder of x divided by y. The remainder will have\n" "the opposite sign of y. x and y must be integers."); static PyObject * Pygmpy_c_mod(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *r, *tempx, *tempy; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_mod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(r = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if(mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("c_mod() division by 0"); Py_DECREF((PyObject*)r); return NULL; } mpz_cdiv_r(r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("c_mod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("c_mod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } mpz_cdiv_r(r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)r; } /* ************************************************************************** * Floor division and remainder. ************************************************************************** */ PyDoc_STRVAR(doc_gmpy_f_divmod, "f_divmod(x, y) -> (quotient, remainder)\n\n" "Return the quotient and remainder of x divided by y. The quotient\n" "is rounded towards -Inf (floor rounding) and the remainder will\n" "have the same sign as y. x and y must be integers."); static PyObject * Pygmpy_f_divmod(PyObject *self, PyObject *args) { PyObject *x, *y, *result; PympzObject *q, *r, *tempx, *tempy; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("f_divmod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); CREATE_TWO_MPZ_TUPLE(q, r, result); if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("f_divmod() division by 0"); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_fdiv_qr(q->z, r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("f_divmod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("f_divmod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_fdiv_qr(q->z, r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } PyTuple_SET_ITEM(result, 0, (PyObject*)q); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; } PyDoc_STRVAR(doc_gmpy_f_div, "f_div(x, y) -> quotient\n\n" "Return the quotient of x divided by y. The quotient is rounded\n" "towards -Inf (floor rounding). x and y must be integers."); static PyObject * Pygmpy_f_div(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *q, *tempx, *tempy; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("f_div() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(q = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("f_div() division by 0"); Py_DECREF((PyObject*)q); return NULL; } mpz_fdiv_q(q->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("f_div() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("f_div() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } mpz_fdiv_q(q->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)q; } PyDoc_STRVAR(doc_gmpy_f_mod, "f_mod(x, y) -> remainder\n\n" "Return the remainder of x divided by y. The remainder will have\n" "the same sign as y. x and y must be integers."); static PyObject * Pygmpy_f_mod(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *r, *tempx, *tempy; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("f_mod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(r = (PympzObject*)Pympz_new())) return NULL; if(CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("f_mod() division by 0"); Py_DECREF((PyObject*)r); return NULL; } mpz_fdiv_r(r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("f_mod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("f_mod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } mpz_fdiv_r(r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)r; } /* ************************************************************************** * Truncating division and remainder. ************************************************************************** */ PyDoc_STRVAR(doc_gmpy_t_divmod, "t_divmod(x, y) -> (quotient, remainder)\n\n" "Return the quotient and remainder of x divided by y. The quotient\n" "is rounded towards zero (truncation) and the remainder will have\n" "the same sign as x. x and y must be integers."); static PyObject * Pygmpy_t_divmod(PyObject *self, PyObject *args) { PyObject *x, *y, *result; PympzObject *q, *r, *tempx, *tempy; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("t_divmod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); CREATE_TWO_MPZ_TUPLE(q, r, result); if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("t_divmod() division by 0"); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_tdiv_qr(q->z, r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("t_divmod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("t_divmod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_tdiv_qr(q->z, r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } PyTuple_SET_ITEM(result, 0, (PyObject*)q); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; } PyDoc_STRVAR(doc_gmpy_t_div, "t_div(x, y) -> quotient\n\n" "Return the quotient of x divided by y. The quotient is rounded\n" "towards 0. x and y must be integers."); static PyObject * Pygmpy_t_div(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *q, *tempx, *tempy; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("t_div() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(q = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("t_div() division by 0"); Py_DECREF((PyObject*)q); return NULL; } mpz_tdiv_q(q->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("t_div() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("t_div() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } mpz_tdiv_q(q->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)q; } PyDoc_STRVAR(doc_gmpy_t_mod, "t_mod(x, y) -> remainder\n\n" "Return the remainder of x divided by y. The remainder will have\n" "the same sign as x. x and y must be integers."); static PyObject * Pygmpy_t_mod(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *r, *tempx, *tempy; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("t_mod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(r = (PympzObject*)Pympz_new())) return NULL; if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("t_mod() division by 0"); Py_DECREF((PyObject*)r); return NULL; } mpz_tdiv_r(r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("t_mod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("t_mod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } mpz_tdiv_r(r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)r; } gmpy2-2.0.7/src/gmpy_mpz.h0000666000000000000000000001541612542614506014076 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MPZ_H #define GMPY_MPZ_H #ifdef __cplusplus extern "C" { #endif typedef struct { PyObject_HEAD mpz_t z; Py_hash_t hash_cache; } PympzObject; #define Pympz_AS_MPZ(obj) (((PympzObject *)(obj))->z) static PyTypeObject Pympz_Type; #define Pympz_Check(v) (((PyObject*)v)->ob_type == &Pympz_Type) static PyObject * Pygmpy_mpz(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pympz_digits(PyObject *self, PyObject *args); static PyObject * Pympz_num_digits(PyObject *self, PyObject *args); static PyObject * Pympz_bit_length(PyObject *self, PyObject *other); static PyObject * Pympz_bit_mask(PyObject *self, PyObject *other); static PyObject * Pympz_bit_scan0(PyObject *self, PyObject *args); static PyObject * Pympz_bit_scan1(PyObject *self, PyObject *args); static PyObject * Pympz_popcount(PyObject *self, PyObject *other); static PyObject * Pygmpy_bit_test(PyObject *self, PyObject *args); static PyObject * Pympz_bit_test(PyObject *self, PyObject *other); static PyObject * Pygmpy_bit_clear(PyObject *self, PyObject *args); static PyObject * Pympz_bit_clear(PyObject *self, PyObject *other); static PyObject * Pygmpy_bit_set(PyObject *self, PyObject *args); static PyObject * Pympz_bit_set(PyObject *self, PyObject *other); static PyObject * Pygmpy_bit_flip(PyObject *self, PyObject *args); static PyObject * Pympz_bit_flip(PyObject *self, PyObject *other); static PyObject * Pympz_iroot(PyObject *self, PyObject *args); static PyObject * Pympz_iroot_rem(PyObject *self, PyObject *args); static PyObject * Pympz_sign(PyObject *self, PyObject *other); static PyObject * Pympz_abs(PympzObject *self); static PyObject * Pympz_neg(PympzObject *self); static PyObject * Pympz_pos(PympzObject *self); static PyObject * Pympz_ceil(PyObject *self, PyObject *other); static PyObject * Pympz_floor(PyObject *self, PyObject *other); static PyObject * Pympz_round(PyObject *self, PyObject *other); static PyObject * Pympz_trunc(PyObject *self, PyObject *other); static PyObject * Pympz_square(PyObject *self, PyObject *other); static PyObject * Pympz_pow(PyObject *b, PyObject *e, PyObject *m); static int Pympz_nonzero(PympzObject *self); static PyObject * Pympz_com(PympzObject *self); static PyObject * Pympz_and(PyObject *self, PyObject *other); static PyObject * Pympz_ior(PyObject *self, PyObject *other); static PyObject * Pympz_xor(PyObject *self, PyObject *other); static PyObject * Pympz_rshift(PyObject *self, PyObject *other); static PyObject * Pympz_lshift(PyObject *self, PyObject *other); #if PY_MAJOR_VERSION < 3 /* hex/oct formatting (mpz-only) */ static PyObject * Pympz_oct(PympzObject *self); static PyObject * Pympz_hex(PympzObject *self); #endif static Py_hash_t Pympz_hash(PympzObject *self); static PyObject * Pygmpy_gcd(PyObject *self, PyObject *args); static PyObject * Pygmpy_lcm(PyObject *self, PyObject *args); static PyObject * Pygmpy_gcdext(PyObject *self, PyObject *args); static PyObject * Pygmpy_divm(PyObject *self, PyObject *args); static PyObject * Pygmpy_fac(PyObject *self, PyObject *other); static PyObject * Pygmpy_fib(PyObject *self, PyObject *other); static PyObject * Pygmpy_fib2(PyObject *self, PyObject *other); static PyObject * Pygmpy_lucas(PyObject *self, PyObject *other); static PyObject * Pygmpy_lucas2(PyObject *self, PyObject *other); static PyObject * Pympz_bincoef(PyObject *self, PyObject *args); static PyObject * Pympz_isqrt(PyObject *self, PyObject *other); static PyObject * Pympz_isqrt_rem(PyObject *self, PyObject *args); static PyObject * Pympz_remove(PyObject *self, PyObject *args); static PyObject * Pygmpy_invert(PyObject *self, PyObject *args); static PyObject * Pympz_hamdist(PyObject *self, PyObject *args); static PyObject * Pygmpy_divexact(PyObject *self, PyObject *args); static PyObject * Pympz_is_square(PyObject *self, PyObject *other); static PyObject * Pympz_is_power(PyObject *self, PyObject *other); static PyObject * Pympz_is_prime(PyObject *self, PyObject *args); static PyObject * Pympz_next_prime(PyObject *self, PyObject *other); static PyObject * Pympz_jacobi(PyObject *self, PyObject *args); static PyObject * Pympz_legendre(PyObject *self, PyObject *args); static PyObject * Pympz_kronecker(PyObject *self, PyObject *args); static PyObject * Pympz_is_even(PyObject *self, PyObject *other); static PyObject * Pympz_is_odd(PyObject *self, PyObject *other); static Py_ssize_t Pympz_nbits(PympzObject *self); static PyObject * Pympz_subscript(PympzObject *self, PyObject *item); static PyObject * Pympz_format(PyObject *self, PyObject *args); static PyObject * Pympz_add(PyObject *self, PyObject *args); static PyObject * Pympz_sub(PyObject *self, PyObject *args); static PyObject * Pympz_mul(PyObject *self, PyObject *args); static PyObject * Pympz_div(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpz.c0000666000000000000000000022230212542614506014063 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpz.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ PyDoc_STRVAR(doc_mpz, "mpz() -> mpz(0)\n\n" " If no argument is given, return mpz(0).\n\n" "mpz(n) -> mpz\n\n" " Return an 'mpz' object with a numeric value 'n' (truncating n\n" " to its integer part if it's a Fraction, 'mpq', Decimal, float\n" " or 'mpfr').\n\n" "mpz(s[, base=0]):\n\n" " Return an 'mpz' object from a string 's' made of digits in the\n" " given base. If base=0, binary, octal, or hex Python strings\n" " are recognized by leading 0b, 0o, or 0x characters, otherwise\n" " the string is assumed to be decimal. Values for base can range\n" " between 2 and 62."); static PyObject * Pygmpy_mpz(PyObject *self, PyObject *args, PyObject *keywds) { PympzObject *result = 0; PyObject *n = 0; int base = 0; Py_ssize_t argc; static char *kwlist[] = {"n", "base", NULL }; /* Optimize the most common use case */ argc = PyTuple_Size(args); if (argc == 0) { if ((result = (PympzObject*)Pympz_new())) { mpz_set_ui(result->z, 0); } return (PyObject*)result; } if (argc == 1) { n = PyTuple_GetItem(args, 0); #ifdef WITHMPFR if (isReal(n) && !keywds) { #else if ((isRational(n) || PyFloat_Check(n)) && !keywds) { #endif result = Pympz_From_Number(n); if (!result && !PyErr_Occurred()) TYPE_ERROR("mpz() requires numeric or string argument"); return (PyObject*)result; } } if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) return NULL; if ((base!=0) && ((base<2)||(base>62))) { VALUE_ERROR("base for mpz() must be 0 or in the " "interval 2 ... 62"); return NULL; } if (PyStrOrUnicode_Check(n)) { /* build-from-string (ascii or unicode) */ result = Pympz_From_PyStr(n, base); } else { if (argc==2 || (argc == 1 && keywds)) TYPE_ERROR("mpz() with non-string argument needs exactly " "1 argument"); else { result = Pympz_From_Number(n); if (!result && !PyErr_Occurred()) TYPE_ERROR("mpz() requires numeric or string argument"); } } return (PyObject*)result; } /* Functions that operate strictly on mpz or xmpz. */ /* produce digits for an mpz in requested base, default 10 */ PyDoc_STRVAR(doc_mpz_digits, "x.digits([base=10]) -> string\n\n" "Return Python string representing x in the given base. Values for\n" "base can range between 2 to 62. A leading '-' is present if x<0\n" "but no leading '+' is present if x>=0."); static PyObject * Pympz_digits(PyObject *self, PyObject *args) { long base = 10; PyObject *result; PARSE_ONE_MPZ_OPT_CLONG(&base, "digits() requires 'int' argument for base"); if ((base < 2) || (base > 62)) { VALUE_ERROR("base must be in the interval 2 ... 62"); Py_DECREF(self); return NULL; } result = Pympz_To_PyStr((PympzObject*)self, (int)base, 16); Py_DECREF(self); return result; } /* return number-of-digits for an mpz in requested base, default 10 */ PyDoc_STRVAR(doc_num_digitsm, "x.num_digits([base=10]) -> int\n\n" "Return length of string representing the absolute value of x in\n" "the given base. Values for base can range between 2 and 62. The\n" "value returned may be 1 too large."); PyDoc_STRVAR(doc_num_digitsg, "num_digits(x[, base=10]) -> int\n\n" "Return length of string representing the absolute value of x in\n" "the given base. Values for base can range between 2 and 62. The\n" "value returned may be 1 too large."); static PyObject * Pympz_num_digits(PyObject *self, PyObject *args) { long base = 10; PyObject *result; PARSE_ONE_MPZ_OPT_CLONG(&base, "num_digits() requires 'mpz',['int'] arguments"); if ((base < 2) || (base > 62)) { VALUE_ERROR("base must be in the interval 2 ... 62"); Py_DECREF(self); return NULL; } result = PyIntOrLong_FromSize_t(mpz_sizeinbase(Pympz_AS_MPZ(self), (int)base)); Py_DECREF(self); return result; } PyDoc_STRVAR(doc_bit_lengthm, "x.bit_length() -> int\n\n" "Return the number of significant bits in the radix-2\n" "representation of x. Note: bit_length(0) returns 0."); PyDoc_STRVAR(doc_bit_lengthg, "x.bit_length() -> int\n\n" "Return the number of significant bits in the radix-2\n" "representation of x. Note: mpz(0).bit_length() returns 0."); static PyObject * Pympz_bit_length(PyObject *self, PyObject *other) { size_t i = 0; PympzObject* tempx; if (self && (CHECK_MPZANY(self))) { if (mpz_size(Pympz_AS_MPZ(self))) i = mpz_sizeinbase(Pympz_AS_MPZ(self), 2); } else if(CHECK_MPZANY(other)) { if (mpz_size(Pympz_AS_MPZ(other))) i = mpz_sizeinbase(Pympz_AS_MPZ(other), 2); } else { if (!(tempx = Pympz_From_Integer(other))) { TYPE_ERROR("bit_length() requires 'mpz' argument"); return NULL; } else { if (mpz_size(Pympz_AS_MPZ(tempx))) i = mpz_sizeinbase(tempx->z, 2); Py_DECREF((PyObject*)tempx); } } return PyIntOrLong_FromSize_t(i); } PyDoc_STRVAR(doc_bit_maskg, "bit_mask(n) -> mpz\n\n" "Return an 'mpz' exactly n bits in length with all bits set.\n"); static PyObject * Pympz_bit_mask(PyObject *self, PyObject *other) { Py_ssize_t i = 0; PympzObject* result; i = ssize_t_From_Integer(other); if (i == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_mask() requires 'int' argument"); return NULL; } if (i < 0) { VALUE_ERROR("mask length must be >= 0"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_set_ui(result->z, 1); mpz_mul_2exp(result->z, result->z, i); mpz_sub_ui(result->z, result->z, 1); return (PyObject*)result; } /* return scan0/scan1 for an mpz */ PyDoc_STRVAR(doc_bit_scan0m, "x.bit_scan0(n=0) -> int\n\n" "Return the index of the first 0-bit of x with index >= n. n >= 0.\n" "If there are no more 0-bits in x at or above index n (which can\n" "only happen for x<0, assuming an infinitely long 2's complement\n" "format), then None is returned."); PyDoc_STRVAR(doc_bit_scan0g, "bit_scan0(x, n=0) -> int\n\n" "Return the index of the first 0-bit of x with index >= n. n >= 0.\n" "If there are no more 0-bits in x at or above index n (which can\n" "only happen for x<0, assuming an infinitely long 2's complement\n" "format), then None is returned."); static PyObject * Pympz_bit_scan0(PyObject *self, PyObject *args) { Py_ssize_t maxbit, starting_bit = 0; mp_bitcnt_t index; PARSE_ONE_MPZ_OPT_SSIZE_T(&starting_bit, "bit_scan0() requires 'mpz',['int'] arguments"); if (starting_bit < 0) { VALUE_ERROR("starting bit must be >= 0"); Py_DECREF(self); return NULL; } maxbit = mpz_sizeinbase(Pympz_AS_MPZ(self), 2); if (starting_bit > maxbit) { if (mpz_sgn(Pympz_AS_MPZ(self))<0) { Py_DECREF(self); Py_RETURN_NONE; } else { return PyIntOrLong_FromSsize_t(starting_bit); } } else { index = mpz_scan0(Pympz_AS_MPZ(self), (mp_bitcnt_t)starting_bit); Py_DECREF(self); if (index == (mp_bitcnt_t)-1) { Py_RETURN_NONE; } else { return PyIntOrLong_FromSize_t(index); } } } PyDoc_STRVAR(doc_bit_scan1m, "x.bit_scan1(n=0) -> int\n\n" "Return the index of the first 1-bit of x with index >= n. n >= 0.\n" "If there are no more 1-bits in x at or above index n (which can\n" "only happen for x>=0, assuming an infinitely long 2's complement\n" "format), then None is returned."); PyDoc_STRVAR(doc_bit_scan1g, "bit_scan1(x, n=0) -> int\n\n" "Return the index of the first 1-bit of x with index >= n. n >= 0.\n" "If there are no more 1-bits in x at or above index n (which can\n" "only happen for x>=0, assuming an infinitely long 2's complement\n" "format), then None is returned."); static PyObject * Pympz_bit_scan1(PyObject *self, PyObject *args) { Py_ssize_t maxbit, starting_bit = 0; mp_bitcnt_t index; PARSE_ONE_MPZ_OPT_SSIZE_T(&starting_bit, "bit_scan1() requires 'mpz',['int'] arguments"); if (starting_bit < 0) { VALUE_ERROR("starting bit must be >= 0"); Py_DECREF(self); return NULL; } maxbit = mpz_sizeinbase(Pympz_AS_MPZ(self), 2); if (starting_bit >= maxbit) { if (mpz_sgn(Pympz_AS_MPZ(self))>=0) { Py_DECREF(self); Py_RETURN_NONE; } else { return PyIntOrLong_FromSsize_t(starting_bit); } } else { index = mpz_scan1(Pympz_AS_MPZ(self), (mp_bitcnt_t)starting_bit); Py_DECREF(self); if (index == (mp_bitcnt_t)-1) { Py_RETURN_NONE; } else { return PyIntOrLong_FromSize_t(index); } } } /* return population-count (# of 1-bits) for an mpz */ PyDoc_STRVAR(doc_popcountg, "popcount(x) -> int\n\n" "Return the number of 1-bits set in x. If x<0, the number of\n" "1-bits is infinite so -1 is returned in that case."); static PyObject * Pympz_popcount(PyObject *self, PyObject *other) { Py_ssize_t temp; PympzObject *tempx; if (self && (CHECK_MPZANY(self))) return PyIntOrLong_FromSsize_t(mpz_popcount(Pympz_AS_MPZ(self))); else if(CHECK_MPZANY(other)) return PyIntOrLong_FromSsize_t(mpz_popcount(Pympz_AS_MPZ(other))); else { if ((tempx = Pympz_From_Integer(other))) { temp = mpz_popcount(tempx->z); Py_DECREF((PyObject*)tempx); return PyIntOrLong_FromSsize_t(temp); } else { TYPE_ERROR("popcount() requires 'mpz' argument"); return NULL; } } } /* get & return one bit from an mpz */ PyDoc_STRVAR(doc_bit_testg, "bit_test(x, n) -> bool\n\n" "Return the value of the n-th bit of x."); static PyObject * Pygmpy_bit_test(PyObject *self, PyObject *args) { Py_ssize_t bit_index; int temp; PyObject *x; PympzObject *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("bit_test() requires 'mpz','int' arguments"); return NULL; } bit_index = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_test() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } x = PyTuple_GET_ITEM(args, 0); if (CHECK_MPZANY(x)) { temp = mpz_tstbit(Pympz_AS_MPZ(x), bit_index); } else { if (!(tempx = Pympz_From_Integer(x))) { TYPE_ERROR("bit_test() requires 'mpz','int' arguments"); return NULL; } temp = mpz_tstbit(tempx->z, bit_index); Py_DECREF((PyObject*)tempx); } if (temp) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_bit_testm, "x.bit_test(n) -> bool\n\n" "Return the value of the n-th bit of x."); static PyObject * Pympz_bit_test(PyObject *self, PyObject *other) { Py_ssize_t bit_index; bit_index = ssize_t_From_Integer(other); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_test() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } if (mpz_tstbit(Pympz_AS_MPZ(self), bit_index)) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_bit_clearg, "bit_clear(x, n) -> mpz\n\n" "Return a copy of x with the n-th bit cleared."); static PyObject * Pygmpy_bit_clear(PyObject *self, PyObject *args) { Py_ssize_t bit_index; PyObject *x; PympzObject *result; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("bit_clear() requires 'mpz','int' arguments"); return NULL; } bit_index = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_clear() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } x = PyTuple_GET_ITEM(args, 0); if (CHECK_MPZANY(x)) { if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_set(result->z, Pympz_AS_MPZ(x)); mpz_clrbit(result->z, bit_index); } else { if (!(result = Pympz_From_Integer(x))) { TYPE_ERROR("bit_clear() requires 'mpz','int' arguments"); return NULL; } mpz_clrbit(result->z, bit_index); } return (PyObject*)result; } PyDoc_STRVAR(doc_bit_clearm, "x.bit_clear(n) -> mpz\n\n" "Return a copy of x with the n-th bit cleared."); static PyObject * Pympz_bit_clear(PyObject *self, PyObject *other) { Py_ssize_t bit_index; PympzObject *result; bit_index = ssize_t_From_Integer(other); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_clear() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_set(result->z, Pympz_AS_MPZ(self)); mpz_clrbit(result->z, bit_index); return (PyObject*)result; } PyDoc_STRVAR(doc_bit_setg, "bit_set(x, n) -> mpz\n\n" "Return a copy of x with the n-th bit set."); static PyObject * Pygmpy_bit_set(PyObject *self, PyObject *args) { Py_ssize_t bit_index; PyObject *x; PympzObject *result; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("bit_set() requires 'mpz','int' arguments"); return NULL; } bit_index = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_set() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } x = PyTuple_GET_ITEM(args, 0); if (CHECK_MPZANY(x)) { if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_set(result->z, Pympz_AS_MPZ(x)); mpz_setbit(result->z, bit_index); } else { if (!(result = Pympz_From_Integer(x))) { TYPE_ERROR("bit_set() requires 'mpz','int' arguments"); return NULL; } mpz_setbit(result->z, bit_index); } return (PyObject*)result; } PyDoc_STRVAR(doc_bit_setm, "x.bit_set(n) -> mpz\n\n" "Return a copy of x with the n-th bit set."); static PyObject * Pympz_bit_set(PyObject *self, PyObject *other) { Py_ssize_t bit_index; PympzObject *result; bit_index = ssize_t_From_Integer(other); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_set() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_set(result->z, Pympz_AS_MPZ(self)); mpz_setbit(result->z, bit_index); return (PyObject*)result; } PyDoc_STRVAR(doc_bit_flipg, "bit_flip(x, n) -> mpz\n\n" "Return a copy of x with the n-th bit inverted."); static PyObject * Pygmpy_bit_flip(PyObject *self, PyObject *args) { Py_ssize_t bit_index; PyObject *x; PympzObject *result; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("bit_flip() requires 'mpz','int' arguments"); return NULL; } bit_index = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_flip() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } x = PyTuple_GET_ITEM(args, 0); if (CHECK_MPZANY(x)) { if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_set(result->z, Pympz_AS_MPZ(x)); mpz_combit(result->z, bit_index); } else { if (!(result = Pympz_From_Integer(x))) { TYPE_ERROR("bit_flip() requires 'mpz','int' arguments"); return NULL; } mpz_combit(result->z, bit_index); } return (PyObject*)result; } PyDoc_STRVAR(doc_bit_flipm, "x.bit_flip(n) -> mpz\n\n" "Return a copy of x with the n-th bit inverted."); static PyObject * Pympz_bit_flip(PyObject *self, PyObject *other) { Py_ssize_t bit_index; PympzObject *result; bit_index = ssize_t_From_Integer(other); if (bit_index == -1 && PyErr_Occurred()) { TYPE_ERROR("bit_flip() requires 'mpz','int' arguments"); return NULL; } if (bit_index < 0) { VALUE_ERROR("bit_index must be >= 0"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_set(result->z, Pympz_AS_MPZ(self)); mpz_combit(result->z, bit_index); return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_iroot, "iroot(x,n) -> (number, boolean)\n\n" "Return the integer n-th root of x and boolean value that is True\n" "iff the root is exact. x >= 0. n > 0."); static PyObject * Pympz_iroot(PyObject *self, PyObject *args) { mpir_si n; int exact; PympzObject *s = 0; PyObject *result = 0; PARSE_ONE_MPZ_REQ_SI(&n, "iroot() requires 'mpz','int' arguments"); if (n <= 0) { VALUE_ERROR("n must be > 0"); Py_DECREF(self); return NULL; } else if (n>1) { if (mpz_sgn(Pympz_AS_MPZ(self))<0) { VALUE_ERROR("iroot() of negative number"); Py_DECREF(self); return NULL; } } if (!(s = (PympzObject*)Pympz_new()) || !(result = PyTuple_New(2))) { Py_DECREF(self); Py_XDECREF((PyObject*)s); Py_XDECREF(result); return NULL; } exact = mpz_root(s->z, Pympz_AS_MPZ(self), n); Py_DECREF(self); PyTuple_SET_ITEM(result, 0, (PyObject*)s); PyTuple_SET_ITEM(result, 1, (PyObject*)PyBool_FromLong(exact)); return result; } PyDoc_STRVAR(doc_mpz_iroot_rem, "iroot_rem(x,n) -> (number, number)\n\n" "Return a 2-element tuple (y,r), such that y is the integer n-th\n" "root of x and x=y**n + r. x >= 0. n > 0."); static PyObject * Pympz_iroot_rem(PyObject *self, PyObject *args) { mpir_si n; PympzObject *r = 0, *y = 0; PyObject *result = 0; PARSE_ONE_MPZ_REQ_SI(&n, "iroot_rem() requires 'mpz','int' arguments"); if (n <= 0) { VALUE_ERROR("n must be > 0"); Py_DECREF(self); return NULL; } else if (n>1) { if (mpz_sgn(Pympz_AS_MPZ(self))<0) { VALUE_ERROR("iroot_rem() of negative number"); Py_DECREF(self); return NULL; } } y = (PympzObject*)Pympz_new(); r = (PympzObject*)Pympz_new(); result = PyTuple_New(2); if (!y || !r || !result) { Py_DECREF(self); Py_XDECREF(result); Py_XDECREF((PyObject*)y); Py_XDECREF((PyObject*)r); return NULL; } mpz_rootrem(y->z, r->z, Pympz_AS_MPZ(self), n); Py_DECREF(self); PyTuple_SET_ITEM(result, 0, (PyObject*)y); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; } static PyObject * Pympz_sign(PyObject *self, PyObject *other) { long res; PympzObject* tempx; if (self && (CHECK_MPZANY(self))) { res = mpz_sgn(Pympz_AS_MPZ(self)); } else if (CHECK_MPZANY(other)) { res = mpz_sgn(Pympz_AS_MPZ(other)); } else { if (!(tempx = Pympz_From_Integer(other))) { TYPE_ERROR("sign() requires 'mpz' argument"); return NULL; } else { res = mpz_sgn(tempx->z); Py_DECREF((PyObject*)tempx); } } return PyIntOrLong_FromLong(res); } static PyObject * Pympz_abs(PympzObject *self) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) mpz_abs(result->z, self->z); return (PyObject*)result; } static PyObject * Pympz_neg(PympzObject *self) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) mpz_neg(result->z, self->z); return (PyObject*)result; } static PyObject * Pympz_pos(PympzObject *self) { Py_INCREF((PyObject*)self); return (PyObject*)self; } PyDoc_STRVAR(doc_mpz_ceil, "Ceiling of an mpz returns itself."); static PyObject * Pympz_ceil(PyObject *self, PyObject *other) { Py_INCREF(self); return self; } PyDoc_STRVAR(doc_mpz_floor, "Floor of an mpz returns itself."); static PyObject * Pympz_floor(PyObject *self, PyObject *other) { Py_INCREF(self); return self; } PyDoc_STRVAR(doc_mpz_trunc, "Truncating an mpz returns itself."); static PyObject * Pympz_trunc(PyObject *self, PyObject *other) { Py_INCREF(self); return self; } PyDoc_STRVAR(doc_mpz_round, "Round an mpz to power of 10."); static PyObject * Pympz_round(PyObject *self, PyObject *args) { Py_ssize_t round_digits; PympzObject *result; mpz_t temp, rem; if (PyTuple_GET_SIZE(args) == 0) { Py_INCREF(self); return self; } if (PyTuple_GET_SIZE(args) != 1) { TYPE_ERROR("Too many arguments for __round__()."); return NULL; } round_digits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0)); if (round_digits == -1 && PyErr_Occurred()) { TYPE_ERROR("__round__() requires 'int' argument"); return NULL; } if (round_digits >= 0) { Py_INCREF(self); return self; } round_digits = -round_digits; if ((result = (PympzObject*)Pympz_new())) { if ((size_t)round_digits >= mpz_sizeinbase(Pympz_AS_MPZ(self), 10)) { mpz_set_ui(result->z, 0); } else { mpz_inoc(temp); mpz_inoc(rem); mpz_ui_pow_ui(temp, 10, round_digits); mpz_fdiv_qr(result->z, rem, Pympz_AS_MPZ(self), temp); mpz_mul_2exp(rem, rem, 1); if (mpz_cmp(rem, temp) > 0) { mpz_add_ui(result->z, result->z, 1); } else if (mpz_cmp(rem, temp) == 0) { if (mpz_odd_p(result->z)) { mpz_add_ui(result->z, result->z, 1); } } mpz_mul(result->z, result->z, temp); mpz_cloc(rem); mpz_cloc(temp); } } return (PyObject*)result; } static PyObject * Pympz_square(PyObject *self, PyObject *other) { PympzObject *tempx, *result; if (!(result = (PympzObject*)Pympz_new())) return NULL; if (self && (CHECK_MPZANY(self))) { mpz_mul(result->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(self)); } else if (CHECK_MPZANY(other)) { mpz_mul(result->z, Pympz_AS_MPZ(other), Pympz_AS_MPZ(other)); } else { if (!(tempx = Pympz_From_Integer(other))) { TYPE_ERROR("square() requires 'mpz' argument"); Py_DECREF((PyObject*)result); return NULL; } else { mpz_mul(result->z, Pympz_AS_MPZ(tempx), Pympz_AS_MPZ(tempx)); Py_DECREF((PyObject*)tempx); } } return (PyObject*)result; } /* Pympz_pow is called by Pympany_pow after verifying that all the * arguments are integers, but not necessarily mpz. */ static PyObject * Pympz_pow(PyObject *b, PyObject *e, PyObject *m) { PympzObject *result, *tempb = 0, *tempe = 0, *tempm = 0; if (!(result = (PympzObject*)Pympz_new())) return NULL; tempb = Pympz_From_Integer(b); tempe = Pympz_From_Integer(e); /* m will either be a number or Py_None. */ if (m != Py_None) { tempm = Pympz_From_Integer(m); } if (!tempb || !tempe || (!tempm && (m != Py_None))) { TYPE_ERROR("Unsupported operand in mpz.pow()"); goto err; } if (m == Py_None) { /* When no modulo is present, the exponent must fit in mpir_ui * the exponent must be positive. */ mpir_ui el; if (mpz_sgn(tempe->z) < 0) { VALUE_ERROR("pow() exponent cannot be negative"); goto err; } if (!mpz_fits_ui_p(tempe->z)) { VALUE_ERROR("pow() outrageous exponent"); goto err; } el = mpz_get_ui(tempe->z); mpz_pow_ui(result->z, tempb->z, el); } else { /* Modulo exponentiation */ int sign; mpz_t mm, base, exp; sign = mpz_sgn(tempm->z); if (sign == 0) { VALUE_ERROR("pow() 3rd argument cannot be 0"); goto err; } mpz_inoc(mm); mpz_abs(mm, tempm->z); /* A negative exponent is allowed if inverse exists. */ if (mpz_sgn(tempe->z) < 0) { mpz_inoc(base); mpz_inoc(exp); if (!mpz_invert(base, tempb->z, mm)) { VALUE_ERROR("pow() base not invertible"); mpz_cloc(base); mpz_cloc(exp); mpz_cloc(mm); goto err; } else { mpz_abs(exp, tempe->z); } mpz_powm(result->z, base, exp, mm); mpz_cloc(base); mpz_cloc(exp); } else { mpz_powm(result->z, tempb->z, tempe->z, mm); } mpz_cloc(mm); /* Python uses a rather peculiar convention for negative modulos * If the modulo is negative, result should be in the interval * m < r <= 0 . */ if ((sign<0) && (mpz_sgn(Pympz_AS_MPZ(result)) > 0)) { mpz_add(result->z, result->z, tempm->z); } } Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempm); return (PyObject*)result; err: Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempm); Py_DECREF((PyObject*)result); return NULL; } PyDoc_STRVAR(doc_gmpy_powmod, "powmod(x,y,m) -> mpz\n\n" "Return (x**y) mod m. Same as the three argument version of Python's\n" "built-in pow(), but converts all three arguments to mpz."); static PyObject * Pympz_powmod(PyObject *self, PyObject *args) { PyObject *x, *y, *m; if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("powmod() requires 3 arguments."); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); m = PyTuple_GET_ITEM(args, 2); if (isInteger(x) && isInteger(y) && isInteger(m)) return Pympz_pow(x, y, m); TYPE_ERROR("powmod() argument types not supported"); return NULL; } static int Pympz_nonzero(PympzObject *self) { return mpz_sgn(self->z) != 0; } /* BIT OPERATIONS */ static PyObject * Pympz_com(PympzObject *self) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) mpz_com(result->z, Pympz_AS_MPZ(self)); return (PyObject*)result; } #define MPZ_BINOP(NAME) \ static PyObject * \ Py##NAME(PyObject *self, PyObject *other) \ { \ PympzObject *result = 0; \ if (CHECK_MPZANY(self)) { \ if (CHECK_MPZANY(other)) { \ if (!(result = (PympzObject*)Pympz_new())) \ return NULL; \ NAME(result->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); \ } \ else { \ if (!(result = Pympz_From_Integer(other))) \ return NULL; \ NAME(result->z, Pympz_AS_MPZ(self), result->z); \ } \ } \ else if (CHECK_MPZANY(other)) { \ if (!(result = Pympz_From_Integer(self))) \ return NULL; \ NAME(result->z, result->z, Pympz_AS_MPZ(other)); \ } \ else { \ Py_RETURN_NOTIMPLEMENTED; \ } \ return (PyObject*)result; \ } MPZ_BINOP(mpz_and) MPZ_BINOP(mpz_ior) MPZ_BINOP(mpz_xor) static PyObject * Pympz_rshift(PyObject *self, PyObject *other) { mpir_si count_si; int overflow; PympzObject *result, *tempa, *tempb; if (!(result = (PympzObject*)Pympz_new())) return NULL; /* Try to make mpz >> Python int/long as fast as possible. */ if (CHECK_MPZANY(self)) { if (PyIntOrLong_Check(other)) { count_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { VALUE_ERROR("outrageous shift count"); Py_DECREF((PyObject*)result); return NULL; } else if (count_si >= 0) { mpz_fdiv_q_2exp(result->z, Pympz_AS_MPZ(self), count_si); return (PyObject*)result; } else { VALUE_ERROR("negative shift count"); Py_DECREF((PyObject*)result); return NULL; } } } tempa = Pympz_From_Integer(self); tempb = Pympz_From_Integer(other); if (!tempb || !tempa) { TYPE_ERROR("Pympz_rshift() expects integer arguments"); goto err; } if (mpz_sgn(Pympz_AS_MPZ(tempb)) < 0) { VALUE_ERROR("negative shift count"); goto err; } if(!mpz_fits_si_p(Pympz_AS_MPZ(tempb))) { OVERFLOW_ERROR("outrageous shift count"); goto err; } count_si = mpz_get_si(tempb->z); mpz_fdiv_q_2exp(result->z, tempa->z, count_si); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); return (PyObject*)result; err: Py_DECREF((PyObject*)result); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); return NULL; } static PyObject * Pympz_lshift(PyObject *self, PyObject *other) { mpir_si count_si; int overflow; PympzObject *result, *tempa, *tempb; if (!(result = (PympzObject*)Pympz_new())) return NULL; /* Try to make mpz >> Python int/long as fast as possible. */ if (CHECK_MPZANY(self)) { if (PyIntOrLong_Check(other)) { count_si = PyLong_AsSIAndOverflow(other, &overflow); if (overflow) { VALUE_ERROR("outrageous shift count"); Py_DECREF((PyObject*)result); return NULL; } else if (count_si >= 0) { mpz_mul_2exp(result->z, Pympz_AS_MPZ(self), count_si); return (PyObject*)result; } else { VALUE_ERROR("negative shift count"); Py_DECREF((PyObject*)result); return NULL; } } } tempa = Pympz_From_Integer(self); tempb = Pympz_From_Integer(other); if (!tempb || !tempa) { TYPE_ERROR("Pympz_lshift() expects integer arguments"); goto err; } if (mpz_sgn(Pympz_AS_MPZ(tempb)) < 0) { VALUE_ERROR("negative shift count"); goto err; } if(!mpz_fits_si_p(Pympz_AS_MPZ(tempb))) { OVERFLOW_ERROR("outrageous shift count"); goto err; } count_si = mpz_get_si(tempb->z); mpz_mul_2exp(result->z, tempa->z, count_si); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); return (PyObject*)result; err: Py_DECREF((PyObject*)result); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); return NULL; } #if PY_MAJOR_VERSION < 3 /* hex/oct formatting (mpz-only) */ static PyObject * Pympz_oct(PympzObject *self) { return Pympz_To_PyStr(self, 8, 0); } static PyObject * Pympz_hex(PympzObject *self) { return Pympz_To_PyStr(self, 16, 0); } #endif static Py_hash_t Pympz_hash(PympzObject *self) { #ifdef _PyHASH_MODULUS Py_hash_t hash; if (self->hash_cache != -1) return self->hash_cache; hash = (Py_hash_t)mpn_mod_1(self->z->_mp_d, mpz_size(self->z), _PyHASH_MODULUS); if (mpz_sgn(self->z)<0) hash = -hash; if (hash==-1) hash = -2; return (self->hash_cache = hash); #else if (self->hash_cache != -1) return self->hash_cache; else return (self->hash_cache = mpz_pythonhash(self->z)); #endif } /* Miscellaneous gmpy functions */ PyDoc_STRVAR(doc_gcd, "gcd(a, b) -> mpz\n\n" "Return the greatest common denominator of integers a and b."); static PyObject * Pygmpy_gcd(PyObject *self, PyObject *args) { PyObject *a, *b; PympzObject *result, *tempa, *tempb; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("gcd() requires 'mpz','mpz' arguments"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; a = PyTuple_GET_ITEM(args, 0); b = PyTuple_GET_ITEM(args, 1); if (CHECK_MPZANY(a) && CHECK_MPZANY(b)) { mpz_gcd(result->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); } else { tempa = Pympz_From_Integer(a); tempb = Pympz_From_Integer(b); if (!tempa || !tempb) { TYPE_ERROR("gcd() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempa); Py_XDECREF((PyObject*)tempb); Py_DECREF((PyObject*)result); return NULL; } mpz_gcd(result->z, tempa->z, tempb->z); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); } return (PyObject*)result; } PyDoc_STRVAR(doc_lcm, "lcm(a, b) -> mpz\n\n" "Return the lowest common multiple of integers a and b."); static PyObject * Pygmpy_lcm(PyObject *self, PyObject *args) { PyObject *a, *b; PympzObject *result, *tempa, *tempb; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("lcm() requires 'mpz','mpz' arguments"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; a = PyTuple_GET_ITEM(args, 0); b = PyTuple_GET_ITEM(args, 1); if (CHECK_MPZANY(a) && CHECK_MPZANY(b)) { mpz_lcm(result->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); } else { tempa = Pympz_From_Integer(a); tempb = Pympz_From_Integer(b); if (!tempa || !tempb) { TYPE_ERROR("lcm() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempa); Py_XDECREF((PyObject*)tempb); Py_DECREF((PyObject*)result); return NULL; } mpz_lcm(result->z, tempa->z, tempb->z); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); } return (PyObject*)result; } PyDoc_STRVAR(doc_gcdext, "gcdext(a, b) - > tuple\n\n" "Return a 3-element tuple (g,s,t) such that\n" " g == gcd(a,b) and g == a*s + b*t"); static PyObject * Pygmpy_gcdext(PyObject *self, PyObject *args) { PyObject *a, *b, *result = 0; PympzObject *g = 0, *s = 0, *t = 0, *tempa, *tempb; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments"); return NULL; } g = (PympzObject*)Pympz_new(); s = (PympzObject*)Pympz_new(); t = (PympzObject*)Pympz_new(); result = PyTuple_New(3); if (!g || !s || !t || !result) { Py_XDECREF((PyObject*)g); Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)t); Py_XDECREF(result); return NULL; } a = PyTuple_GET_ITEM(args, 0); b = PyTuple_GET_ITEM(args, 1); if (CHECK_MPZANY(a) && CHECK_MPZANY(b)) { mpz_gcdext(g->z, s->z, t->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); } else { tempa = Pympz_From_Integer(a); tempb = Pympz_From_Integer(b); if(!tempa || !tempb) { TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempa); Py_XDECREF((PyObject*)tempb); Py_DECREF((PyObject*)g); Py_DECREF((PyObject*)s); Py_DECREF((PyObject*)t); Py_DECREF(result); return NULL; } mpz_gcdext(g->z, s->z, t->z, tempa->z, tempb->z); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); } PyTuple_SET_ITEM(result, 0, (PyObject*)g); PyTuple_SET_ITEM(result, 1, (PyObject*)s); PyTuple_SET_ITEM(result, 2, (PyObject*)t); return result; } PyDoc_STRVAR(doc_divm, "divm(a, b, m) -> mpz\n\n" "Return x such that b*x == a mod m. Raises a ZeroDivisionError\n" "exception if no such value x exists."); static PyObject * Pygmpy_divm(PyObject *self, PyObject *args) { PympzObject *result, *num, *den, *mod; mpz_t numz, denz, modz, gcdz; int ok; if(PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; num = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); den = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); mod = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); if(!num || !den || !mod) { TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments"); Py_XDECREF((PyObject*)num); Py_XDECREF((PyObject*)den); Py_XDECREF((PyObject*)mod); Py_DECREF((PyObject*)result); return NULL; } /* Make copies so we don't destroy the input. */ mpz_inoc(numz); mpz_inoc(denz); mpz_inoc(modz); mpz_set(numz, num->z); mpz_set(denz, den->z); mpz_set(modz, mod->z); Py_DECREF((PyObject*)num); Py_DECREF((PyObject*)den); Py_DECREF((PyObject*)mod); if (mpz_invert(result->z, denz, modz)) { /* inverse exists */ ok = 1; } else { /* last-ditch attempt: do num, den AND mod have a gcd>1 ? */ mpz_inoc(gcdz); mpz_gcd(gcdz, numz, denz); mpz_gcd(gcdz, gcdz, modz); mpz_divexact(numz, numz, gcdz); mpz_divexact(denz, denz, gcdz); mpz_divexact(modz, modz, gcdz); mpz_cloc(gcdz); ok = mpz_invert(result->z, denz, modz); } if (ok) { mpz_mul(result->z, result->z, numz); mpz_mod(result->z, result->z, modz); mpz_cloc(numz); mpz_cloc(denz); mpz_cloc(modz); return (PyObject*)result; } else { ZERO_ERROR("not invertible"); mpz_cloc(numz); mpz_cloc(denz); mpz_cloc(modz); Py_DECREF((PyObject*)result); return NULL; } } PyDoc_STRVAR(doc_fac, "fac(n) -> mpz\n\n" "Return the exact factorial of n.\n\n" "See factorial(n) to get the floating-point approximation."); static PyObject * Pygmpy_fac(PyObject *self, PyObject *other) { PympzObject *result; mpir_si n; n = SI_From_Integer(other); if ((n == -1) && PyErr_Occurred()) { TYPE_ERROR("fac() requires 'int' argument"); return NULL; } else if (n < 0) { VALUE_ERROR("fac() of negative number"); return NULL; } else { if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_fac_ui(result->z, n); } return (PyObject*)result; } PyDoc_STRVAR(doc_fib, "fib(n) -> mpz\n\n" "Return the n-th Fibonacci number."); static PyObject * Pygmpy_fib(PyObject *self, PyObject *other) { PympzObject *result; mpir_si n; n = SI_From_Integer(other); if ((n == -1) && PyErr_Occurred()) { TYPE_ERROR("fib() requires 'int' argument"); return NULL; } else if (n < 0) { VALUE_ERROR("Fibonacci of negative number"); return NULL; } else { if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_fib_ui(Pympz_AS_MPZ(result), n); } return (PyObject*)result; } PyDoc_STRVAR(doc_fib2, "fib2(n) -> tuple\n\n" "Return a 2-tuple with the (n-1)-th and n-th Fibonacci numbers."); static PyObject * Pygmpy_fib2(PyObject *self, PyObject *other) { PyObject *result; PympzObject *fib1 = 0, *fib2 = 0; mpir_si n; n = SI_From_Integer(other); if ((n == -1) && PyErr_Occurred()) { TYPE_ERROR("fib2() requires 'int' argument"); return NULL; } else if (n < 0) { VALUE_ERROR("Fibonacci of negative number"); return NULL; } else { CREATE_TWO_MPZ_TUPLE(fib1, fib2, result); mpz_fib2_ui(fib1->z, fib2->z, n); } PyTuple_SET_ITEM(result, 0, (PyObject*)fib1); PyTuple_SET_ITEM(result, 1, (PyObject*)fib2); return result; } PyDoc_STRVAR(doc_lucas, "lucas(n) -> mpz\n\n" "Return the n-th Lucas number."); static PyObject * Pygmpy_lucas(PyObject *self, PyObject *other) { PympzObject *result; mpir_si n; n = SI_From_Integer(other); if ((n == -1) && PyErr_Occurred()) { TYPE_ERROR("luc() requires 'int' argument"); return NULL; } else if (n < 0) { VALUE_ERROR("Lucas of negative number"); return NULL; } else { if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_lucnum_ui(result->z, n); } return (PyObject*)result; } PyDoc_STRVAR(doc_lucas2, "lucas2(n) -> tuple\n\n" "Return a 2-tuple with the (n-1)-th and n-th Lucas numbers."); static PyObject * Pygmpy_lucas2(PyObject *self, PyObject *other) { PyObject *result; PympzObject *luc1, *luc2; mpir_si n; n = SI_From_Integer(other); if ((n == -1) && PyErr_Occurred()) { TYPE_ERROR("luc2() requires 'int' argument"); return NULL; } else if (n < 0) { VALUE_ERROR("Lucas of negative number"); return NULL; } else { CREATE_TWO_MPZ_TUPLE(luc1, luc2, result); mpz_lucnum2_ui(luc1->z, luc2->z, n); } PyTuple_SET_ITEM(result, 0, (PyObject*)luc1); PyTuple_SET_ITEM(result, 1, (PyObject*)luc2); return result; } PyDoc_STRVAR(doc_bincoefg, "bincoef(x, n) -> mpz\n\n" "Return the binomial coefficient ('x over n'). n >= 0."); PyDoc_STRVAR(doc_combg, "comb(x, n) -> mpz\n\n" "Return the number of combinations of 'x things, taking n at a\n" "time'. n >= 0."); static PyObject * Pympz_bincoef(PyObject *self, PyObject *args) { PympzObject *result; mpir_si k; PARSE_ONE_MPZ_REQ_SI(&k, "bincoef() requires 'mpz','int' arguments"); if (k < 0) { VALUE_ERROR("binomial coefficient with negative k"); Py_DECREF(self); return NULL; } if(!(result = (PympzObject*)Pympz_new())) { Py_DECREF(self); return NULL; } mpz_bin_ui(result->z, Pympz_AS_MPZ(self), k); Py_DECREF(self); return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_isqrt, "isqrt(x) -> mpz\n\n" "Return the integer square root of an integer x. x >= 0."); static PyObject * Pympz_isqrt(PyObject *self, PyObject *other) { PympzObject *result; if (self && (CHECK_MPZANY(self))) { if (mpz_sgn(Pympz_AS_MPZ(self)) < 0) { VALUE_ERROR("isqrt() of negative number"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_sqrt(result->z, Pympz_AS_MPZ(self)); } else if (CHECK_MPZANY(other)) { if (mpz_sgn(Pympz_AS_MPZ(other)) < 0) { VALUE_ERROR("isqrt() of negative number"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; mpz_sqrt(result->z, Pympz_AS_MPZ(other)); } else { if (!(result = Pympz_From_Integer(other))) { TYPE_ERROR("isqrt() requires 'mpz' argument"); return NULL; } if (mpz_sgn(result->z) < 0) { VALUE_ERROR("isqrt() of negative number"); Py_DECREF((PyObject*)result); return NULL; } mpz_sqrt(result->z, result->z); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_isqrt_rem, "isqrt_rem(x) -> tuple\n\n" "Return a 2-element tuple (s,t) such that s=isqrt(x) and t=x-s*s.\n" "x >=0."); static PyObject * Pympz_isqrt_rem(PyObject *self, PyObject *args) { PympzObject *root = 0, *rem = 0; PyObject *result = 0; PARSE_ONE_MPZ("isqrt_rem() requires 'mpz' argument"); if (mpz_sgn(Pympz_AS_MPZ(self)) < 0) { VALUE_ERROR("isqrt_rem() of negative number"); Py_DECREF(self); return NULL; } root = (PympzObject*)Pympz_new(); rem = (PympzObject*)Pympz_new(); result = PyTuple_New(2); if (!root || !rem || !result) { Py_DECREF(self); Py_XDECREF(result); Py_XDECREF((PyObject*)root); Py_XDECREF((PyObject*)rem); return NULL; } mpz_sqrtrem(root->z, rem->z, Pympz_AS_MPZ(self)); Py_DECREF(self); PyTuple_SET_ITEM(result, 0, (PyObject*)root); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } PyDoc_STRVAR(doc_removeg, "remove(x, f) -> tuple\n\n" "Return a 2-element tuple (y,m) such that x=y*(f**m) and f does\n" "not divide y. Remove the factor f from x as many times as\n" "possible. m is the multiplicity f in x. f > 1."); static PyObject * Pympz_remove(PyObject *self, PyObject *args) { PympzObject *result; PyObject *factor; size_t multiplicity; PARSE_TWO_MPZ(factor, "remove() requires 'mpz','mpz' arguments"); if (mpz_cmp_si(Pympz_AS_MPZ(factor), 2) < 0) { VALUE_ERROR("factor must be > 1"); Py_DECREF(self); Py_DECREF(factor); return NULL; } if (!(result = (PympzObject*)Pympz_new())) { Py_DECREF(self); Py_DECREF(factor); return NULL; } multiplicity = mpz_remove(result->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(factor)); Py_DECREF(self); Py_DECREF(factor); return Py_BuildValue("(Nk)", result, multiplicity); } PyDoc_STRVAR(doc_invertg, "invert(x, m) -> mpz\n\n" "Return y such that x*y == 1 (mod m). Raises ZeroDivisionError if no\n" "inverse exists."); static PyObject * Pygmpy_invert(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *result, *tempx, *tempy; int success; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("invert() requires 'mpz','mpz' arguments"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("invert() division by 0"); Py_DECREF((PyObject*)result); return NULL; } success = mpz_invert(result->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); if (!success) { ZERO_ERROR("invert() no inverse exists"); Py_DECREF((PyObject*)result); return NULL; } } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("invert() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } if (mpz_sgn(tempy->z) == 0) { ZERO_ERROR("invert() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF(result); return NULL; } success = mpz_invert(result->z, tempx->z, tempy->z); if (!success) { ZERO_ERROR("invert() no inverse exists"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)result; } PyDoc_STRVAR(doc_hamdistg, "hamdist(x, y) -> int\n\n" "Return the Hamming distance (number of bit-positions where the\n" "bits differ) between integers x and y."); static PyObject * Pympz_hamdist(PyObject *self, PyObject *args) { PyObject *result, *other; PARSE_TWO_MPZ(other, "hamdist() requires 'mpz','mpz' arguments"); result = PyIntOrLong_FromSize_t( mpz_hamdist(Pympz_AS_MPZ(self),Pympz_AS_MPZ(other))); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } PyDoc_STRVAR(doc_divexactg, "divexact(x, y) -> mpz\n\n" "Return the quotient of x divided by y. Faster than standard\n" "division but requires the remainder is zero!"); static PyObject * Pygmpy_divexact(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *result, *tempx, *tempy; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("divexact() requires 'mpz','mpz' arguments"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("divexact() division by 0"); Py_DECREF((PyObject*)result); return NULL; } mpz_divexact(result->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("divexact() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("divexact() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpz_divexact(result->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)result; } PyDoc_STRVAR(doc_is_squareg, "is_square(x) -> bool\n\n" "Returns True if x is a perfect square, else return False."); static PyObject * Pympz_is_square(PyObject *self, PyObject *other) { int res; PympzObject *tempx; if (CHECK_MPZANY(other)) { res = mpz_perfect_square_p(Pympz_AS_MPZ(other)); } else { if (!(tempx = Pympz_From_Integer(other))) { TYPE_ERROR("is_square() requires 'mpz' argument"); return NULL; } else { res = mpz_perfect_square_p(tempx->z); Py_DECREF((PyObject*)tempx); } } if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_is_powerg, "is_power(x) -> bool\n\n" "Return True if x is a perfect power (there exists a y and an\n" "n > 1, such that x=y**n), else return False."); static PyObject * Pympz_is_power(PyObject *self, PyObject *other) { int res; PympzObject* tempx; if (CHECK_MPZANY(other)) { res = mpz_perfect_power_p(Pympz_AS_MPZ(other)); } else { if (!(tempx = Pympz_From_Integer(other))) { TYPE_ERROR("is_power() requires 'mpz' argument"); return NULL; } else { res = mpz_perfect_power_p(tempx->z); Py_DECREF((PyObject*)tempx); } } if(res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_is_primeg, "is_prime(x[, n=25]) -> bool\n\n" "Return True if x is _probably_ prime, else False if x is\n" "definately composite. x is checked for small divisors and up\n" "to n Miller-Rabin tests are performed."); static PyObject * Pympz_is_prime(PyObject *self, PyObject *args) { int i, reps = 25; PARSE_ONE_MPZ_OPT_CLONG(&reps, "is_prime() requires 'mpz'[,'int'] arguments"); if (reps <= 0) { VALUE_ERROR("repetition count for is_prime() must be positive"); Py_DECREF(self); return NULL; } i = mpz_probab_prime_p(Pympz_AS_MPZ(self), reps); Py_DECREF(self); if (i) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_next_primeg, "next_prime(x) -> mpz\n\n" "Return the next _probable_ prime number > x."); static PyObject * Pympz_next_prime(PyObject *self, PyObject *other) { PympzObject *result; if(CHECK_MPZANY(other)) { if(!(result = (PympzObject*)Pympz_new())) return NULL; mpz_nextprime(result->z, Pympz_AS_MPZ(other)); } else { if (!(result = Pympz_From_Integer(other))) { TYPE_ERROR("next_prime() requires 'mpz' argument"); return NULL; } else { mpz_nextprime(result->z, result->z); } } return (PyObject*)result; } PyDoc_STRVAR(doc_jacobig, "jacobi(x, y) -> mpz\n\n" "Return the Jacobi symbol (x|y). y must be odd and >0."); static PyObject * Pympz_jacobi(PyObject *self, PyObject *args) { PyObject *other; long i; PARSE_TWO_MPZ(other, "jacobi() requires 'mpz','mpz' arguments"); if (mpz_sgn(Pympz_AS_MPZ(other)) <= 0 || mpz_even_p(Pympz_AS_MPZ(other))) { VALUE_ERROR("y must be odd and >0"); Py_DECREF(self); Py_DECREF(other); return NULL; } i = (long)(mpz_jacobi(Pympz_AS_MPZ(self), Pympz_AS_MPZ(other))); Py_DECREF(self); Py_DECREF(other); return PyIntOrLong_FromLong(i); } PyDoc_STRVAR(doc_legendreg, "legendre(x, y) -> mpz\n\n" "Return the Legendre symbol (x|y). y is assumed to be an odd prime."); static PyObject * Pympz_legendre(PyObject *self, PyObject *args) { PyObject *other; long i; PARSE_TWO_MPZ(other, "legendre() requires 'mpz','mpz' arguments"); if (mpz_sgn(Pympz_AS_MPZ(other)) <= 0 || mpz_even_p(Pympz_AS_MPZ(other))) { VALUE_ERROR("y must be odd and >0"); Py_DECREF(self); Py_DECREF(other); return NULL; } i = (long) mpz_legendre(Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); Py_DECREF(self); Py_DECREF(other); return PyIntOrLong_FromLong(i); } PyDoc_STRVAR(doc_kroneckerg, "kronecker(x, y) -> mpz\n\n" "Return the Kronecker-Jacobi symbol (x|y)."); static PyObject * Pympz_kronecker(PyObject *self, PyObject *args) { PyObject *other; long ires; PARSE_TWO_MPZ(other, "kronecker() requires 'mpz','mpz' arguments"); ires = (long) mpz_kronecker(Pympz_AS_MPZ(self), (Pympz_AS_MPZ(other))); Py_DECREF(self); Py_DECREF(other); return PyIntOrLong_FromLong(ires); } PyDoc_STRVAR(doc_is_eveng, "is_even(x) -> bool\n\n" "Return True if x is even, False otherwise."); static PyObject * Pympz_is_even(PyObject *self, PyObject *other) { int res; PympzObject *tempx; if (CHECK_MPZANY(other)) { res = mpz_even_p(Pympz_AS_MPZ(other)); } else { if (!(tempx = Pympz_From_Integer(other))) { TYPE_ERROR("is_even() requires 'mpz' argument"); return NULL; } else { res = mpz_even_p(tempx->z); Py_DECREF((PyObject*)tempx); } } if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_is_oddg, "is_odd(x) -> bool\n\n" "Return True if x is odd, False otherwise."); static PyObject * Pympz_is_odd(PyObject *self, PyObject *other) { int res; PympzObject *tempx; if (CHECK_MPZANY(other)) { res = mpz_odd_p(Pympz_AS_MPZ(other)); } else { if (!(tempx = Pympz_From_Integer(other))) { TYPE_ERROR("is_odd() requires 'mpz' argument"); return NULL; } else { res = mpz_odd_p(tempx->z); Py_DECREF((PyObject*)tempx); } } if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } /* * Add mapping support to mpz objects. */ static Py_ssize_t Pympz_nbits(PympzObject *self) { return mpz_sizeinbase(self->z, 2); } static PyObject * Pympz_subscript(PympzObject *self, PyObject *item) { if (PyIndex_Check(item)) { Py_ssize_t i; i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; if (i < 0) i += mpz_sizeinbase(self->z, 2); return PyIntOrLong_FromLong(mpz_tstbit(self->z, i)); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, cur, i; PyObject* result; #if PY_VERSION_HEX > 0x030200A4 if (PySlice_GetIndicesEx(item, #else if (PySlice_GetIndicesEx((PySliceObject*)item, #endif mpz_sizeinbase(self->z, 2), &start, &stop, &step, &slicelength) < 0) { return NULL; } if ((step < 0 && start < stop) || (step > 0 && start > stop)) stop = start; if (!(result = (PyObject*)Pympz_new())) return NULL; mpz_set_ui(Pympz_AS_MPZ(result), 0); if (slicelength > 0) { for (cur = start, i = 0; i < slicelength; cur += step, i++) { if(mpz_tstbit(self->z, cur)) { mpz_setbit(Pympz_AS_MPZ(result), i); } } } return result; } else { TYPE_ERROR("bit positions must be integers"); return NULL; } } PyDoc_STRVAR(doc_mpz_format, "x.__format__(fmt) -> string\n\n" "Return a Python string by formatting mpz 'x' using the format string\n" "'fmt'. A valid format string consists of:\n" " optional alignment code:\n" " '<' -> left shifted in field\n" " '>' -> right shifted in field\n" " '^' -> centered in field\n" " optional leading sign code:\n" " '+' -> always display leading sign\n" " '-' -> only display minus sign\n" " ' ' -> minus for negative values, space for positive values\n" " optional base indicator\n" " '#' -> precede binary, octal, or hex with 0b, 0o or 0x\n" " optional width\n" " optional conversion code:\n" " 'd' -> decimal format\n" " 'b' -> binary format\n" " 'o' -> octal format\n" " 'x' -> hex format\n" "The default format is 'd'."); /* Formatting occurs in two phases. Pympz_ascii() is used to create a string * with the appropriate binary/octal/decimal/hex formatting, including the * leading sign character (+ , -, or space) and base encoding (0b, 0o, or 0x). * Left/right/centering using the specified width is done by creating a * format string and calling the __format__() method of the string object * returned by Pympz_ascii(). */ static PyObject * Pympz_format(PyObject *self, PyObject *args) { PyObject *result = 0, *mpzstr = 0; char *fmtcode = 0, *p1, *p2; char fmt[30]; int base = 10, option = 16; int seensign = 0, seenindicator = 0, seenalign = 0, seendigits = 0; if (!CHECK_MPZANY(self)) { TYPE_ERROR("requires mpz type"); return NULL; } if (!PyArg_ParseTuple(args, "s", &fmtcode)) return NULL; p2 = fmt; for (p1 = fmtcode; *p1 != '\00'; p1++) { if (*p1 == '<' || *p1 == '>' || *p1 == '^') { if (seenalign || seensign || seenindicator || seendigits) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(p2++) = *p1; seenalign = 1; continue; } } if (*p1 == '+') { if (seensign || seenindicator || seendigits) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { option |= 2; seensign = 1; continue; } } if (*p1 == '-') { if (seensign || seenindicator || seendigits) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { seensign = 1; continue; } } if (*p1 == ' ') { if (seensign || seenindicator || seendigits) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { option |= 4; seensign = 1; continue; } } if (*p1 == '#') { if (seenindicator || seendigits) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { option |= 8; seenindicator = 1; continue; } } if (isdigit(*p1)) { if (!seenalign) { *(p2++) = '>'; seenalign = 1; } *(p2++) = *p1; seendigits = 1; continue; } if (*p1 == 'b') { base = 2; break; } if (*p1 == 'o') { base = 8; break; } if (*p1 == 'x') { base = 16; break; } if (*p1 == 'd') { base = 10; break; } if (*p1 == 'X') { base = -16; break; } VALUE_ERROR("Invalid conversion specification"); return NULL; } *(p2++) = '\00'; if (!(mpzstr = mpz_ascii(Pympz_AS_MPZ(self), base, option))) return NULL; result = PyObject_CallMethod(mpzstr, "__format__", "(s)", fmt); Py_DECREF(mpzstr); return result; } static PyObject * Pympz_add(PyObject *self, PyObject *args) { PympzObject *result; PyObject *other; PARSE_TWO_MPZ(other, "add() requires 'mpz','mpz' arguments"); if ((result = (PympzObject*)Pympz_new())) mpz_add(result->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympz_sub(PyObject *self, PyObject *args) { PympzObject *result; PyObject *other; PARSE_TWO_MPZ(other, "sub() requires 'mpz','mpz' arguments"); if ((result = (PympzObject*)Pympz_new())) mpz_sub(result->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympz_mul(PyObject *self, PyObject *args) { PympzObject *result; PyObject *other; PARSE_TWO_MPZ(other, "mul() requires 'mpz','mpz' arguments"); if ((result = (PympzObject*)Pympz_new())) mpz_mul(result->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympz_div(PyObject *self, PyObject *args) { PympzObject *result; PyObject *other; PARSE_TWO_MPZ(other, "div() requires 'mpz','mpz' arguments"); if ((result = (PympzObject*)Pympz_new())) { if (mpz_sgn(Pympz_AS_MPZ(other)) == 0) { ZERO_ERROR("mpz division by zero"); Py_DECREF((PyObject*)result); result = 0; } else { mpz_div(result->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other)); } } Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympz_getnumer(PympzObject *self, void *closure) { Py_INCREF((PyObject*)self); return (PyObject*)self; } static PyObject * Pympz_getdenom(PympqObject *self, void *closure) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) mpz_set_ui(result->z, 1); return (PyObject*)result; } PyDoc_STRVAR(doc_mpz_sizeof, "x.__sizeof__()\n\n" "Returns the amount of memory consumed by x. Note: deleted mpz objects\n" "are reused and may or may not be resized when a new value is assigned."); static PyObject * Pympz_sizeof(PyObject *self, PyObject *other) { return PyIntOrLong_FromSize_t(sizeof(PympzObject) + \ (Pympz_AS_MPZ(self)->_mp_alloc * sizeof(mp_limb_t))); } #ifdef PY3 static PyNumberMethods mpz_number_methods = { (binaryfunc) Pybasic_add, /* nb_add */ (binaryfunc) Pybasic_sub, /* nb_subtract */ (binaryfunc) Pybasic_mul, /* nb_multiply */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympz_neg, /* nb_negative */ (unaryfunc) Pympz_pos, /* nb_positive */ (unaryfunc) Pympz_abs, /* nb_absolute */ (inquiry) Pympz_nonzero, /* nb_bool */ (unaryfunc) Pympz_com, /* nb_invert */ (binaryfunc) Pympz_lshift, /* nb_lshift */ (binaryfunc) Pympz_rshift, /* nb_rshift */ (binaryfunc) Pympz_and, /* nb_and */ (binaryfunc) Pympz_xor, /* nb_xor */ (binaryfunc) Pympz_ior, /* nb_or */ (unaryfunc) Pympz_To_PyLong, /* nb_int */ 0, /* nb_reserved */ (unaryfunc) Pympz_To_PyFloat, /* nb_float */ (binaryfunc) Pympz_inplace_add, /* nb_inplace_add */ (binaryfunc) Pympz_inplace_sub, /* nb_inplace_subtract */ (binaryfunc) Pympz_inplace_mul, /* nb_inplace_multiply */ (binaryfunc) Pympz_inplace_rem, /* nb_inplace_remainder */ (ternaryfunc) Pympz_inplace_pow, /* nb_inplace_power */ (binaryfunc) Pympz_inplace_lshift, /* nb_inplace_lshift */ (binaryfunc) Pympz_inplace_rshift, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pybasic_truediv, /* nb_true_divide */ (binaryfunc) Pympz_inplace_floordiv, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ (unaryfunc) Pympz_To_PyIntOrLong, /* nb_index */ }; #else static PyNumberMethods mpz_number_methods = { (binaryfunc) Pybasic_add, /* nb_add */ (binaryfunc) Pybasic_sub, /* nb_subtract */ (binaryfunc) Pybasic_mul, /* nb_multiply */ (binaryfunc) Pybasic_div2, /* nb_divide */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympz_neg, /* nb_negative */ (unaryfunc) Pympz_pos, /* nb_positive */ (unaryfunc) Pympz_abs, /* nb_absolute */ (inquiry) Pympz_nonzero, /* nb_bool */ (unaryfunc) Pympz_com, /* nb_invert */ (binaryfunc) Pympz_lshift, /* nb_lshift */ (binaryfunc) Pympz_rshift, /* nb_rshift */ (binaryfunc) Pympz_and, /* nb_and */ (binaryfunc) Pympz_xor, /* nb_xor */ (binaryfunc) Pympz_ior, /* nb_or */ 0, /* nb_coerce */ (unaryfunc) Pympz_To_PyIntOrLong, /* nb_int */ (unaryfunc) Pympz_To_PyLong, /* nb_long */ (unaryfunc) Pympz_To_PyFloat, /* nb_float */ (unaryfunc) Pympz_oct, /* nb_oct */ (unaryfunc) Pympz_hex, /* nb_hex */ (binaryfunc) Pympz_inplace_add, /* nb_inplace_add */ (binaryfunc) Pympz_inplace_sub, /* nb_inplace_subtract */ (binaryfunc) Pympz_inplace_mul, /* nb_inplace_multiply */ 0, /* nb_inplace_divide */ (binaryfunc) Pympz_inplace_rem, /* nb_inplace_remainder */ (ternaryfunc) Pympz_inplace_pow, /* nb_inplace_power */ (binaryfunc) Pympz_inplace_lshift, /* nb_inplace_lshift */ (binaryfunc) Pympz_inplace_rshift, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pybasic_truediv, /* nb_true_divide */ (binaryfunc) Pympz_inplace_floordiv, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ (unaryfunc) Pympz_To_PyIntOrLong, /* nb_index */ }; #endif static PyMappingMethods mpz_mapping_methods = { (lenfunc)Pympz_nbits, (binaryfunc)Pympz_subscript, NULL }; static PyGetSetDef Pympz_getseters[] = { { "numerator", (getter)Pympz_getnumer, NULL, "numerator", NULL }, { "denominator", (getter)Pympz_getdenom, NULL, "denominator", NULL }, {NULL} }; static PyMethodDef Pympz_methods [] = { { "__format__", Pympz_format, METH_VARARGS, doc_mpz_format }, { "__ceil__", Pympz_ceil, METH_NOARGS, doc_mpz_ceil }, { "__floor__", Pympz_floor, METH_NOARGS, doc_mpz_floor }, { "__round__", Pympz_round, METH_VARARGS, doc_mpz_round }, { "__sizeof__", Pympz_sizeof, METH_NOARGS, doc_mpz_sizeof }, { "__trunc__", Pympz_trunc, METH_NOARGS, doc_mpz_trunc }, { "bit_clear", Pympz_bit_clear, METH_O, doc_bit_clearm }, { "bit_flip", Pympz_bit_flip, METH_O, doc_bit_flipm }, { "bit_length", Pympz_bit_length, METH_NOARGS, doc_bit_lengthm }, { "bit_scan0", Pympz_bit_scan0, METH_VARARGS, doc_bit_scan0m }, { "bit_scan1", Pympz_bit_scan1, METH_VARARGS, doc_bit_scan1m }, { "bit_set", Pympz_bit_set, METH_O, doc_bit_setm }, { "bit_test", Pympz_bit_test, METH_O, doc_bit_testm }, { "digits", Pympz_digits, METH_VARARGS, doc_mpz_digits }, { "num_digits", Pympz_num_digits, METH_VARARGS, doc_num_digitsm }, { NULL, NULL, 1 } }; static PyTypeObject Pympz_Type = { /* PyObject_HEAD_INIT(&PyType_Type) */ #ifdef PY3 PyVarObject_HEAD_INIT(0, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "mpz", /* tp_name */ sizeof(PympzObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor) Pympz_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) Pympz_To_Repr, /* tp_repr */ &mpz_number_methods, /* tp_as_number */ 0, /* tp_as_sequence */ &mpz_mapping_methods, /* tp_as_mapping */ (hashfunc) Pympz_hash, /* tp_hash */ 0, /* tp_call */ (reprfunc) Pympz_To_Str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ #ifdef PY3 Py_TPFLAGS_DEFAULT, /* tp_flags */ #else Py_TPFLAGS_HAVE_INDEX|Py_TPFLAGS_HAVE_RICHCOMPARE| \ Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_CLASS| \ Py_TPFLAGS_HAVE_INPLACEOPS, #endif "Multiple precision integer", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)&mpany_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ Pympz_methods, /* tp_methods */ 0, /* tp_members */ Pympz_getseters, /* tp_getset */ }; gmpy2-2.0.7/src/gmpy_mpq.h0000666000000000000000000000730112542614506014057 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpq.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MPQ_H #define GMPY_MPQ_H #ifdef __cplusplus extern "C" { #endif typedef struct { PyObject_HEAD mpq_t q; Py_hash_t hash_cache; } PympqObject; #define Pympq_AS_MPQ(obj) (((PympqObject *)(obj))->q) static PyTypeObject Pympq_Type; #define Pympq_Check(v) (((PyObject*)v)->ob_type == &Pympq_Type) static PyObject * Pygmpy_mpq(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pympq_digits(PyObject *self, PyObject *args); static PyObject * Pympq_sign(PyObject *self, PyObject *other); static PyObject * Pympq_numer(PyObject *self, PyObject *args); static PyObject * Pympq_getnumer(PympqObject *self, void *closure); static PyObject * Pympq_denom(PyObject *self, PyObject *args); static PyObject * Pympq_getdenom(PympqObject *self, void *closure); static PyObject * Pympq_qdiv(PyObject *self, PyObject *args); static PyObject * Pympq_neg(PympqObject *self); static PyObject * Pympq_abs(PympqObject *self); static PyObject * Pympq_pos(PympqObject *self); static PyObject * Pympq_ceil(PyObject *self, PyObject *other); static PyObject * Pympq_floor(PyObject *self, PyObject *other); static PyObject * Pympq_trunc(PyObject *self, PyObject *other); static PyObject * Pympq_square(PyObject *self, PyObject *other); static PyObject * Pympq_pow(PyObject *base, PyObject *exp, PyObject *m); static int Pympq_nonzero(PympqObject *x); static Py_hash_t Pympq_hash(PympqObject *self); static PyObject * Pympq_add(PyObject *self, PyObject *args); static PyObject * Pympq_sub(PyObject *self, PyObject *args); static PyObject * Pympq_mul(PyObject *self, PyObject *args); static PyObject * Pympq_div(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpq.c0000666000000000000000000007434312542614506014064 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpq.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ PyDoc_STRVAR(doc_mpq, "mpq() -> mpq(0,1)\n\n" " If no argument is given, return mpq(0,1).\n\n" "mpq(n) -> mpq\n\n" " Return an 'mpq' object with a numeric value n. Decimal and\n" " Fraction values are converted exactly.\n\n" "mpq(n,m) -> mpq\n\n" " Return an 'mpq' object with a numeric value n/m.\n\n" "mpq(s[, base=10]) -> mpq\n\n" " Return an 'mpq' object from a string s made up of digits in\n" " the given base. s may be made up of two numbers in the same\n" " base separated by a '/' character.\n"); static PyObject * Pygmpy_mpq(PyObject *self, PyObject *args, PyObject *keywds) { PympqObject *result = 0, *temp; PyObject *n = 0, *m = 0; int base = 10; Py_ssize_t argc; static char *kwlist[] = {"s", "base", NULL }; argc = PyTuple_Size(args); if (argc > 2) { TYPE_ERROR("mpq() requires 0, 1 or 2 arguments"); return NULL; } if (argc == 0) { if ((result = (PympqObject*)Pympq_new())) { mpq_set_ui(result->q, 0, 0); } return (PyObject*)result; } n = PyTuple_GetItem(args, 0); if (PyStrOrUnicode_Check(n)) { /* keyword base is legal */ if (PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) { if ((base!=0) && ((base<2)||(base>62))) { VALUE_ERROR("base for mpq() must be 0 or in the " "interval 2 ... 62"); } else { result = Pympq_From_PyStr(n, base); } } return (PyObject*)result; } if (isDecimal(n)) { return (PyObject*)Pympq_From_Decimal(n); } if (argc == 2) m = PyTuple_GetItem(args, 1); #ifdef WITHMPFR if (!isReal(n) || (m && !isReal(m))) { #else if (!(isRational(n) || PyFloat_Check(n)) || (m && !(isRational(m) || PyFloat_Check(m)))) { #endif TYPE_ERROR("mpq() requires numeric or string argument"); return NULL; } /* should now have one or two numeric values */ result = Pympq_From_Number(n); if (!result && !PyErr_Occurred()) { TYPE_ERROR("mpq() requires numeric or string argument"); return NULL; } if (m) { temp = Pympq_From_Number(m); if (!temp && !PyErr_Occurred()) { TYPE_ERROR("mpq() requires numeric or string argument"); Py_DECREF((PyObject*)result); return NULL; } if (mpq_sgn(temp->q) == 0) { ZERO_ERROR("zero denominator in 'mpq'"); Py_DECREF((PyObject*)result); Py_DECREF((PyObject*)temp); return NULL; } mpq_div(result->q, result->q, temp->q); Py_DECREF((PyObject*)temp); } return (PyObject*)result; } /* Functions that operate strictly on mpq. */ /* produce digits for an mpq in requested base, default 10 */ PyDoc_STRVAR(doc_qdigitsm, "x.digits([base=10]) -> string\n\n" "Return a Python string representing x in the given base (2 to 62,\n" "default is 10). A leading '-' is present if x<0, but no leading '+'\n" "is present if x>=0.\n"); static PyObject * Pympq_digits(PyObject *self, PyObject *args) { int base = 10; PyObject *result; SELF_MPQ_ONE_ARG("|i", &base); result = Pympq_To_PyStr((PympqObject*)self, base, 0); Py_DECREF(self); return result; } /* Since Pympq_sign() is called by Pympany_sign(), we know that 'other' is * a Rational type. */ static PyObject * Pympq_sign(PyObject *self, PyObject *other) { long res; PympqObject* tempx; if (Pympq_Check(other)) { res = mpq_sgn(Pympq_AS_MPQ(other)); } else { if (!(tempx = Pympq_From_Number(other))) { TYPE_ERROR("sign() requires 'mpq' argument"); return NULL; } else { res = mpq_sgn(tempx->q); Py_DECREF((PyObject*)tempx); } } return PyIntOrLong_FromLong(res); } PyDoc_STRVAR(doc_numerg, "numer(x) -> mpz\n\n" "Return the numerator of x."); static PyObject * Pympq_numer(PyObject *self, PyObject *args) { PympzObject *result; if (!(result = (PympzObject*)Pympz_new())) return NULL; SELF_MPQ_NO_ARG; assert(Pympq_Check(self)); mpz_set(result->z, mpq_numref(Pympq_AS_MPQ(self))); Py_DECREF(self); return (PyObject*)result; } static PyObject * Pympq_getnumer(PympqObject *self, void *closure) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) mpz_set(result->z, mpq_numref(Pympq_AS_MPQ(self))); return (PyObject*)result; } PyDoc_STRVAR(doc_denomg, "denom(x) -> mpz\n\n" "Return the denominator of x."); static PyObject * Pympq_denom(PyObject *self, PyObject *args) { PympzObject *result; if (!(result = (PympzObject*)Pympz_new())) return NULL; SELF_MPQ_NO_ARG; assert(Pympq_Check(self)); mpz_set(result->z, mpq_denref(Pympq_AS_MPQ(self))); Py_DECREF(self); return (PyObject*)result; } static PyObject * Pympq_getdenom(PympqObject *self, void *closure) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) mpz_set(result->z, mpq_denref(Pympq_AS_MPQ(self))); return (PyObject*)result; } PyDoc_STRVAR(doc_qdivg, "qdiv(x[, y=1]) -> number\n\n" "Return x/y as 'mpz' if possible, or as 'mpq' if x is not exactly\n" "divisible by y."); static int isOne(PyObject* obj) { int overflow = 0; long temp; if (!obj) return 1; if (Pympq_Check(obj)) { return (0==mpz_cmp_ui(mpq_denref(Pympq_AS_MPQ(obj)),1)) && (0==mpz_cmp_ui(mpq_numref(Pympq_AS_MPQ(obj)),1)); } else if (Pympz_Check(obj)) { return 0==mpz_cmp_ui(Pympz_AS_MPZ(obj),1); } else if (Pyxmpz_Check(obj)) { return 0==mpz_cmp_ui(Pyxmpz_AS_MPZ(obj),1); #ifdef PY2 } else if (PyInt_Check(obj)) { return PyInt_AS_LONG(obj)==1; #endif } #ifdef WITHMPFR else if (Pympfr_Check(obj)) { return mpfr_get_d(Pympfr_AS_MPFR(obj), context->ctx.mpfr_round)==1.0; } #endif else if (PyFloat_Check(obj)) { return PyFloat_AS_DOUBLE(obj)==1.0; } else if (PyLong_Check(obj)) { temp = PyLong_AsLongAndOverflow(obj, &overflow); if (!overflow && temp == 1) return 1; else return 0; } return 0; } static PyObject * Pympq_qdiv(PyObject *self, PyObject *args) { PyObject *other = 0; PyObject *s = 0; int wasone; if ( self && Pympq_Check(self)) { if (!PyArg_ParseTuple(args, "|O", &other)) return NULL; } else { if (!PyArg_ParseTuple(args, "O|O", &self, &other)) return NULL; } wasone = isOne(other); /* optimize if self must be returned unchanged */ if (Pympq_Check(self) && wasone) { /* optimize if self is mpq and result must==self */ if (mpz_cmp_ui(mpq_denref(Pympq_AS_MPQ(self)), 1) != 0) { Py_INCREF(self); return self; } else { /* denominator is 1, optimize returning an mpz */ s = Pympz_new(); mpz_set(Pympz_AS_MPZ(s), mpq_numref(Pympq_AS_MPQ(self))); return s; } } else if (Pympz_Check(self) && wasone) { /* optimize if self is mpz and result must==self */ Py_INCREF(self); return self; } /* normal, non-optimized case: must make new object as result */ self = (PyObject*)Pympq_From_Rational(self); if (!self) { if (!PyErr_Occurred()) TYPE_ERROR("first argument cannot be converted to 'mpq'"); return NULL; } if (wasone) { /* self was mpf, float, int, long... */ s = self; } else { /* other explicitly present and !=1... must compute */ other = (PyObject*)Pympq_From_Rational(other); if (!other) { Py_DECREF(self); if (!PyErr_Occurred()) TYPE_ERROR("second argument cannot be converted to 'mpq'"); return NULL; } if (mpq_sgn(Pympq_AS_MPQ(other))==0) { PyObject* result = 0; ZERO_ERROR("division or modulo by zero in qdiv"); Py_DECREF(self); Py_DECREF(other); return result; } s = Pympq_new(); mpq_div(Pympq_AS_MPQ(s), Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); Py_DECREF(self); Py_DECREF(other); } if (mpz_cmp_ui(mpq_denref(Pympq_AS_MPQ(s)), 1) != 0) { return s; } else { /* denominator is 1, return an mpz */ PyObject* ss = Pympz_new(); if (ss) mpz_set(Pympz_AS_MPZ(ss), mpq_numref(Pympq_AS_MPQ(s))); Py_DECREF(s); return ss; } } static PyObject * Pympq_neg(PympqObject *self) { PympqObject *result; if ((result = (PympqObject*)Pympq_new())) { mpq_neg(result->q, self->q); } return (PyObject*)result; } static PyObject * Pympq_abs(PympqObject *self) { PympqObject *result; if ((result = (PympqObject*)Pympq_new())) { mpq_set(result->q, self->q); mpz_abs(mpq_numref(result->q), mpq_numref(result->q)); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpq_floor, "Return greatest integer less than or equal to an mpq."); static PyObject * Pympq_floor(PyObject *self, PyObject *other) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) { mpz_fdiv_q(result->z, mpq_numref(Pympq_AS_MPQ(self)), mpq_denref(Pympq_AS_MPQ(self))); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpq_ceil, "Return least integer greater than or equal to an mpq."); static PyObject * Pympq_ceil(PyObject *self, PyObject *other) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) { mpz_cdiv_q(result->z, mpq_numref(Pympq_AS_MPQ(self)), mpq_denref(Pympq_AS_MPQ(self))); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpq_trunc, "Return integer portion of an mpq."); static PyObject * Pympq_trunc(PyObject *self, PyObject *other) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) { mpz_tdiv_q(result->z, mpq_numref(Pympq_AS_MPQ(self)), mpq_denref(Pympq_AS_MPQ(self))); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpq_round, "Round an mpq to power of 10."); static PyObject * Pympq_round(PyObject *self, PyObject *args) { Py_ssize_t round_digits = 0; PympqObject *resultq; PympzObject *resultz; mpz_t temp, rem; /* If args is NULL or the size of args is 0, we just return an mpz. */ if (!args || PyTuple_GET_SIZE(args) == 0) { if (!(resultz = (PympzObject*)Pympz_new())) return NULL; mpz_inoc(rem); mpz_fdiv_qr(resultz->z, rem, mpq_numref(Pympq_AS_MPQ(self)), mpq_denref(Pympq_AS_MPQ(self))); mpz_mul_2exp(rem, rem, 1); if (mpz_cmp(rem, mpq_denref(Pympq_AS_MPQ(self))) > 0) { mpz_add_ui(resultz->z, resultz->z, 1); } else if (mpz_cmp(rem, mpq_denref(Pympq_AS_MPQ(self))) == 0) { if (mpz_odd_p(resultz->z)) { mpz_add_ui(resultz->z, resultz->z, 1); } } mpz_cloc(rem); return (PyObject*)resultz; } if (PyTuple_GET_SIZE(args) > 1) { TYPE_ERROR("Too many arguments for __round__()."); return NULL; } if (PyTuple_GET_SIZE(args) == 1) { round_digits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0)); if (round_digits == -1 && PyErr_Occurred()) { TYPE_ERROR("__round__() requires 'int' argument"); return NULL; } } if (!(resultq = (PympqObject*)Pympq_new())) return NULL; mpz_inoc(temp); mpz_ui_pow_ui(temp, 10, round_digits > 0 ? round_digits : -round_digits); mpq_set(resultq->q, Pympq_AS_MPQ(self)); if (round_digits > 0) { mpz_mul(mpq_numref(resultq->q), mpq_numref(resultq->q), temp); mpq_canonicalize(resultq->q); if (!(resultz = (PympzObject*)Pympq_round((PyObject*)resultq, NULL))) { mpz_cloc(temp); return NULL; } mpz_set(mpq_numref(resultq->q), resultz->z); Py_DECREF((PyObject*)resultz); mpz_set(mpq_denref(resultq->q), temp); mpz_cloc(temp); mpq_canonicalize(resultq->q); } else { mpz_mul(mpq_denref(resultq->q), mpq_denref(resultq->q), temp); mpq_canonicalize(resultq->q); if (!(resultz = (PympzObject*)Pympq_round((PyObject*)resultq, NULL))) { mpz_cloc(temp); return NULL; } mpq_set_ui(resultq->q, 0, 1); mpz_mul(mpq_numref(resultq->q), resultz->z, temp); Py_DECREF((PyObject*)resultz); mpz_cloc(temp); mpq_canonicalize(resultq->q); } return (PyObject*)resultq; } static PyObject * Pympq_pos(PympqObject *self) { Py_INCREF((PyObject*)self); return (PyObject*)self; } static PyObject * Pympq_square(PyObject *self, PyObject *other) { PympqObject *tempx, *result; if (!(result = (PympqObject*)Pympq_new())) return NULL; if (self && (Pympq_Check(self))) { mpq_mul(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(self)); } else if (Pympq_Check(other)) { mpq_mul(result->q, Pympq_AS_MPQ(other), Pympq_AS_MPQ(other)); } else { if (!(tempx = Pympq_From_Rational(other))) { TYPE_ERROR("square() requires 'mpq' argument"); Py_DECREF((PyObject*)result); return NULL; } else { mpq_mul(result->q, Pympq_AS_MPQ(tempx), Pympq_AS_MPQ(tempx)); Py_DECREF((PyObject*)tempx); } } return (PyObject*)result; } static PyObject * Pympq_pow(PyObject *base, PyObject *exp, PyObject *m) { PympqObject *rq, *tempbq; PympzObject *tempez; #ifdef WITHMPFR PympfrObject *rf, *tempbf, *tempef; #endif int esign, bsign; mpir_si tempexp; if ((PyObject*)m != Py_None) { TYPE_ERROR("mpq.pow() no modulo allowed"); return NULL; } /* Only support mpq**int. Everything else gets converted to mpf. */ if (isRational(base) && isInteger(exp)) { tempbq = Pympq_From_Rational(base); tempez = Pympz_From_Integer(exp); if (!tempbq || !tempez) { Py_XDECREF((PyObject*)tempbq); Py_XDECREF((PyObject*)tempez); return NULL; } if (!mpz_fits_slong_p(tempez->z)) { VALUE_ERROR("mpq.pow() outrageous exponent"); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } esign = mpz_sgn(tempez->z); if (esign == 0) { mpq_set_si(rq->q, 1, 1); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return (PyObject*)rq; } bsign = mpq_sgn(tempbq->q); if (esign < 0) { if (bsign == 0) { ZERO_ERROR("mpq.pow() 0 base to negative exponent"); Py_DECREF((PyObject*)rq); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } if (bsign < 0) { mpz_neg(mpq_numref(rq->q), mpq_denref(tempbq->q)); } else { mpz_set(mpq_numref(rq->q), mpq_denref(tempbq->q)); } mpz_abs(mpq_denref(rq->q), mpq_numref(tempbq->q)); tempexp = -mpz_get_si(tempez->z); } else { mpq_set(rq->q, tempbq->q); tempexp = mpz_get_si(tempez->z); } if (tempexp>1) { mpz_pow_ui(mpq_numref(rq->q), mpq_numref(rq->q), tempexp); mpz_pow_ui(mpq_denref(rq->q), mpq_denref(rq->q), tempexp); } Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return (PyObject*)rq; } else { #ifdef WITHMPFR tempbf = Pympfr_From_Real(base, 0); tempef = Pympfr_From_Real(exp, 0); rf = (PympfrObject*)Pympfr_new(0); if (!tempbf || !tempef || !rf) { TYPE_ERROR("mpq.pow() unsupported operands"); Py_XDECREF((PyObject*)tempbf); Py_XDECREF((PyObject*)tempef); Py_XDECREF((PyObject*)rf); return NULL; } rf->rc = mpfr_pow(rf->f, tempbf->f, tempef->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)tempbf); Py_DECREF((PyObject*)tempef); return (PyObject*)rf; #else TYPE_ERROR("mpq.pow() unsupported operands"); return NULL; #endif } } static int Pympq_nonzero(PympqObject *self) { return mpq_sgn(self->q) != 0; } static Py_hash_t Pympq_hash(PympqObject *self) { #ifdef _PyHASH_MODULUS Py_hash_t hash = 0; mpz_t temp, temp1, mask; if (self->hash_cache != -1) return self->hash_cache; mpz_inoc(temp); mpz_inoc(temp1); mpz_inoc(mask); mpz_set_si(mask, 1); mpz_mul_2exp(mask, mask, _PyHASH_BITS); mpz_sub_ui(mask, mask, 1); if (!mpz_invert(temp, mpq_denref(self->q), mask)) { mpz_cloc(temp); mpz_cloc(temp1); mpz_cloc(mask); hash = _PyHASH_INF; if (mpz_sgn(mpq_numref(self->q))<0) hash = -hash; self->hash_cache = hash; return hash; } mpz_set(temp1, mask); mpz_sub_ui(temp1, temp1, 2); mpz_powm(temp, mpq_denref(self->q), temp1, mask); mpz_tdiv_r(temp1, mpq_numref(self->q), mask); mpz_mul(temp, temp, temp1); hash = (Py_hash_t)mpn_mod_1(temp->_mp_d, mpz_size(temp), _PyHASH_MODULUS); if (mpz_sgn(mpq_numref(self->q))<0) hash = -hash; if (hash==-1) hash = -2; mpz_cloc(temp); mpz_cloc(temp1); mpz_cloc(mask); self->hash_cache = hash; return hash; #else PyObject *temp; if (self->hash_cache != -1) return self->hash_cache; if (!(temp = Pympq_To_PyFloat(self))) { SYSTEM_ERROR("Could not convert 'mpq' to float."); return -1; } self->hash_cache = PyObject_Hash(temp); Py_DECREF(temp); return self->hash_cache; #endif } static PyObject * Pympq_add(PyObject *self, PyObject *args) { PympqObject *result; PyObject *other; PARSE_TWO_MPQ(other, "add() requires 'mpq','mpq' arguments"); if ((result = (PympqObject*)Pympq_new())) mpq_add(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympq_sub(PyObject *self, PyObject *args) { PympqObject *result; PyObject *other; PARSE_TWO_MPQ(other, "sub() requires 'mpq','mpq' arguments"); if ((result = (PympqObject*)Pympq_new())) mpq_sub(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympq_mul(PyObject *self, PyObject *args) { PympqObject *result; PyObject *other; PARSE_TWO_MPQ(other, "mul() requires 'mpq','mpq' arguments"); if ((result = (PympqObject*)Pympq_new())) mpq_mul(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympq_div(PyObject *self, PyObject *args) { PympqObject *result; PyObject *other; PARSE_TWO_MPQ(other, "div() requires 'mpq','mpq' arguments"); if ((result = (PympqObject*)Pympq_new())) { if (mpq_sgn(Pympq_AS_MPQ(other)) == 0) { ZERO_ERROR("'mpq' division by zero"); Py_DECREF((PyObject*)result); result = 0; } else { mpq_div(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); } } Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } PyDoc_STRVAR(doc_mpq_sizeof, "x.__sizeof__()\n\n" "Returns the amount of memory consumed by x. Note: deleted mpq objects\n" "are reused and may or may not be resized when a new value is assigned."); static PyObject * Pympq_sizeof(PyObject *self, PyObject *other) { return PyIntOrLong_FromSize_t(sizeof(PympqObject) + \ (mpq_numref(Pympq_AS_MPQ(self))->_mp_alloc * sizeof(mp_limb_t)) + \ (mpq_denref(Pympq_AS_MPQ(self))->_mp_alloc * sizeof(mp_limb_t))); } #ifdef PY3 static PyNumberMethods mpq_number_methods = { (binaryfunc) Pybasic_add, /* nb_add */ (binaryfunc) Pybasic_sub, /* nb_subtract */ (binaryfunc) Pybasic_mul, /* nb_multiply */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympq_neg, /* nb_negative */ (unaryfunc) Pympq_pos, /* nb_positive */ (unaryfunc) Pympq_abs, /* nb_absolute */ (inquiry) Pympq_nonzero, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ (unaryfunc) Pympq_To_PyLong, /* nb_int */ 0, /* nb_reserved */ (unaryfunc) Pympq_To_PyFloat, /* nb_float */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pybasic_truediv, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ 0, /* nb_index */ }; #else static PyNumberMethods mpq_number_methods = { (binaryfunc) Pybasic_add, /* nb_add */ (binaryfunc) Pybasic_sub, /* nb_subtract */ (binaryfunc) Pybasic_mul, /* nb_multiply */ (binaryfunc) Pybasic_div2, /* nb_divide */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympq_neg, /* nb_negative */ (unaryfunc) Pympq_pos, /* nb_positive */ (unaryfunc) Pympq_abs, /* nb_absolute */ (inquiry) Pympq_nonzero, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ 0, /* nb_coerce */ (unaryfunc) Pympq_To_PyInt, /* nb_int */ (unaryfunc) Pympq_To_PyLong, /* nb_long */ (unaryfunc) Pympq_To_PyFloat, /* nb_float */ 0, /* nb_oct */ 0, /* nb_hex */ 0, /* nb_inplace_add; */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_divide */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pybasic_truediv, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ }; #endif static PyGetSetDef Pympq_getseters[] = { { "numerator", (getter)Pympq_getnumer, NULL, "numerator", NULL }, { "denominator", (getter)Pympq_getdenom, NULL, "denominator", NULL }, {NULL} }; static PyMethodDef Pympq_methods [] = { { "__ceil__", Pympq_ceil, METH_NOARGS, doc_mpq_ceil }, { "__floor__", Pympq_floor, METH_NOARGS, doc_mpq_floor }, { "__round__", Pympq_round, METH_VARARGS, doc_mpq_round }, { "__sizeof__", Pympq_sizeof, METH_NOARGS, doc_mpq_sizeof }, { "__trunc__", Pympq_trunc, METH_NOARGS, doc_mpq_trunc }, { "digits", Pympq_digits, METH_VARARGS, doc_qdigitsm }, { NULL, NULL, 1 } }; static PyTypeObject Pympq_Type = { /* PyObject_HEAD_INIT(&PyType_Type) */ #ifdef PY3 PyVarObject_HEAD_INIT(NULL, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "mpq", /* tp_name */ sizeof(PympqObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor) Pympq_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) Pympq_To_Repr, /* tp_repr */ &mpq_number_methods, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc) Pympq_hash, /* tp_hash */ 0, /* tp_call */ (reprfunc) Pympq_To_Str, /* tp_str */ (getattrofunc) 0, /* tp_getattro */ (setattrofunc) 0, /* tp_setattro */ 0, /* tp_as_buffer */ #ifdef PY3 Py_TPFLAGS_DEFAULT, /* tp_flags */ #else Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ #endif "Multiple precision rational", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)&mpany_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ Pympq_methods, /* tp_methods */ 0, /* tp_members */ Pympq_getseters, /* tp_getset */ }; gmpy2-2.0.7/src/gmpy_mpmath.c0000666000000000000000000003055512542614506014552 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpmath.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Internal helper function for mpmath. */ static PyObject * mpmath_build_mpf(long sign, PympzObject *man, PyObject *exp, mpir_si bc) { PyObject *tup, *tsign, *tbc; if (!(tup = PyTuple_New(4))) { Py_DECREF((PyObject*)man); Py_DECREF(exp); return NULL; } if (!(tsign = PyIntOrLong_FromLong(sign))) { Py_DECREF((PyObject*)man); Py_DECREF(exp); Py_DECREF(tup); return NULL; } if (!(tbc = PyIntOrLong_FromSI(bc))) { Py_DECREF((PyObject*)man); Py_DECREF(exp); Py_DECREF(tup); Py_DECREF(tsign); return NULL; } PyTuple_SET_ITEM(tup, 0, tsign); PyTuple_SET_ITEM(tup, 1, (PyObject*)man); PyTuple_SET_ITEM(tup, 2, (exp)?exp:PyIntOrLong_FromLong(0)); PyTuple_SET_ITEM(tup, 3, tbc); return tup; } PyDoc_STRVAR(doc_mpmath_normalizeg, "_mpmath_normalize(...): helper function for mpmath."); static PyObject * Pympz_mpmath_normalize(PyObject *self, PyObject *args) { long sign = 0; mpir_si bc = 0, prec = 0, shift, zbits, carry = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0, *rndstr = 0; PympzObject *man = 0, *upper = 0, *lower = 0; char rnd = 0; if (PyTuple_GET_SIZE(args) == 6) { /* Need better error-checking here. Under Python 3.0, overflow into C-long is possible. */ sign = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); man = (PympzObject *)PyTuple_GET_ITEM(args, 1); exp = PyTuple_GET_ITEM(args, 2); bc = SI_From_Integer(PyTuple_GET_ITEM(args, 3)); prec = SI_From_Integer(PyTuple_GET_ITEM(args, 4)); rndstr = PyTuple_GET_ITEM(args, 5); if (PyErr_Occurred()) { TYPE_ERROR("arguments long, PympzObject*, PyObject*, long, long, char needed"); return NULL; } } else { TYPE_ERROR("6 arguments required"); return NULL; } if (!Pympz_Check(man)) { TYPE_ERROR("argument is not an mpz"); return NULL; } /* If rndstr really is a string, extract the first character. */ if (Py2or3String_Check(rndstr)) { rnd = Py2or3String_AsString(rndstr)[0]; } else { VALUE_ERROR("invalid rounding mode specified"); return NULL; } /* If the mantissa is 0, return the normalized representation. */ if (!mpz_sgn(man->z)) { Py_INCREF((PyObject*)man); return mpmath_build_mpf(0, man, 0, 0); } /* if bc <= prec and the number is odd return it */ if ((bc <= prec) && mpz_odd_p(man->z)) { Py_INCREF((PyObject*)man); Py_INCREF((PyObject*)exp); return mpmath_build_mpf(sign, man, exp, bc); } if (!(upper = (PympzObject*)Pympz_new()) || !(lower = (PympzObject*)Pympz_new())) { Py_XDECREF((PyObject*)upper); Py_XDECREF((PyObject*)lower); } shift = bc - prec; if (shift>0) { switch (rnd) { case 'f': if(sign) { mpz_cdiv_q_2exp(upper->z, man->z, shift); } else { mpz_fdiv_q_2exp(upper->z, man->z, shift); } break; case 'c': if(sign) { mpz_fdiv_q_2exp(upper->z, man->z, shift); } else { mpz_cdiv_q_2exp(upper->z, man->z, shift); } break; case 'd': mpz_fdiv_q_2exp(upper->z, man->z, shift); break; case 'u': mpz_cdiv_q_2exp(upper->z, man->z, shift); break; case 'n': default: mpz_tdiv_r_2exp(lower->z, man->z, shift); mpz_tdiv_q_2exp(upper->z, man->z, shift); if (mpz_sgn(lower->z)) { /* lower is not 0 so it must have at least 1 bit set */ if (mpz_sizeinbase(lower->z, 2) == shift) { /* lower is >= 1/2 */ if (mpz_scan1(lower->z, 0) == shift-1) { /* lower is exactly 1/2 */ if (mpz_odd_p(upper->z)) carry = 1; } else { carry = 1; } } } if (carry) mpz_add_ui(upper->z, upper->z, 1); } if (!(tmp = PyIntOrLong_FromSI(shift))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); return NULL; } if (!(newexp = PyNumber_Add(exp, tmp))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); return NULL; } Py_DECREF(tmp); bc = prec; } else { mpz_set(upper->z, man->z); newexp = exp; Py_INCREF(newexp); } /* Strip trailing 0 bits. */ if ((zbits = mpz_scan1(upper->z, 0))) mpz_tdiv_q_2exp(upper->z, upper->z, zbits); if (!(tmp = PyIntOrLong_FromSI(zbits))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(newexp); return NULL; } if (!(newexp2 = PyNumber_Add(newexp, tmp))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); Py_DECREF(newexp); return NULL; } Py_DECREF(newexp); Py_DECREF(tmp); bc -= zbits; /* Check if one less than a power of 2 was rounded up. */ if (!mpz_cmp_ui(upper->z, 1)) bc = 1; Py_DECREF((PyObject*)lower); return mpmath_build_mpf(sign, upper, newexp2, bc); } PyDoc_STRVAR(doc_mpmath_createg, "_mpmath_create(...): helper function for mpmath."); static PyObject * Pympz_mpmath_create(PyObject *self, PyObject *args) { long sign; mpir_si bc, shift, zbits, carry = 0, prec = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0; PympzObject *man = 0, *upper = 0, *lower = 0; const char *rnd = "f"; if (PyTuple_GET_SIZE(args) < 2) { TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments"); return NULL; } switch (PyTuple_GET_SIZE(args)) { case 4: rnd = Py2or3String_AsString(PyTuple_GET_ITEM(args, 3)); case 3: prec = SI_From_Integer(PyTuple_GET_ITEM(args, 2)); if (prec == -1 && PyErr_Occurred()) return NULL; prec = ABS(prec); case 2: exp = PyTuple_GET_ITEM(args, 1); case 1: man = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); if (!man) { TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments"); return NULL; } } /* If the mantissa is 0, return the normalized representation. */ if (!mpz_sgn(man->z)) { return mpmath_build_mpf(0, man, 0, 0); } upper = (PympzObject*)Pympz_new(); lower = (PympzObject*)Pympz_new(); if (!upper || !lower) { Py_DECREF((PyObject*)man); Py_XDECREF((PyObject*)upper); Py_XDECREF((PyObject*)lower); return NULL; } /* Extract sign, make man positive, and set bit count */ sign = (mpz_sgn(man->z) == -1); mpz_abs(upper->z, man->z); bc = mpz_sizeinbase(upper->z, 2); if (!prec) prec = bc; shift = bc - prec; if (shift > 0) { switch (rnd[0]) { case 'f': if(sign) { mpz_cdiv_q_2exp(upper->z, upper->z, shift); } else { mpz_fdiv_q_2exp(upper->z, upper->z, shift); } break; case 'c': if(sign) { mpz_fdiv_q_2exp(upper->z, upper->z, shift); } else { mpz_cdiv_q_2exp(upper->z, upper->z, shift); } break; case 'd': mpz_fdiv_q_2exp(upper->z, upper->z, shift); break; case 'u': mpz_cdiv_q_2exp(upper->z, upper->z, shift); break; case 'n': default: mpz_tdiv_r_2exp(lower->z, upper->z, shift); mpz_tdiv_q_2exp(upper->z, upper->z, shift); if (mpz_sgn(lower->z)) { /* lower is not 0 so it must have at least 1 bit set */ if (mpz_sizeinbase(lower->z, 2)==shift) { /* lower is >= 1/2 */ if (mpz_scan1(lower->z, 0)==shift-1) { /* lower is exactly 1/2 */ if (mpz_odd_p(upper->z)) carry = 1; } else { carry = 1; } } } if (carry) mpz_add_ui(upper->z, upper->z, 1); } if (!(tmp = PyIntOrLong_FromSI(shift))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); return NULL; } if (!(newexp = PyNumber_Add(exp, tmp))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); return NULL; } Py_DECREF(tmp); bc = prec; } else { newexp = exp; Py_INCREF(newexp); } /* Strip trailing 0 bits. */ if ((zbits = mpz_scan1(upper->z, 0))) mpz_tdiv_q_2exp(upper->z, upper->z, zbits); if (!(tmp = PyIntOrLong_FromSI(zbits))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(newexp); return NULL; } if (!(newexp2 = PyNumber_Add(newexp, tmp))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); Py_DECREF(newexp); return NULL; } Py_DECREF(newexp); Py_DECREF(tmp); bc -= zbits; /* Check if one less than a power of 2 was rounded up. */ if (!mpz_cmp_ui(upper->z, 1)) bc = 1; Py_DECREF((PyObject*)lower); Py_DECREF((PyObject*)man); return mpmath_build_mpf(sign, upper, newexp2, bc); } gmpy2-2.0.7/src/gmpy_mpfr.h0000666000000000000000000004477412542614506014245 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpfr.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* gmpy_mpfr C API extension header file. * * Provide interface to the MPFR (Multiple Precision Floating-point with * Rounding) library. * * Version 2.00, April 2011 (created) casevh */ #ifndef GMPY_MPFR_H #define GMPY_MPFR_H #ifdef __cplusplus extern "C" { #endif #if !defined(FLT_RADIX) || (FLT_RADIX!=2) # error "FLT_RADIX undefined or != 2, GMPY2 is confused. :(" #endif #if defined(MS_WIN32) && defined(_MSC_VER) # pragma comment(lib,"mpfr.lib") #endif typedef struct { PyObject_HEAD mpfr_t f; Py_hash_t hash_cache; int rc; int round_mode; } PympfrObject; #define GMPY_DIVZERO(msg) PyErr_SetString(GMPyExc_DivZero, msg) #define GMPY_INEXACT(msg) PyErr_SetString(GMPyExc_Inexact, msg) #define GMPY_INVALID(msg) PyErr_SetString(GMPyExc_Invalid, msg) #define GMPY_OVERFLOW(msg) PyErr_SetString(GMPyExc_Overflow, msg) #define GMPY_UNDERFLOW(msg) PyErr_SetString(GMPyExc_Underflow, msg) #define GMPY_ERANGE(msg) PyErr_SetString(GMPyExc_Erange, msg) #define GMPY_EXPBOUND(msg) PyErr_SetString(GMPyExc_ExpBound, msg) #define CHECK_UNDERFLOW(msg) \ if (mpfr_underflow_p() && context->ctx.trap_underflow) { \ GMPY_UNDERFLOW(msg); \ goto done; \ } #define MPFR_CHECK_UNDERFLOW(mpfrt, msg) \ if (mpfr_zero_p(mpfrt->f) && mpfrt->rc) { \ context->ctx.underflow = 1; \ if (context->ctx.trap_underflow) { \ GMPY_UNDERFLOW(msg); \ goto done; \ } \ } #define CHECK_OVERFLOW(msg) \ if (mpfr_overflow_p() && context->ctx.trap_overflow) { \ GMPY_OVERFLOW(msg); \ goto done; \ } #define MPFR_CHECK_OVERFLOW(mpfrt, msg) \ if (mpfr_inf_p(mpfrt->f)) { \ context->ctx.overflow = 1; \ if (context->ctx.trap_overflow) { \ GMPY_OVERFLOW(msg); \ goto done; \ } \ } #define CHECK_INEXACT(msg) \ if (mpfr_inexflag_p() && context->ctx.trap_inexact) { \ GMPY_INEXACT(msg); \ goto done; \ } #define MPFR_CHECK_INEXACT(mpfrt, msg) \ if (mpfrt->rc) { \ context->ctx.inexact = 1; \ if (context->ctx.trap_inexact) { \ GMPY_INEXACT(msg); \ goto done; \ } \ } #define CHECK_INVALID(msg) \ if (mpfr_nanflag_p() && context->ctx.trap_invalid) { \ GMPY_INVALID(msg); \ goto done; \ } #define MPFR_CHECK_INVALID(mpfrt, msg) \ if (mpfr_nan_p(mpfrt->f)) { \ context->ctx.invalid = 1; \ if (context->ctx.trap_invalid) { \ GMPY_INVALID(msg); \ goto done; \ } \ } #define CHECK_ERANGE(msg) \ if (mpfr_erangeflag_p() && context->ctx.trap_erange) { \ GMPY_ERANGE(msg); \ goto done; \ } #define CHECK_DIVBY0(msg) \ if (mpfr_divby0_p() && context->ctx.trap_divzero) { \ GMPY_DIVZERO(msg); \ goto done; \ } #define MERGE_FLAGS \ context->ctx.underflow |= mpfr_underflow_p(); \ context->ctx.overflow |= mpfr_overflow_p(); \ context->ctx.invalid |= mpfr_nanflag_p(); \ context->ctx.inexact |= mpfr_inexflag_p(); \ context->ctx.erange |= mpfr_erangeflag_p(); \ context->ctx.divzero |= mpfr_divby0_p(); #define CHECK_FLAGS(NAME) \ CHECK_DIVBY0("'mpfr' division by zero in "NAME); \ CHECK_INVALID("'mpfr' invalid operation in "NAME); \ CHECK_UNDERFLOW("'mpfr' underflow in "NAME); \ CHECK_OVERFLOW("'mpfr' overflow in "NAME); \ CHECK_INEXACT("'mpfr' inexact result in "NAME); \ #define MPFR_CHECK_FLAGS(mpfrt, NAME) \ CHECK_DIVBY0(mpfrt, "'mpfr' division by zero in "NAME); \ CHECK_INVALID(mpfrt, "'mpfr' invalid operation in "NAME); \ CHECK_UNDERFLOW(mpfrt, "'mpfr' underflow in "NAME); \ CHECK_OVERFLOW(mpfrt, "'mpfr' overflow in "NAME); \ CHECK_INEXACT(mpfrt, "'mpfr' inexact result in "NAME); \ #define SUBNORMALIZE(NAME) \ if (context->ctx.subnormalize) \ NAME->rc = mpfr_subnormalize(NAME->f, NAME->rc, context->ctx.mpfr_round); #define MPFR_SUBNORMALIZE(mpfrt) \ if (context->ctx.subnormalize) \ mpfrt->rc = mpfr_subnormalize(mpfrt->f, mpfrt->rc, context->ctx.mpfr_round); #define MPFR_CLEANUP_SELF(NAME) \ SUBNORMALIZE(result); \ MERGE_FLAGS; \ CHECK_DIVBY0("'mpfr' division by zero in "NAME); \ CHECK_INVALID("'mpfr' invalid operation in "NAME); \ CHECK_UNDERFLOW("'mpfr' underflow in "NAME); \ CHECK_OVERFLOW("'mpfr' overflow in "NAME); \ CHECK_INEXACT("'mpfr' inexact result in "NAME); \ done: \ Py_DECREF(self); \ if (PyErr_Occurred()) { \ Py_XDECREF((PyObject*)result); \ result = NULL; \ } \ return (PyObject*)result; #define MPFR_CLEANUP_SELF_OTHER(NAME) \ SUBNORMALIZE(result); \ MERGE_FLAGS; \ CHECK_DIVBY0("'mpfr' division by zero in "NAME); \ CHECK_INVALID("'mpfr' invalid operation in "NAME); \ CHECK_UNDERFLOW("'mpfr' underflow in "NAME); \ CHECK_OVERFLOW("'mpfr' overflow in "NAME); \ CHECK_INEXACT("'mpfr' inexact result in "NAME); \ done: \ Py_DECREF(self); \ Py_DECREF(other); \ if (PyErr_Occurred()) { \ Py_XDECREF((PyObject*)result); \ result = NULL; \ } \ return (PyObject*)result; #define MPFR_CLEANUP_RF(NAME) \ SUBNORMALIZE(rf); \ MERGE_FLAGS; \ if (mpfr_nanflag_p() && context->ctx.trap_invalid) { \ GMPY_INVALID("'mpfr' invalid operation in " #NAME); \ Py_DECREF((PyObject*)rf); \ return NULL; \ } \ if (mpfr_divby0_p() && context->ctx.trap_divzero) { \ GMPY_DIVZERO("'mpfr' division by zero in " #NAME); \ Py_DECREF((PyObject*)rf); \ return NULL; \ } \ if (mpfr_underflow_p() && context->ctx.trap_underflow) { \ GMPY_UNDERFLOW("'mpfr' underflow in " #NAME); \ Py_DECREF((PyObject*)rf); \ return NULL; \ } \ if (mpfr_overflow_p() && context->ctx.trap_overflow) { \ GMPY_OVERFLOW("'mpfr' overflow in " #NAME); \ Py_DECREF((PyObject*)rf); \ return NULL; \ } \ if (mpfr_inexflag_p() && context->ctx.trap_inexact) { \ GMPY_INEXACT("'mpfr' inexact result in " #NAME); \ Py_DECREF((PyObject*)rf); \ return NULL; \ } \ return (PyObject*)rf; #define MPFR_CLEANUP_RESULT(NAME) \ SUBNORMALIZE(result); \ MERGE_FLAGS; \ if (mpfr_nanflag_p() && context->ctx.trap_invalid) { \ GMPY_INVALID("'mpfr' invalid operation in " #NAME); \ Py_DECREF((PyObject*)result); \ return NULL; \ } \ if (mpfr_divby0_p() && context->ctx.trap_divzero) { \ GMPY_DIVZERO("'mpfr' division by zero in " #NAME); \ Py_DECREF((PyObject*)result); \ return NULL; \ } \ if (mpfr_underflow_p() && context->ctx.trap_underflow) { \ GMPY_UNDERFLOW("'mpfr' underflow in " #NAME); \ Py_DECREF((PyObject*)result); \ return NULL; \ } \ if (mpfr_overflow_p() && context->ctx.trap_overflow) { \ GMPY_OVERFLOW("'mpfr' overflow in " #NAME); \ Py_DECREF((PyObject*)result); \ return NULL; \ } \ if (mpfr_inexflag_p() && context->ctx.trap_inexact) { \ GMPY_INEXACT("'mpfr' inexact result in " #NAME); \ Py_DECREF((PyObject*)result); \ return NULL; \ } \ return (PyObject*)result; static PyTypeObject Pympfr_Type; #define Pympfr_AS_MPFR(obj) (((PympfrObject *)(obj))->f) #define Pympfr_Check(v) (((PyObject*)v)->ob_type == &Pympfr_Type) /* Verify that an object is an mpfr and the exponent is valid */ #define Pympfr_CheckAndExp(v) \ (Pympfr_Check(v) && \ (mpfr_zero_p(Pympfr_AS_MPFR(v)) || \ (mpfr_regular_p(Pympfr_AS_MPFR(v)) && \ (Pympfr_AS_MPFR(v)->_mpfr_exp >= context->ctx.emin) && \ (Pympfr_AS_MPFR(v)->_mpfr_exp <= context->ctx.emax) \ ) \ ) \ ) static PyObject * Pympfr_f2q(PyObject *self, PyObject *args); static PyObject * Pygmpy_mpfr(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pympfr_getprec_attrib(PympfrObject *self, void *closure); static PyObject * Pympfr_getrc_attrib(PympfrObject *self, void *closure); static PyObject * Pympfr_getimag_attrib(PympfrObject *self, void *closure); static PyObject * Pympfr_getreal_attrib(PympfrObject *self, void *closure); static int Pympfr_nonzero(PympfrObject *self); static PyObject * Pympfr_conjugate(PyObject *self, PyObject *args); static PyObject * Pympfr_pos(PympfrObject *self); static PyObject * Pympfr_get_emin_min(PyObject *self, PyObject *args); static PyObject * Pympfr_get_emax_max(PyObject *self, PyObject *args); static PyObject * Pympfr_get_max_precision(PyObject *self, PyObject *args); static PyObject * Pympfr_get_exp(PyObject *self, PyObject *other); static PyObject * Pympfr_set_exp(PyObject *self, PyObject *args); static PyObject * Pympfr_set_sign(PyObject *self, PyObject *args); static PyObject * Pympfr_copy_sign(PyObject *self, PyObject *args); static PyObject * Pympfr_div_2exp(PyObject *self, PyObject *args); static PyObject * Pympfr_mul_2exp(PyObject *self, PyObject *args); static PyObject * Pympfr_set_nan(PyObject *self, PyObject *other); static PyObject * Pympfr_set_inf(PyObject *self, PyObject *args); static PyObject * Pympfr_set_zero(PyObject *self, PyObject *args); static PyObject * Pympfr_is_signed(PyObject *self, PyObject *other); static PyObject * Pympfr_is_nan(PyObject *self, PyObject *other); /* Pympfr_is_number is used to implement is_finite. */ static PyObject * Pympfr_is_number(PyObject *self, PyObject *other); /* Pympfr_is_inf is used to implement is_infinite. */ static PyObject * Pympfr_is_inf(PyObject *self, PyObject *other); static PyObject * Pympfr_is_zero(PyObject *self, PyObject *other); static PyObject * Pympfr_is_regular(PyObject *self, PyObject *other); static PyObject * Pympfr_is_integer(PyObject *self, PyObject *other); static PyObject * Pympfr_digits(PyObject *self, PyObject *args); static PyObject * Pympfr_integer_ratio(PyObject *self, PyObject *args); static PyObject * Pympfr_mantissa_exp(PyObject *self, PyObject *args); static PyObject * Pympfr_simple_fraction(PyObject *self, PyObject *args, PyObject *keywds); static Py_hash_t Pympfr_hash(PympfrObject *self); static PyObject * Pympfr_pow(PyObject *base, PyObject *exp, PyObject *m); static PyObject * Pympfr_const_pi(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pympfr_const_euler(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pympfr_const_log2(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pympfr_const_catalan(PyObject *self, PyObject *args, PyObject *keywds); static PyObject * Pympfr_sqrt(PyObject *self, PyObject *other); static PyObject * Pympfr_rec_sqrt(PyObject *self, PyObject *other); static PyObject * Pympfr_root(PyObject *self, PyObject *args); static PyObject * Pympfr_reldiff(PyObject *self, PyObject *args); static PyObject * Pympfr_sign(PyObject *self, PyObject *other); static PyObject * Pympfr_abs(PympfrObject *x); static PyObject * Pympfr_neg(PympfrObject *x); static PyObject * Pympfr_ceil(PyObject *self, PyObject *other); static PyObject * Pympfr_floor(PyObject *self, PyObject *other); static PyObject * Pympfr_trunc(PyObject *self, PyObject *other); static PyObject * Pympfr_round2(PyObject *self, PyObject *args); static PyObject * Pympfr_round10(PyObject *self, PyObject *args); static PyObject * Pympfr_round_away(PyObject* self, PyObject *other); static PyObject * Pympfr_rint(PyObject* self, PyObject *other); static PyObject * Pympfr_rint_ceil(PyObject* self, PyObject *other); static PyObject * Pympfr_rint_floor(PyObject* self, PyObject *other); static PyObject * Pympfr_rint_trunc(PyObject* self, PyObject *other); static PyObject * Pympfr_frac(PyObject* self, PyObject *other); static PyObject * Pympfr_modf(PyObject* self, PyObject *other); static PyObject * Pympfr_sqr(PyObject* self, PyObject *other); static PyObject * Pympfr_cbrt(PyObject* self, PyObject *other); static PyObject * Pympfr_log(PyObject* self, PyObject *other); static PyObject * Pympfr_log2(PyObject* self, PyObject *other); static PyObject * Pympfr_log10(PyObject* self, PyObject *other); static PyObject * Pympfr_exp(PyObject* self, PyObject *other); static PyObject * Pympfr_exp2(PyObject* self, PyObject *other); static PyObject * Pympfr_exp10(PyObject* self, PyObject *other); static PyObject * Pympfr_sin(PyObject* self, PyObject *other); static PyObject * Pympfr_cos(PyObject* self, PyObject *other); static PyObject * Pympfr_tan(PyObject* self, PyObject *other); static PyObject * Pympfr_sec(PyObject* self, PyObject *other); static PyObject * Pympfr_csc(PyObject* self, PyObject *other); static PyObject * Pympfr_cot(PyObject* self, PyObject *other); static PyObject * Pympfr_acos(PyObject* self, PyObject *other); static PyObject * Pympfr_asin(PyObject* self, PyObject *other); static PyObject * Pympfr_atan(PyObject* self, PyObject *other); static PyObject * Pympfr_cosh(PyObject* self, PyObject *other); static PyObject * Pympfr_sinh(PyObject* self, PyObject *other); static PyObject * Pympfr_tanh(PyObject* self, PyObject *other); static PyObject * Pympfr_sech(PyObject* self, PyObject *other); static PyObject * Pympfr_csch(PyObject* self, PyObject *other); static PyObject * Pympfr_coth(PyObject* self, PyObject *other); static PyObject * Pympfr_acosh(PyObject* self, PyObject *other); static PyObject * Pympfr_asinh(PyObject* self, PyObject *other); static PyObject * Pympfr_atanh(PyObject* self, PyObject *other); static PyObject * Pympfr_log1p(PyObject* self, PyObject *other); static PyObject * Pympfr_expm1(PyObject* self, PyObject *other); static PyObject * Pympfr_eint(PyObject* self, PyObject *other); static PyObject * Pympfr_li2(PyObject* self, PyObject *other); static PyObject * Pympfr_gamma(PyObject* self, PyObject *other); static PyObject * Pympfr_lngamma(PyObject* self, PyObject *other); static PyObject * Pympfr_lgamma(PyObject* self, PyObject *other); static PyObject * Pympfr_digamma(PyObject* self, PyObject *other); static PyObject * Pympfr_zeta(PyObject* self, PyObject *other); static PyObject * Pympfr_erf(PyObject* self, PyObject *other); static PyObject * Pympfr_erfc(PyObject* self, PyObject *other); static PyObject * Pympfr_j0(PyObject* self, PyObject *other); static PyObject * Pympfr_j1(PyObject* self, PyObject *other); static PyObject * Pympfr_jn(PyObject* self, PyObject *other); static PyObject * Pympfr_y0(PyObject* self, PyObject *other); static PyObject * Pympfr_y1(PyObject* self, PyObject *other); static PyObject * Pympfr_yn(PyObject* self, PyObject *other); static PyObject * Pympfr_ai(PyObject* self, PyObject *other); static PyObject * Pympfr_add_fast(PyObject *x, PyObject *y); static PyObject * Pympfr_add(PyObject* self, PyObject *other); static PyObject * Pympfr_sub_fast(PyObject *x, PyObject *y); static PyObject * Pympfr_sub(PyObject* self, PyObject *other); static PyObject * Pympfr_mul_fast(PyObject *x, PyObject *y); static PyObject * Pympfr_mul(PyObject *self, PyObject *args); static PyObject * Pympfr_truediv_fast(PyObject *x, PyObject *y); #ifdef PY2 static PyObject * Pympfr_div2_fast(PyObject *x, PyObject *y); #endif static PyObject * Pympfr_div(PyObject *self, PyObject *args); static PyObject * Pympfr_fmod(PyObject *self, PyObject *args); static PyObject * Pympfr_remainder(PyObject *self, PyObject *args); static PyObject * Pympfr_remquo(PyObject* self, PyObject *args); static PyObject * Pympfr_frexp(PyObject *self, PyObject *other); static PyObject * Pympfr_atan2(PyObject *self, PyObject *args); static PyObject * Pympfr_agm(PyObject *self, PyObject *args); static PyObject * Pympfr_hypot(PyObject *self, PyObject *args); static PyObject * Pympfr_max2(PyObject *self, PyObject *args); static PyObject * Pympfr_min2(PyObject *self, PyObject *args); static PyObject * Pympfr_nexttoward(PyObject *self, PyObject *args); static PyObject * Pympfr_nextabove(PyObject *self, PyObject *other); static PyObject * Pympfr_nextbelow(PyObject *self, PyObject *other); static PyObject * Pympfr_sin_cos(PyObject *self, PyObject *other); static PyObject * Pympfr_sinh_cosh(PyObject *self, PyObject *other); static PyObject * Pympfr_fma(PyObject *self, PyObject *args); static PyObject * Pympfr_fms(PyObject *self, PyObject *args); static PyObject * Pympfr_factorial(PyObject *self, PyObject *other); static PyObject * Pympfr_is_lessgreater(PyObject *self, PyObject *args); static PyObject * Pympfr_is_unordered(PyObject *self, PyObject *args); static PyObject * Pympfr_check_range(PyObject *self, PyObject *other); static PyObject * Pympfr_fsum(PyObject *self, PyObject *other); static PyObject * Pympfr_degrees(PyObject *self, PyObject *other); static PyObject * Pympfr_radians(PyObject *self, PyObject *other); static PyObject * Pympfr_format(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpfr.c0000666000000000000000000024712512542614506014233 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpfr.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ PyDoc_STRVAR(doc_g_mpfr_f2q, "f2q(x,[err]) -> mpq\n\n" "Return the 'best' mpq approximating x to within relative error 'err'.\n" "Default is the precision of x. Uses Stern-Brocot tree to find the\n" "'best' approximation. An 'mpz' is returned if the the denominator\n" "is 1. If 'err'<0, error sought is 2.0 ** err."); static PyObject * Pympfr_f2q(PyObject *self, PyObject *args) { PympfrObject *err = 0; PyObject *result; if (!PyArg_ParseTuple(args, "O&|O&", Pympfr_convert_arg, &self, Pympfr_convert_arg, &err)) { TYPE_ERROR("f2q() requires 'mpfr', ['mpfr'] arguments"); return NULL; } result = (PyObject*)stern_brocot((PympfrObject*)self, err, 0, 1); Py_DECREF(self); Py_XDECREF((PyObject*)err); return result; } PyDoc_STRVAR(doc_mpfr, "mpfr() -> mpfr(0.0)\n\n" " If no argument is given, return mpfr(0.0).\n\n" "mpfr(n[, precison=0]) -> mpfr\n\n" " Return an 'mpfr' object after converting a numeric value. If\n" " no precision, or a precision of 0, is specified; the precison\n" " is taken from the current context.\n\n" "mpfr(s[, precision=0[, [base=0]]) -> mpfr\n\n" " Return 'mpfr' object after converting a string 's' made up of\n" " digits in the given base, possibly with fraction-part (with\n" " period as a separator) and/or exponent-part (with exponent\n" " marker 'e' for base<=10, else '@'). If no precision, or a\n" " precision of 0, is specified; the precison is taken from the\n" " current context. The base of the string representation must\n" " be 0 or in the interval 2 ... 62. If the base is 0, the leading\n" " digits of the string are used to identify the base: 0b implies\n" " base=2, 0x implies base=16, otherwise base=10 is assumed.\n"); static PyObject * Pygmpy_mpfr(PyObject *self, PyObject *args, PyObject *keywds) { PympfrObject *result = 0; PyObject *arg0; int base = 0; Py_ssize_t argc; /* Assumes mpfr_prec_t is the same as a long. */ mpfr_prec_t bits = 0; static char *kwlist_s[] = {"s", "precision", "base", NULL}; static char *kwlist_n[] = {"n", "precision", NULL}; argc = PyTuple_Size(args); if ((argc < 0) || (argc > 3)) { TYPE_ERROR("mpfr() requires 0 to 3 arguments"); return NULL; } if (argc == 0) { if ((result = (PympfrObject*)Pympfr_new(0))) { mpfr_set_ui(result->f, 0, context->ctx.mpfr_round); } return (PyObject*)result; } arg0 = PyTuple_GetItem(args, 0); if (PyStrOrUnicode_Check(arg0)) { /* Can have both precision and/or base as keyword arguments. */ if (PyArg_ParseTupleAndKeywords(args, keywds, "O|li", kwlist_s, &arg0, &bits, &base)) { if ((base!=0) && ((base<2)||(base>62))) { VALUE_ERROR("base for mpfr() must be 0 or in the " "interval 2 ... 62"); } else if (bits < 0) { VALUE_ERROR("precision for mpfr() must be >= 0"); } else { result = Pympfr_From_PyStr(arg0, base, bits); } } SUBNORMALIZE(result); return (PyObject*)result; } /* Optimize the common case */ if (isReal(arg0) && argc == 1 && !keywds) { result = Pympfr_From_Real(arg0, bits); SUBNORMALIZE(result); return (PyObject*)result; } /* Can only have precision as keyword argument. */ if (PyArg_ParseTupleAndKeywords(args, keywds, "O|l", kwlist_n, &arg0, &bits)) { if (bits < 0) { VALUE_ERROR("precision for mpfr() must be >= 0"); } else { result = Pympfr_From_Real(arg0, bits); if (!result) TYPE_ERROR("mpfr() requires numeric or string argument"); } } return (PyObject*)result; } /* Implement the .precision attribute of an mpfr. */ static PyObject * Pympfr_getprec_attrib(PympfrObject *self, void *closure) { return PyIntOrLong_FromSsize_t((Py_ssize_t)mpfr_get_prec(self->f)); } /* Implement the .rc attribute of an mpfr. */ static PyObject * Pympfr_getrc_attrib(PympfrObject *self, void *closure) { return PyIntOrLong_FromLong((long)self->rc); } /* Implement the .imag attribute of an mpfr. */ static PyObject * Pympfr_getimag_attrib(PympfrObject *self, void *closure) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(0))) mpfr_set_zero(result->f, 1); return (PyObject*)result; } /* Implement the .real attribute of an mpfr. */ static PyObject * Pympfr_getreal_attrib(PympfrObject *self, void *closure) { return (PyObject*)Pympfr_From_Pympfr((PyObject*)self, 0); } /* Implement the nb_bool slot. */ static int Pympfr_nonzero(PympfrObject *self) { return !mpfr_zero_p(self->f); } /* Implement the conjugate() method. */ PyDoc_STRVAR(doc_mpfr_conjugate, "x.conjugate() -> mpfr\n\n" "Return the conjugate of x (which is just a copy of x since x is\n" "not a complex number)."); static PyObject * Pympfr_conjugate(PyObject *self, PyObject *args) { return (PyObject*)Pympfr_From_Pympfr(self, 0); } /* Implement the nb_positive slot. */ /* TODO: can probably just call Pympfr_From_Real. */ static PyObject * Pympfr_pos(PympfrObject *self) { PympfrObject *result; if (!(result = (PympfrObject*)Pympfr_new(mpfr_get_prec(self->f)))) return NULL; mpfr_clear_flags(); /* Since result has the same precision as self, no rounding occurs. */ mpfr_set(result->f, self->f, context->ctx.mpfr_round); result->round_mode = self->round_mode; result->rc = self->rc; /* Force the exponents to be valid. */ result->rc = mpfr_check_range(result->f, result->rc, result->round_mode); /* Now round result to the current precision. */ result->rc = mpfr_prec_round(result->f, context->ctx.mpfr_prec, context->ctx.mpfr_round); SUBNORMALIZE(result); MERGE_FLAGS; CHECK_FLAGS("__pos__"); done: if (PyErr_Occurred()) { Py_XDECREF((PyObject*)result); result = NULL; } return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_get_emin_min, "get_emin_min() -> integer\n\n" "Return the minimum possible exponent that can be set for 'mpfr'."); static PyObject * Pympfr_get_emin_min(PyObject *self, PyObject *args) { return PyIntOrLong_FromSsize_t((Py_ssize_t)mpfr_get_emin_min()); } PyDoc_STRVAR(doc_g_mpfr_get_emax_max, "get_emax_max() -> integer\n\n" "Return the maximum possible exponent that can be set for 'mpfr'."); static PyObject * Pympfr_get_emax_max(PyObject *self, PyObject *args) { return PyIntOrLong_FromSsize_t((Py_ssize_t)mpfr_get_emax_max()); } PyDoc_STRVAR(doc_g_mpfr_get_max_precision, "get_max_precision() -> integer\n\n" "Return the maximum bits of precision that can be used for calculations.\n" "Note: to allow extra precision for intermediate calculations, avoid\n" "setting precision close the maximum precision."); static PyObject * Pympfr_get_max_precision(PyObject *self, PyObject *args) { return PyIntOrLong_FromSsize_t((Py_ssize_t)MPFR_PREC_MAX); } PyDoc_STRVAR(doc_g_mpfr_get_exp, "get_exp(mpfr) -> integer\n\n" "Return the exponent of an mpfr. Returns 0 for NaN or Infinity and\n" "sets the erange flag and will raise an exception if trap_erange\n" "is set."); static PyObject * Pympfr_get_exp(PyObject *self, PyObject *other) { PyObject *result = 0; Py_ssize_t exp; PARSE_ONE_MPFR_OTHER("get_exp() requires 'mpfr' argument"); if (mpfr_regular_p(Pympfr_AS_MPFR(self))) { exp = (Py_ssize_t)mpfr_get_exp(Pympfr_AS_MPFR(self)); result = PyIntOrLong_FromSsize_t((Py_ssize_t)exp); } else if (mpfr_zero_p(Pympfr_AS_MPFR(self))) { Py_DECREF(self); result = PyIntOrLong_FromSsize_t(0); } else { context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("Can not get exponent from NaN or Infinity."); } else { result = PyIntOrLong_FromSsize_t(0); } } Py_DECREF(self); return result; } PyDoc_STRVAR(doc_g_mpfr_set_exp, "set_exp(mpfr, n) -> mpfr\n\n" "Set the exponent of an mpfr to n. If n is outside the range of\n" "valid exponents, set_exp() will set the erange flag and either\n" "return the original value or raise an exception if trap_erange\n" "is set."); static PyObject * Pympfr_set_exp(PyObject *self, PyObject *args) { PympfrObject *result = 0; long exp = 0; if (!PyArg_ParseTuple(args, "O&l", Pympfr_convert_arg, &self, &exp)) { TYPE_ERROR("set_exp() requires 'mpfr', 'integer' arguments"); return NULL; } if (!(result = Pympfr_From_Pympfr(self, 0))) return NULL; Py_DECREF(self); result->rc = mpfr_set_exp(Pympfr_AS_MPFR(result), exp); if (result->rc) { context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("New exponent is out-of-bounds."); Py_DECREF(result); return NULL; } } return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_set_sign, "set_sign(mpfr, bool) -> mpfr\n\n" "If 'bool' is True, then return an 'mpfr' with the sign bit set."); static PyObject * Pympfr_set_sign(PyObject *self, PyObject *args) { PympfrObject *result = 0; PyObject *boolean = 0; int s; if (!PyArg_ParseTuple(args, "O&O", Pympfr_convert_arg, &self, &boolean)) { TYPE_ERROR("set_sign() requires 'mpfr', 'boolean' arguments"); return NULL; } if (!(result = (PympfrObject*)Pympfr_new(0))) return NULL; s = PyObject_IsTrue(boolean); if (s == -1) { TYPE_ERROR("set_sign() requires 'mpfr', 'boolean' arguments"); Py_DECREF(self); Py_DECREF(boolean); Py_DECREF(result); return NULL; } result->rc = mpfr_setsign(Pympfr_AS_MPFR(result), Pympfr_AS_MPFR(self), s, context->ctx.mpfr_round); Py_DECREF(self); Py_DECREF(boolean); return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_copy_sign, "copy_sign(mpfr, mpfr) -> mpfr\n\n" "Return an 'mpfr' composed of the first argument with the sign of the\n" "second argument."); static PyObject * Pympfr_copy_sign(PyObject *self, PyObject *args) { PympfrObject *result = 0; PyObject *other = 0; if (!PyArg_ParseTuple(args, "O&O&", Pympfr_convert_arg, &self, Pympfr_convert_arg, &other)) { TYPE_ERROR("copy_sign() requires 'mpfr', 'mpfr' arguments"); return NULL; } if (!(result = (PympfrObject*)Pympfr_new(0))) return NULL; result->rc = mpfr_copysign(Pympfr_AS_MPFR(result), Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympfr_div_2exp(PyObject *self, PyObject *args) { PympfrObject *result = 0; unsigned long exp = 0; if (!PyArg_ParseTuple(args, "O&k", Pympfr_convert_arg, &self, &exp)) { TYPE_ERROR("div_2exp() requires 'mpfr', 'integer' arguments"); return NULL; } if (!(result = (PympfrObject*)Pympfr_new(0))) return NULL; mpfr_clear_flags(); result->rc = mpfr_div_2ui(Pympfr_AS_MPFR(result), Pympfr_AS_MPFR(self), exp, context->ctx.mpfr_round); MPFR_CLEANUP_SELF("div_2exp()"); } static PyObject * Pympfr_mul_2exp(PyObject *self, PyObject *args) { PympfrObject *result = 0; unsigned long exp = 0; if (!PyArg_ParseTuple(args, "O&k", Pympfr_convert_arg, &self, &exp)) { TYPE_ERROR("mul_2exp() requires 'mpfr', 'integer' arguments"); return NULL; } if (!(result = (PympfrObject*)Pympfr_new(0))) return NULL; mpfr_clear_flags(); result->rc = mpfr_mul_2ui(Pympfr_AS_MPFR(result), Pympfr_AS_MPFR(self), exp, context->ctx.mpfr_round); MPFR_CLEANUP_SELF("mul_2exp()"); } PyDoc_STRVAR(doc_g_mpfr_set_nan, "nan() -> mpfr\n\n" "Return an 'mpfr' initialized to NaN (Not-A-Number)."); static PyObject * Pympfr_set_nan(PyObject *self, PyObject *other) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(0))) mpfr_set_nan(result->f); return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_set_inf, "inf(n) -> mpfr\n\n" "Return an 'mpfr' initialized to Infinity with the same sign as n.\n" "If n is not given, +Infinity is returned."); static PyObject * Pympfr_set_inf(PyObject *self, PyObject *args) { PympfrObject *result; long s = 1; if (PyTuple_Size(args) == 1) { s = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); if (s == -1 && PyErr_Occurred()) { TYPE_ERROR("inf() requires 'int' argument"); return NULL; } } if ((result = (PympfrObject*)Pympfr_new(0))) mpfr_set_inf(result->f, s<0?-1:1); return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_set_zero, "zero(n) -> mpfr\n\n" "Return an 'mpfr' inialized to 0.0 with the same sign as n.\n" "If n is not given, +0.0 is returned."); static PyObject * Pympfr_set_zero(PyObject *self, PyObject *args) { PympfrObject *result; long s = 1; if (PyTuple_Size(args) == 1) { s = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); if (s == -1 && PyErr_Occurred()) { TYPE_ERROR("zero() requires 'int' argument"); return NULL; } } if ((result = (PympfrObject*)Pympfr_new(0))) mpfr_set_zero(result->f, s<0?-1:1); return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_is_signed, "is_signed(x) -> boolean\n\n" "Return True if the sign bit of x is set."); static PyObject * Pympfr_is_signed(PyObject *self, PyObject *other) { int res; if(self && Pympfr_Check(self)) { Py_INCREF(self); } else if(Pympfr_Check(other)) { self = other; Py_INCREF((PyObject*)self); } else if (!(self = (PyObject*)Pympfr_From_Real(other, 0))) { TYPE_ERROR("is_signed() requires 'mpfr' argument"); return NULL; } res = mpfr_signbit(Pympfr_AS_MPFR(self)); Py_DECREF(self); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } #define MPFR_TEST_OTHER(NAME, msg) \ static PyObject * \ Pympfr_is_##NAME(PyObject *self, PyObject *other)\ {\ int res;\ if(self && Pympfr_Check(self)) {\ Py_INCREF(self);\ }\ else if(Pympfr_Check(other)) {\ self = other;\ Py_INCREF((PyObject*)self);\ }\ else if (!(self = (PyObject*)Pympfr_From_Real(other, 0))) {\ PyErr_SetString(PyExc_TypeError, msg);\ return NULL;\ }\ res = mpfr_##NAME##_p(Pympfr_AS_MPFR(self));\ Py_DECREF(self);\ if (res)\ Py_RETURN_TRUE;\ else\ Py_RETURN_FALSE;\ } MPFR_TEST_OTHER(nan, "is_nan() requires 'mpfr' argument"); MPFR_TEST_OTHER(inf, "is_infinite() requires 'mpfr' argument"); PyDoc_STRVAR(doc_g_mpfr_is_number, "is_number(x) -> boolean\n\n" "Return True if x is an actual number (i.e. not NaN or Infinity);\n" "False otherwise.\n" "Note: is_number() is deprecated; please use is_finite()."); MPFR_TEST_OTHER(number, "is_finite() requires 'mpfr' argument"); MPFR_TEST_OTHER(zero, "is_zero() requires 'mpfr' argument"); PyDoc_STRVAR(doc_g_mpfr_is_regular, "is_regular(x) -> boolean\n\n" "Return True if x is not zero, NaN, or Infinity; False otherwise."); MPFR_TEST_OTHER(regular, "is_regular() requires 'mpfr' argument"); PyDoc_STRVAR(doc_mpfr_is_integer, "x.is_integer() -> boolean\n\n" "Return True if x is an integer; False otherwise."); PyDoc_STRVAR(doc_g_mpfr_is_integer, "is_integer(x) -> boolean\n\n" "Return True if x is an integer; False otherwise."); MPFR_TEST_OTHER(integer, "is_integer() requires 'mpfr' argument"); /* produce string for an mpfr with requested/defaulted parameters */ PyDoc_STRVAR(doc_mpfr_digits, "x.digits([base=10[, prec=0]]) -> (mantissa, exponent, bits)\n\n" "Returns up to 'prec' digits in the given base. If 'prec' is 0, as many\n" "digits that are available are returned. No more digits than available\n" "given x's precision are returned. 'base' must be between 2 and 62,\n" "inclusive. The result is a three element tuple containing the mantissa,\n" "the exponent, and the number of bits of precision."); /* TODO: support keyword arguments. */ static PyObject * Pympfr_digits(PyObject *self, PyObject *args) { int base = 10; int prec = 0; PyObject *result; if (self && Pympfr_Check(self)) { if (!PyArg_ParseTuple(args, "|ii", &base, &prec)) return NULL; Py_INCREF(self); } else { if(!PyArg_ParseTuple(args, "O&|ii", Pympfr_convert_arg, &self, &base, &prec)) return NULL; } result = Pympfr_To_PyStr((PympfrObject*)self, base, prec); Py_DECREF(self); return result; } PyDoc_STRVAR(doc_mpfr_integer_ratio, "x.as_integer_ratio() -> (num, den)\n\n" "Return the exact rational equivalent of an mpfr. Value is a tuple\n" "for compatibility with Python's float.as_integer_ratio()."); static PyObject * Pympfr_integer_ratio(PyObject *self, PyObject *args) { PympzObject *num = 0, *den = 0; mpfr_exp_t temp, twocount; PyObject *result; if (mpfr_nan_p(Pympfr_AS_MPFR(self))) { VALUE_ERROR("Cannot pass NaN to mpfr.as_integer_ratio."); return NULL; } if (mpfr_inf_p(Pympfr_AS_MPFR(self))) { OVERFLOW_ERROR("Cannot pass Infinity to mpfr.as_integer_ratio."); return NULL; } num = (PympzObject*)Pympz_new(); den = (PympzObject*)Pympz_new(); if (!num || !den) { Py_XDECREF((PyObject*)num); Py_XDECREF((PyObject*)den); return NULL; } if (mpfr_zero_p(Pympfr_AS_MPFR(self))) { mpz_set_ui(num->z, 0); mpz_set_ui(den->z, 1); } else { temp = mpfr_get_z_2exp(num->z, Pympfr_AS_MPFR(self)); twocount = (mpfr_exp_t)mpz_scan1(num->z, 0); if (twocount) { temp += twocount; mpz_div_2exp(num->z, num->z, twocount); } mpz_set_ui(den->z, 1); if (temp > 0) mpz_mul_2exp(num->z, num->z, temp); else if (temp < 0) mpz_mul_2exp(den->z, den->z, -temp); } result = Py_BuildValue("(NN)", (PyObject*)num, (PyObject*)den); if (!result) { Py_DECREF((PyObject*)num); Py_DECREF((PyObject*)den); } return result; } PyDoc_STRVAR(doc_mpfr_mantissa_exp, "x.as_mantissa_exp() -> (mantissa,exponent)\n\n" "Return the mantissa and exponent of an mpfr."); static PyObject * Pympfr_mantissa_exp(PyObject *self, PyObject *args) { PympzObject *mantissa = 0, *exponent = 0; mpfr_exp_t temp; PyObject *result; if (mpfr_nan_p(Pympfr_AS_MPFR(self))) { VALUE_ERROR("Cannot pass NaN to mpfr.as_mantissa_exp."); return NULL; } if (mpfr_inf_p(Pympfr_AS_MPFR(self))) { OVERFLOW_ERROR("Cannot pass Infinity to mpfr.as_mantissa_exp."); return NULL; } mantissa = (PympzObject*)Pympz_new(); exponent = (PympzObject*)Pympz_new(); if (!mantissa || !exponent) { Py_XDECREF((PyObject*)mantissa); Py_XDECREF((PyObject*)exponent); return NULL; } if (mpfr_zero_p(Pympfr_AS_MPFR(self))) { mpz_set_ui(mantissa->z, 0); mpz_set_ui(exponent->z, 1); } else { temp = mpfr_get_z_2exp(mantissa->z, Pympfr_AS_MPFR(self)); mpz_set_si(exponent->z, temp); } result = Py_BuildValue("(NN)", (PyObject*)mantissa, (PyObject*)exponent); if (!result) { Py_DECREF((PyObject*)mantissa); Py_DECREF((PyObject*)exponent); } return result; } PyDoc_STRVAR(doc_mpfr_simple_fraction, "x.as_simple_fraction([precision=0]) -> mpq\n\n" "Return a simple rational approximation to x. The result will be\n" "accurate to 'precision' bits. If 'precision' is 0, the precision\n" "of 'x' will be used."); static PyObject * Pympfr_simple_fraction(PyObject *self, PyObject *args, PyObject *keywds) { mpfr_prec_t prec = 0; static char *kwlist[] = {"precision", NULL}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &prec)) return NULL; return (PyObject*)stern_brocot((PympfrObject*)self, 0, prec, 0); } static Py_hash_t _mpfr_hash(mpfr_t f) { #ifdef _PyHASH_MODULUS Py_uhash_t hash = 0; Py_ssize_t exp; size_t msize; int sign; /* Handle special cases first */ if (!mpfr_number_p(f)) { if (mpfr_inf_p(f)) if (mpfr_sgn(f) > 0) return _PyHASH_INF; else return -_PyHASH_INF; else return _PyHASH_NAN; } /* Calculate the number of limbs in the mantissa. */ msize = (f->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb; /* Calculate the hash of the mantissa. */ if (mpfr_sgn(f) > 0) { hash = mpn_mod_1(f->_mpfr_d, msize, _PyHASH_MODULUS); sign = 1; } else if (mpfr_sgn(f) < 0) { hash = mpn_mod_1(f->_mpfr_d, msize, _PyHASH_MODULUS); sign = -1; } else { return 0; } /* Calculate the final hash. */ exp = f->_mpfr_exp - (msize * mp_bits_per_limb); exp = exp >= 0 ? exp % _PyHASH_BITS : _PyHASH_BITS-1-((-1-exp) % _PyHASH_BITS); hash = ((hash << exp) & _PyHASH_MODULUS) | hash >> (_PyHASH_BITS - exp); hash *= sign; if (hash == (Py_uhash_t)-1) hash = (Py_uhash_t)-2; return (Py_hash_t)hash; #else double temp; temp = mpfr_get_d(f, context->ctx.mpfr_round); return _Py_HashDouble(temp); #endif } static Py_hash_t Pympfr_hash(PympfrObject *self) { if (self->hash_cache == -1) self->hash_cache = _mpfr_hash(self->f); return self->hash_cache; } /* This function is used in gmpy_mpany. */ static PyObject * Pympfr_pow(PyObject *base, PyObject *exp, PyObject *m) { PympfrObject *tempb, *tempe, *result; #ifdef WITHMPC PympcObject *mpc_result; #endif if (m != Py_None) { TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers"); return NULL; } tempb = Pympfr_From_Real(base, 0); tempe = Pympfr_From_Real(exp, 0); if (!tempe || !tempb) { Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); Py_RETURN_NOTIMPLEMENTED; } result = (PympfrObject*)Pympfr_new(0); if (!result) { Py_DECREF((PyObject*)tempe); Py_DECREF((PyObject*)tempb); return NULL; } if (mpfr_zero_p(tempb->f) && (mpfr_sgn(tempe->f) < 0)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("zero cannot be raised to a negative power"); goto done; } } mpfr_clear_flags(); result->rc = mpfr_pow(result->f, tempb->f, tempe->f, context->ctx.mpfr_round); #ifdef WITHMPC if (result && mpfr_nanflag_p() && context->ctx.allow_complex) { /* If we don't get a valid result, or the result is a nan, then just * return the original mpfr value. */ if (!(mpc_result = (PympcObject*)Pympc_pow(base, exp, m)) || MPC_IS_NAN_P(mpc_result)) { Py_XDECREF((PyObject*)mpc_result); context->ctx.invalid = 1; GMPY_INVALID("invalid operation in 'mpfr' pow()"); goto done; } /* return a valid complex result */ Py_DECREF(result); result = (PympfrObject*)mpc_result; goto done; } #endif SUBNORMALIZE(result) MERGE_FLAGS CHECK_FLAGS("pow()") done: Py_DECREF((PyObject*)tempe); Py_DECREF((PyObject*)tempb); if (PyErr_Occurred()) { Py_XDECREF((PyObject*)result); result = NULL; } return (PyObject*)result; } #define MPFR_CONST(NAME) \ static PyObject * \ Pympfr_##NAME(PyObject *self, PyObject *args, PyObject *keywds) \ { \ PympfrObject *result; \ mpfr_prec_t bits = 0; \ static char *kwlist[] = {"precision", NULL}; \ if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) return NULL; \ if ((result = (PympfrObject*)Pympfr_new(bits))) { \ mpfr_clear_flags(); \ result->rc = mpfr_##NAME(result->f, context->ctx.mpfr_round); \ MERGE_FLAGS \ CHECK_FLAGS(#NAME "()") \ } \ done: \ return (PyObject*)result; \ } PyDoc_STRVAR(doc_mpfr_const_pi, "const_pi([precision=0]) -> mpfr\n\n" "Return the constant pi using the specified precision. If no\n" "precision is specified, the default precision is used."); MPFR_CONST(const_pi) PyDoc_STRVAR(doc_mpfr_const_euler, "const_euler([precision=0]) -> mpfr\n\n" "Return the euler constant using the specified precision. If no\n" "precision is specified, the default precision is used."); MPFR_CONST(const_euler) PyDoc_STRVAR(doc_mpfr_const_log2, "const_log2([precision=0]) -> mpfr\n\n" "Return the log2 constant using the specified precision. If no\n" "precision is specified, the default precision is used."); MPFR_CONST(const_log2) PyDoc_STRVAR(doc_mpfr_const_catalan, "const_catalan([precision=0]) -> mpfr\n\n" "Return the catalan constant using the specified precision. If no\n" "precision is specified, the default precision is used."); MPFR_CONST(const_catalan) static PyObject * Pympfr_sqrt(PyObject *self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("sqrt() requires 'mpfr' argument"); #ifdef WITHMPC if (mpfr_sgn(Pympfr_AS_MPFR(self)) < 0 && context->ctx.allow_complex) { Py_DECREF(self); return Pympc_sqrt(self, other); } #endif if (!(result = (PympfrObject*)Pympfr_new(0))) { Py_DECREF(self); return NULL; } mpfr_clear_flags(); result->rc = mpfr_sqrt(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MPFR_CLEANUP_SELF("sqrt()"); } PyDoc_STRVAR(doc_g_mpfr_rec_sqrt, "rec_sqrt(x) -> mpfr\n\n" "Return the reciprocal of the square root of x."); static PyObject * Pympfr_rec_sqrt(PyObject *self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("rec_sqrt() requires 'mpfr' argument"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_rec_sqrt(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MPFR_CLEANUP_SELF("rec_sqrt()"); } PyDoc_STRVAR(doc_mpfr_root, "root(x, n) -> mpfr\n\n" "Return n-th root of x. The result always an 'mpfr'."); static PyObject * Pympfr_root(PyObject *self, PyObject *args) { long n; PympfrObject *result; PARSE_ONE_MPFR_REQ_CLONG(&n, "root() requires 'mpfr','int' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; if (n <= 0) { VALUE_ERROR("n must be > 0"); goto done; } mpfr_clear_flags(); result->rc = mpfr_root(result->f, Pympfr_AS_MPFR(self), n, context->ctx.mpfr_round); MPFR_CLEANUP_SELF("root()"); } PyDoc_STRVAR(doc_g_mpfr_round2, "round2(x[, n]) -> mpfr\n\n" "Return x rounded to n bits. Uses default precision if n is not\n" "specified. See round_away() to access the mpfr_round() function."); static PyObject * Pympfr_round2(PyObject *self, PyObject *args) { mpfr_prec_t prec = context->ctx.mpfr_prec; PympfrObject *result = 0; PARSE_ONE_MPFR_OPT_CLONG(&prec, "round2() requires 'mpfr',['int'] arguments"); if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) { VALUE_ERROR("invalid precision"); goto done; } if (!(result = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(self))))) { goto done; } mpfr_clear_flags(); /* Duplicate the code from Pympfr_pos. */ mpfr_set(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); result->round_mode = ((PympfrObject*)self)->round_mode; result->rc = ((PympfrObject*)self)->rc; result->rc = mpfr_check_range(result->f, result->rc, result->round_mode); result->rc = mpfr_prec_round(result->f, prec, context->ctx.mpfr_round); MPFR_CLEANUP_SELF("round2()"); } PyDoc_STRVAR(doc_g_mpfr_round10, "__round__(x[, n = 0]) -> mpfr\n\n" "Return x rounded to n decimal digits before (n < 0) or after (n > 0)\n" "the decimal point. Rounds to an integer if n is not specified."); static PyObject * Pympfr_round10(PyObject *self, PyObject *args) { Py_ssize_t digits = 0; mpz_t temp; PympfrObject *resultf = 0; PympzObject *resultz; /* If the size of args is 0, we just return an mpz. */ if (PyTuple_GET_SIZE(args) == 0) { if ((resultz = (PympzObject*)Pympz_new())) { if (mpfr_nan_p(Pympfr_AS_MPFR(self))) { Py_DECREF((PyObject*)resultz); VALUE_ERROR("'mpz' does not support NaN"); return NULL; } if (mpfr_inf_p(Pympfr_AS_MPFR(self))) { Py_DECREF((PyObject*)resultz); OVERFLOW_ERROR("'mpz' does not support Infinity"); return NULL; } /* return code is ignored */ mpfr_get_z(resultz->z, Pympfr_AS_MPFR(self), MPFR_RNDN); } return (PyObject*)resultz; } /* Now we need to return an mpfr, so handle the simple cases. */ if (!mpfr_regular_p(Pympfr_AS_MPFR(self))) { Py_INCREF(self); return self; } if (PyTuple_GET_SIZE(args) > 1) { TYPE_ERROR("Too many arguments for __round__()."); return NULL; } if (PyTuple_GET_SIZE(args) == 1) { digits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0)); if (digits == -1 && PyErr_Occurred()) { TYPE_ERROR("__round__() requires 'int' argument"); return NULL; } } /* TODO: better error analysis, or else convert the mpfr to an exact * fraction, round the fraction, and then convert back to an mpfr. */ resultf = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(self))+100); if (!resultf) return NULL; mpz_inoc(temp); mpz_ui_pow_ui(temp, 10, digits > 0 ? digits : -digits); if (digits >= 0) { mpfr_mul_z(resultf->f, Pympfr_AS_MPFR(self), temp, MPFR_RNDN); } else { mpfr_div_z(resultf->f, Pympfr_AS_MPFR(self), temp, MPFR_RNDN); } mpfr_rint(resultf->f, resultf->f, MPFR_RNDN); if (digits >= 0) { mpfr_div_z(resultf->f, resultf->f, temp, MPFR_RNDN); } else { mpfr_mul_z(resultf->f, resultf->f, temp, MPFR_RNDN); } mpfr_prec_round(resultf->f, mpfr_get_prec(Pympfr_AS_MPFR(self)), MPFR_RNDN); mpz_cloc(temp); return((PyObject*)resultf); } PyDoc_STRVAR(doc_g_mpfr_reldiff, "reldiff(x, y) -> mpfr\n\n" "Return the relative difference between x and y. Result is equal to\n" "abs(x-y)/x."); static PyObject * Pympfr_reldiff(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "reldiff() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) { Py_DECREF(self); Py_DECREF(other); return NULL; } /* mpfr_reldiff doesn't guarantee correct rounding and doesn't appear * to set any exceptions. */ mpfr_reldiff(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); result->rc = 0; Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; } static PyObject * Pympfr_sign(PyObject *self, PyObject *other) { long sign; PARSE_ONE_MPFR_OTHER("sign() requires 'mpfr' argument"); mpfr_clear_flags(); sign = mpfr_sgn(Pympfr_AS_MPFR(self)); MERGE_FLAGS; CHECK_ERANGE("range error in 'mpfr' sign(), NaN argument"); done: Py_DECREF((PyObject*)self); if (PyErr_Occurred()) return NULL; else return PyIntOrLong_FromLong(sign); } #define MPFR_MONOP(NAME) \ static PyObject * \ Py##NAME(PympfrObject *x) \ { \ PympfrObject *r; \ if (!(r = (PympfrObject*)Pympfr_new(0))) \ return NULL; \ if (Pympfr_CheckAndExp(x)) { \ r->rc = NAME(r->f, x->f, context->ctx.mpfr_round); \ } \ else { \ mpfr_set(r->f, x->f, context->ctx.mpfr_round); \ r->round_mode = x->round_mode; \ r->rc = x->rc; \ mpfr_clear_flags(); \ mpfr_check_range(r->f, r->rc, r->round_mode); \ r->rc = NAME(r->f, r->f, context->ctx.mpfr_round); \ MERGE_FLAGS; \ CHECK_FLAGS(#NAME "()"); \ } \ done: \ return (PyObject *) r; \ } MPFR_MONOP(mpfr_abs) MPFR_MONOP(mpfr_neg) #define MPFR_UNIOP_NOROUND(NAME) \ static PyObject * \ Pympfr_##NAME(PyObject* self, PyObject *other) \ { \ PympfrObject *result; \ PARSE_ONE_MPFR_OTHER(#NAME "() requires 'mpfr' argument"); \ if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; \ mpfr_clear_flags(); \ result->rc = mpfr_##NAME(result->f, Pympfr_AS_MPFR(self)); \ MPFR_CLEANUP_SELF(#NAME "()"); \ } PyDoc_STRVAR(doc_mpfr_ceil, "x.__ceil__() -> mpfr\n\n" "Return an 'mpfr' that is the smallest integer >= x."); PyDoc_STRVAR(doc_g_mpfr_ceil, "ceil(x) ->mpfr\n\n" "Return an 'mpfr' that is the smallest integer >= x."); MPFR_UNIOP_NOROUND(ceil) PyDoc_STRVAR(doc_mpfr_floor, "x.__floor__() -> mpfr\n\n" "Return an 'mpfr' that is the smallest integer <= x."); PyDoc_STRVAR(doc_g_mpfr_floor, "floor(x) -> mpfr\n\n" "Return an 'mpfr' that is the smallest integer <= x."); MPFR_UNIOP_NOROUND(floor); PyDoc_STRVAR(doc_mpfr_trunc, "x.__trunc__() -> mpfr\n\n" "Return an 'mpfr' that is truncated towards 0. Same as\n" "x.floor() if x>=0 or x.ceil() if x<0."); PyDoc_STRVAR(doc_g_mpfr_trunc, "trunc(x) -> mpfr\n\n" "Return an 'mpfr' that is x truncated towards 0. Same as\n" "x.floor() if x>=0 or x.ceil() if x<0."); MPFR_UNIOP_NOROUND(trunc) PyDoc_STRVAR(doc_g_mpfr_round_away, "round_away(x) -> mpfr\n\n" "Return an 'mpfr' that is x rounded to the nearest integer,\n" "with ties rounded away from 0."); static PyObject * Pympfr_round_away(PyObject* self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("round_away() requires 'mpfr' argument"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_round(result->f, Pympfr_AS_MPFR(self)); MPFR_CLEANUP_SELF("round_away()"); } #define MPFR_UNIOP(NAME) \ static PyObject * \ Pympfr_##NAME(PyObject* self, PyObject *other) \ { \ PympfrObject *result; \ PARSE_ONE_MPFR_OTHER(#NAME "() requires 'mpfr' argument"); \ if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; \ mpfr_clear_flags(); \ result->rc = mpfr_##NAME(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); \ MPFR_CLEANUP_SELF(#NAME "()"); \ } PyDoc_STRVAR(doc_g_mpfr_rint, "rint(x) -> mpfr\n\n" "Return x rounded to the nearest integer using the current rounding\n" "mode."); MPFR_UNIOP(rint) PyDoc_STRVAR(doc_g_mpfr_rint_ceil, "rint_ceil(x) -> mpfr\n\n" "Return x rounded to the nearest integer by first rounding to the\n" "next higher or equal integer and then, if needed, using the current\n" "rounding mode."); MPFR_UNIOP(rint_ceil) PyDoc_STRVAR(doc_g_mpfr_rint_floor, "rint_floor(x) -> mpfr\n\n" "Return x rounded to the nearest integer by first rounding to the\n" "next lower or equal integer and then, if needed, using the current\n" "rounding mode."); MPFR_UNIOP(rint_floor) PyDoc_STRVAR(doc_g_mpfr_rint_round, "rint_round(x) -> mpfr\n\n" "Return x rounded to the nearest integer by first rounding to the\n" "nearest integer (ties away from 0) and then, if needed, using\n" "the current rounding mode."); MPFR_UNIOP(rint_round) PyDoc_STRVAR(doc_g_mpfr_rint_trunc, "rint_trunc(x) -> mpfr\n\n" "Return x rounded to the nearest integer by first rounding towards\n" "zero and then, if needed, using the current rounding mode."); MPFR_UNIOP(rint_trunc) PyDoc_STRVAR(doc_g_mpfr_frac, "frac(x) -> mpfr\n\n" "Return fractional part of x."); MPFR_UNIOP(frac) PyDoc_STRVAR(doc_g_mpfr_modf, "modf(x) -> (mpfr, mpfr)\n\n" "Return a tuple containing the integer and fractional portions\n" "of x."); static PyObject * Pympfr_modf(PyObject *self, PyObject *other) { PympfrObject *s, *c; PyObject *result; int code; PARSE_ONE_MPFR_OTHER("modf() requires 'mpfr' argument"); s = (PympfrObject*)Pympfr_new(0); c = (PympfrObject*)Pympfr_new(0); result = PyTuple_New(2); if (!s || !c || !result) goto done; mpfr_clear_flags(); code = mpfr_modf(s->f, c->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); s->rc = code & 0x03; c->rc = code >> 2; if (s->rc == 2) s->rc = -1; if (c->rc == 2) c->rc = -1; SUBNORMALIZE(s); SUBNORMALIZE(c); MERGE_FLAGS; CHECK_FLAGS("modf()"); done: Py_DECREF(self); if (PyErr_Occurred()) { Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)c); Py_XDECREF(result); result = NULL; } else { PyTuple_SET_ITEM(result, 0, (PyObject*)s); PyTuple_SET_ITEM(result, 1, (PyObject*)c); } return result; } /* Needed for square() in mpz_mpany.c */ MPFR_UNIOP(sqr) PyDoc_STRVAR(doc_g_mpfr_cbrt, "cbrt(x) -> mpfr\n\n" "Return the cube root of x."); MPFR_UNIOP(cbrt) /* Called via gmpy_mpany so doc-string is there. */ MPFR_UNIOP(log) PyDoc_STRVAR(doc_g_mpfr_log2, "log2(x) -> mpfr\n\n" "Return base-2 logarithm of x."); MPFR_UNIOP(log2) /* Called via gmpy_mpany so doc-string is there. */ MPFR_UNIOP(log10) /* Called via gmpy_mpany so doc-string is there. */ MPFR_UNIOP(exp) PyDoc_STRVAR(doc_g_mpfr_exp2, "exp2(x) -> mpfr\n\n" "Return 2**x."); MPFR_UNIOP(exp2) PyDoc_STRVAR(doc_g_mpfr_exp10, "exp10(x) -> mpfr\n\n" "Return 10**x."); MPFR_UNIOP(exp10) MPFR_UNIOP(sin) MPFR_UNIOP(cos) MPFR_UNIOP(tan) PyDoc_STRVAR(doc_g_mpfr_sec, "sec(x) -> mpfr\n\n" "Return secant of x; x in radians."); MPFR_UNIOP(sec) PyDoc_STRVAR(doc_g_mpfr_csc, "csc(x) -> mpfr\n\n" "Return cosecant of x; x in radians."); MPFR_UNIOP(csc) PyDoc_STRVAR(doc_g_mpfr_cot, "cot(x) -> mpfr\n\n" "Return cotangent of x; x in radians."); MPFR_UNIOP(cot) static PyObject * Pympfr_acos(PyObject* self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("acos() requires 'mpfr' argument"); #ifdef WITHMPC if (!mpfr_nan_p(Pympfr_AS_MPFR(self)) && (mpfr_cmp_si(Pympfr_AS_MPFR(self), 1) > 0 || mpfr_cmp_si(Pympfr_AS_MPFR(self), -1) < 0) && context->ctx.allow_complex) { Py_DECREF(self); return Pympc_acos(self, other); } #endif if (!(result = (PympfrObject*)Pympfr_new(0))) { Py_DECREF(self); return NULL; } mpfr_clear_flags(); result->rc = mpfr_acos(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MPFR_CLEANUP_SELF("acos()"); } static PyObject * Pympfr_asin(PyObject* self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("asin() requires 'mpfr' argument"); #ifdef WITHMPC if (!mpfr_nan_p(Pympfr_AS_MPFR(self)) && (mpfr_cmp_si(Pympfr_AS_MPFR(self), 1) > 0 || mpfr_cmp_si(Pympfr_AS_MPFR(self), -1) < 0) && context->ctx.allow_complex) { Py_DECREF(self); return Pympc_asin(self, other); } #endif if (!(result = (PympfrObject*)Pympfr_new(0))) { Py_DECREF(self); return NULL; } mpfr_clear_flags(); result->rc = mpfr_asin(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MPFR_CLEANUP_SELF("asin()"); } MPFR_UNIOP(atan) MPFR_UNIOP(cosh) MPFR_UNIOP(sinh) MPFR_UNIOP(tanh) PyDoc_STRVAR(doc_g_mpfr_sech, "sech(x) -> mpfr\n\n" "Returns hyperbolic secant of x."); MPFR_UNIOP(sech) PyDoc_STRVAR(doc_g_mpfr_csch, "csch(x) -> mpfr\n\n" "Return hyperbolic cosecant of x."); MPFR_UNIOP(csch) PyDoc_STRVAR(doc_g_mpfr_coth, "coth(x) -> mpfr\n\n" "Return hyperbolic cotangent of x."); MPFR_UNIOP(coth) MPFR_UNIOP(acosh) MPFR_UNIOP(asinh) static PyObject * Pympfr_atanh(PyObject* self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("atanh() requires 'mpfr' argument"); #ifdef WITHMPC if (!mpfr_nan_p(Pympfr_AS_MPFR(self)) && (mpfr_cmp_si(Pympfr_AS_MPFR(self), 1) > 0 || mpfr_cmp_si(Pympfr_AS_MPFR(self), -1) < 0) && context->ctx.allow_complex) { Py_DECREF(self); return Pympc_atanh(self, other); } #endif if (!(result = (PympfrObject*)Pympfr_new(0))) { Py_DECREF(self); return NULL; } mpfr_clear_flags(); result->rc = mpfr_atanh(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MPFR_CLEANUP_SELF("atanh()"); } PyDoc_STRVAR(doc_g_mpfr_log1p, "log1p(x) -> mpfr\n\n" "Return logarithm of (1+x)."); MPFR_UNIOP(log1p) PyDoc_STRVAR(doc_g_mpfr_expm1, "expm1(x) -> mpfr\n\n" "Return exponential(x) - 1."); MPFR_UNIOP(expm1) PyDoc_STRVAR(doc_g_mpfr_eint, "eint(x) -> mpfr\n\n" "Return exponential integral of x."); MPFR_UNIOP(eint) PyDoc_STRVAR(doc_g_mpfr_li2, "li2(x) -> mpfr\n\n" "Return real part of dilogarithm of x."); MPFR_UNIOP(li2) PyDoc_STRVAR(doc_g_mpfr_gamma, "gamma(x) -> mpfr\n\n" "Return gamma of x."); MPFR_UNIOP(gamma) PyDoc_STRVAR(doc_g_mpfr_lngamma, "lngamma(x) -> mpfr\n\n" "Return logarithm of gamma(x)."); MPFR_UNIOP(lngamma) PyDoc_STRVAR(doc_g_mpfr_lgamma, "lgamma(x) -> (mpfr, int)\n\n" "Return a tuple containing the logarithm of the absolute value of\n" "gamma(x) and the sign of gamma(x)"); static PyObject * Pympfr_lgamma(PyObject* self, PyObject *other) { PyObject *result; PympfrObject *value; int signp = 0; PARSE_ONE_MPFR_OTHER("lgamma() requires 'mpfr' argument"); value = (PympfrObject*)Pympfr_new(0); result = PyTuple_New(2); if (!value || !result) goto done; mpfr_clear_flags(); value->rc = mpfr_lgamma(value->f, &signp, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); SUBNORMALIZE(value); MERGE_FLAGS; CHECK_FLAGS("lgamma()"); done: Py_DECREF(self); if (PyErr_Occurred()) { Py_XDECREF(result); Py_XDECREF((PyObject*)value); result = NULL; } else { PyTuple_SET_ITEM(result, 0, (PyObject*)value); PyTuple_SET_ITEM(result, 1, PyIntOrLong_FromLong((long)signp)); } return result; } PyDoc_STRVAR(doc_g_mpfr_digamma, "digamma(x) -> mpfr\n\n" "Return digamma of x."); MPFR_UNIOP(digamma) PyDoc_STRVAR(doc_g_mpfr_zeta, "zeta(x) -> mpfr\n\n" "Return Riemann zeta of x."); MPFR_UNIOP(zeta) PyDoc_STRVAR(doc_g_mpfr_erf, "erf(x) -> mpfr\n\n" "Return error function of x."); MPFR_UNIOP(erf) PyDoc_STRVAR(doc_g_mpfr_erfc, "erfc(x) -> mpfr\n\n" "Return complementary error function of x."); MPFR_UNIOP(erfc) PyDoc_STRVAR(doc_g_mpfr_j0, "j0(x) -> mpfr\n\n" "Return first kind Bessel function of order 0 of x."); MPFR_UNIOP(j0) PyDoc_STRVAR(doc_g_mpfr_j1, "j1(x) -> mpfr\n\n" "Return first kind Bessel function of order 1 of x."); MPFR_UNIOP(j1) PyDoc_STRVAR(doc_g_mpfr_jn, "jn(x,n) -> mpfr\n\n" "Return the first kind Bessel function of order n of x."); static PyObject * Pympfr_jn(PyObject *self, PyObject *args) { PympfrObject *result; long n = 0; PARSE_ONE_MPFR_REQ_CLONG(&n, "jn() requires 'mpfr','int' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_jn(result->f, n, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MPFR_CLEANUP_SELF("jn()"); } PyDoc_STRVAR(doc_g_mpfr_y0, "y0(x) -> mpfr\n\n" "Return second kind Bessel function of order 0 of x."); MPFR_UNIOP(y0) PyDoc_STRVAR(doc_g_mpfr_y1, "y1(x) -> mpfr\n\n" "Return second kind Bessel function of order 1 of x."); MPFR_UNIOP(y1) PyDoc_STRVAR(doc_g_mpfr_yn, "yn(x,n) -> mpfr\n\n" "Return the second kind Bessel function of order n of x."); static PyObject * Pympfr_yn(PyObject *self, PyObject *args) { PympfrObject *result; long n = 0; PARSE_ONE_MPFR_REQ_CLONG(&n, "yn() requires 'mpfr','int' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_yn(result->f, n, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MPFR_CLEANUP_SELF("yn()"); } PyDoc_STRVAR(doc_g_mpfr_ai, "ai(x) -> mpfr\n\n" "Return Airy function of x."); MPFR_UNIOP(ai) static PyObject * Pympfr_add_fast(PyObject *x, PyObject *y) { PympfrObject *result; if (Pympfr_CheckAndExp(x) && Pympfr_CheckAndExp(y)) { if (!(result = (PympfrObject*)Pympfr_new(0))) { return NULL; } mpfr_clear_flags(); result->rc = mpfr_add(result->f, Pympfr_AS_MPFR(x), Pympfr_AS_MPFR(y), context->ctx.mpfr_round); MPFR_CLEANUP_RESULT("addition"); return (PyObject*)result; } else { return Pybasic_add(x, y); } } static PyObject * Pympfr_add(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "add() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_add(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("add()"); } static PyObject * Pympfr_sub_fast(PyObject *x, PyObject *y) { PympfrObject *result; if (Pympfr_CheckAndExp(x) && Pympfr_CheckAndExp(y)) { if (!(result = (PympfrObject*)Pympfr_new(0))) { return NULL; } mpfr_clear_flags(); result->rc = mpfr_sub(result->f, Pympfr_AS_MPFR(x), Pympfr_AS_MPFR(y), context->ctx.mpfr_round); MPFR_CLEANUP_RESULT("subtraction"); return (PyObject*)result; } else { return Pybasic_sub(x, y); } } static PyObject * Pympfr_sub(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "sub() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_sub(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("sub()"); } static PyObject * Pympfr_mul_fast(PyObject *x, PyObject *y) { PympfrObject *result; if (Pympfr_CheckAndExp(x) && Pympfr_CheckAndExp(y)) { if (!(result = (PympfrObject*)Pympfr_new(0))) { return NULL; } mpfr_clear_flags(); result->rc = mpfr_mul(result->f, Pympfr_AS_MPFR(x), Pympfr_AS_MPFR(y), context->ctx.mpfr_round); MPFR_CLEANUP_RESULT("multiplication"); return (PyObject*)result; } else { return Pybasic_mul(x, y); } } static PyObject * Pympfr_mul(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "mul() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_mul(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("mul()"); } static PyObject * Pympfr_truediv_fast(PyObject *x, PyObject *y) { PympfrObject *result; if (Pympfr_CheckAndExp(x) && Pympfr_CheckAndExp(y)) { if (!(result = (PympfrObject*)Pympfr_new(0))) { return NULL; } mpfr_clear_flags(); result->rc = mpfr_div(result->f, Pympfr_AS_MPFR(x), Pympfr_AS_MPFR(y), context->ctx.mpfr_round); MPFR_CLEANUP_RESULT("division"); return (PyObject*)result; } else { return Pybasic_truediv(x, y); } } #ifdef PY2 static PyObject * Pympfr_div2_fast(PyObject *x, PyObject *y) { PympfrObject *result; if (Pympfr_CheckAndExp(x) && Pympfr_CheckAndExp(y)) { if (!(result = (PympfrObject*)Pympfr_new(0))) { return NULL; } mpfr_clear_flags(); result->rc = mpfr_div(result->f, Pympfr_AS_MPFR(x), Pympfr_AS_MPFR(y), context->ctx.mpfr_round); MPFR_CLEANUP_RESULT("division"); return (PyObject*)result; } else { return Pybasic_div2(x, y); } } #endif static PyObject * Pympfr_div(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "div() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_div(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("div()"); } PyDoc_STRVAR(doc_g_mpfr_fmod, "fmod(x, y) -> mpfr\n\n" "Return x - n*y where n is the integer quotient of x/y, rounded to 0."); static PyObject * Pympfr_fmod(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "fmod() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_fmod(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("fmod()"); } PyDoc_STRVAR(doc_g_mpfr_remainder, "remainder(x, y) -> mpfr\n\n" "Return x - n*y where n is the integer quotient of x/y, rounded to\n" "the nearest integer and ties rounded to even."); static PyObject * Pympfr_remainder(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "remainder() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_remainder(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("remainder()"); } PyDoc_STRVAR(doc_g_mpfr_remquo, "remquo(x, y) -> (mpfr, int)\n\n" "Return a tuple containing the remainder(x,y) and the low bits of the\n" "quotient."); static PyObject * Pympfr_remquo(PyObject* self, PyObject *args) { PyObject *result, *other; PympfrObject *value; long quobits = 0; PARSE_TWO_MPFR_ARGS(other, "remquo() requires 'mpfr', 'mpfr' argument"); value = (PympfrObject*)Pympfr_new(0); result = PyTuple_New(2); if (!value || !result) goto done; mpfr_clear_flags(); value->rc = mpfr_remquo(value->f, &quobits, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); SUBNORMALIZE(value); MERGE_FLAGS; CHECK_FLAGS("remquo()"); done: Py_DECREF(self); Py_DECREF(other); if (PyErr_Occurred()) { Py_XDECREF(result); Py_XDECREF((PyObject*)value); result = NULL; } else { PyTuple_SET_ITEM(result, 0, (PyObject*)value); PyTuple_SET_ITEM(result, 1, PyIntOrLong_FromLong(quobits)); } return result; } PyDoc_STRVAR(doc_g_mpfr_frexp, "frexp(x) -> (int, mpfr)\n\n" "Return a tuple containing the exponent and mantissa of x."); static PyObject * Pympfr_frexp(PyObject *self, PyObject *other) { PyObject *result; PympfrObject *value; mpfr_exp_t exp = 0; PARSE_ONE_MPFR_OTHER("frexp() requires 'mpfr' argument"); value = (PympfrObject*)Pympfr_new(0); result = PyTuple_New(2); if (!value || !result) goto done; mpfr_clear_flags(); value->rc = mpfr_frexp(&exp, value->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); MERGE_FLAGS; CHECK_FLAGS("frexp()"); done: Py_DECREF(self); Py_DECREF(other); if (PyErr_Occurred()) { Py_XDECREF(result); Py_XDECREF((PyObject*)value); result = NULL; } else { PyTuple_SET_ITEM(result, 0, PyIntOrLong_FromSsize_t((Py_ssize_t)exp)); PyTuple_SET_ITEM(result, 1, (PyObject*)value); } return result; } PyDoc_STRVAR(doc_g_mpfr_atan2, "atan2(y, x) -> mpfr\n\n" "Return arc-tangent of (y/x)."); static PyObject * Pympfr_atan2(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "atan2() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_atan2(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("atan2()"); } PyDoc_STRVAR(doc_g_mpfr_agm, "agm(x, y) -> mpfr\n\n" "Return arithmetic-geometric mean of x and y."); static PyObject * Pympfr_agm(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "agm() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_agm(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("agm()"); } PyDoc_STRVAR(doc_g_mpfr_hypot, "hypot(y, x) -> mpfr\n\n" "Return square root of (x**2 + y**2)."); static PyObject * Pympfr_hypot(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "hypot() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_hypot(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("hypot()"); } PyDoc_STRVAR(doc_g_mpfr_max2, "max2(x, y) -> mpfr\n\n" "Return the maximum number of x and y. This function is deprecated.\n" "Please use maxnum() instead."); PyDoc_STRVAR(doc_g_mpfr_maxnum, "maxnum(x, y) -> mpfr\n\n" "Return the maximum number of x and y. If x and y are not 'mpfr', they are\n" "converted to 'mpfr'. The result is rounded to match the current\n" "context. If only one of x or y is a number, then that number is returned."); static PyObject * Pympfr_max2(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "max2() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_max(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("max2()"); } PyDoc_STRVAR(doc_g_mpfr_min2, "min2(x, y) -> mpfr\n\n" "Return the minimum of x and y. This function is deprecated.\n" "Please use minnum() instead."); PyDoc_STRVAR(doc_g_mpfr_minnum, "minnum(x, y) -> mpfr\n\n" "Return the minimum of x and y. If x and y are not 'mpfr', they are\n" "converted to 'mpfr'. The result is rounded to match the current\n" "context. If only one of x or y is a number, then that number is returned."); static PyObject * Pympfr_min2(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "min2() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(0))) goto done; mpfr_clear_flags(); result->rc = mpfr_min(result->f, Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other), context->ctx.mpfr_round); MPFR_CLEANUP_SELF_OTHER("min2()"); } PyDoc_STRVAR(doc_g_mpfr_nexttoward, "next_toward(y, x) -> mpfr\n\n" "Return the next 'mpfr' from x in the direction of y."); static PyObject * Pympfr_nexttoward(PyObject *self, PyObject *args) { PympfrObject *result; PyObject *other; PARSE_TWO_MPFR_ARGS(other, "next_toward() requires 'mpfr','mpfr' arguments"); if (!(result = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(self))))) goto done; mpfr_clear_flags(); mpfr_set(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); mpfr_nexttoward(result->f, Pympfr_AS_MPFR(other)); result->rc = 0; MPFR_CLEANUP_SELF_OTHER("next_toward()"); } PyDoc_STRVAR(doc_g_mpfr_nextabove, "next_above(x) -> mpfr\n\n" "Return the next 'mpfr' from x toward +Infinity."); static PyObject * Pympfr_nextabove(PyObject *self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("next_above() requires 'mpfr' argument"); if (!(result = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(self))))) goto done; mpfr_clear_flags(); mpfr_set(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); mpfr_nextabove(result->f); result->rc = 0; MPFR_CLEANUP_SELF("next_above()"); } PyDoc_STRVAR(doc_g_mpfr_nextbelow, "next_below(x) -> mpfr\n\n" "Return the next 'mpfr' from x toward -Infinity."); static PyObject * Pympfr_nextbelow(PyObject *self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPFR_OTHER("next_below() requires 'mpfr' argument"); if (!(result = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(self))))) goto done; mpfr_clear_flags(); mpfr_set(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); mpfr_nextbelow(result->f); result->rc = 0; MPFR_CLEANUP_SELF("next_below()"); } static PyObject * Pympfr_sin_cos(PyObject *self, PyObject *other) { PympfrObject *s, *c; PyObject *result; int code; PARSE_ONE_MPFR_OTHER("sin_cos() requires 'mpfr' argument"); s = (PympfrObject*)Pympfr_new(0); c = (PympfrObject*)Pympfr_new(0); result = PyTuple_New(2); if (!s || !c || !result) goto done; mpfr_clear_flags(); code = mpfr_sin_cos(s->f, c->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); s->rc = code & 0x03; c->rc = code >> 2; if (s->rc == 2) s->rc = -1; if (c->rc == 2) c->rc = -1; SUBNORMALIZE(s); SUBNORMALIZE(c); MERGE_FLAGS; CHECK_FLAGS("sin_cos()"); done: Py_DECREF(self); if (PyErr_Occurred()) { Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)c); Py_XDECREF(result); result = NULL; } else { PyTuple_SET_ITEM(result, 0, (PyObject*)s); PyTuple_SET_ITEM(result, 1, (PyObject*)c); } return result; } PyDoc_STRVAR(doc_g_mpfr_sinh_cosh, "sinh_cosh(x) -> (mpfr, mpfr)\n\n" "Return a tuple containing the hyperbolic sine and cosine of x."); static PyObject * Pympfr_sinh_cosh(PyObject *self, PyObject *other) { PympfrObject *s, *c; PyObject *result; int code; PARSE_ONE_MPFR_OTHER("sinh_cosh() requires 'mpfr' argument"); s = (PympfrObject*)Pympfr_new(0); c = (PympfrObject*)Pympfr_new(0); result = PyTuple_New(2); if (!s || !c || !result) goto done; mpfr_clear_flags(); code = mpfr_sinh_cosh(s->f, c->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); s->rc = code & 0x03; c->rc = code >> 2; if (s->rc == 2) s->rc = -1; if (c->rc == 2) c->rc = -1; SUBNORMALIZE(s); SUBNORMALIZE(c); MERGE_FLAGS; CHECK_FLAGS("sin_cos()"); done: Py_DECREF(self); if (PyErr_Occurred()) { Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)c); Py_XDECREF(result); result = NULL; } else { PyTuple_SET_ITEM(result, 0, (PyObject*)s); PyTuple_SET_ITEM(result, 1, (PyObject*)c); } return result; } static PyObject * Pympfr_fma(PyObject *self, PyObject *args) { PympfrObject *result, *x, *y, *z; if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("fma() requires 'mpfr','mpfr','mpfr' arguments."); return NULL; } result = (PympfrObject*)Pympfr_new(0); x = Pympfr_From_Real(PyTuple_GET_ITEM(args, 0), 0); y = Pympfr_From_Real(PyTuple_GET_ITEM(args, 1), 0); z = Pympfr_From_Real(PyTuple_GET_ITEM(args, 2), 0); if (!result || !x || !y || !z) { TYPE_ERROR("fma() requires 'mpfr','mpfr','mpfr' arguments."); goto done; } mpfr_clear_flags(); result->rc = mpfr_fma(result->f, x->f, y->f, z->f, context->ctx.mpfr_round); SUBNORMALIZE(result); MERGE_FLAGS; CHECK_FLAGS("fma()"); done: Py_XDECREF((PyObject*)x); Py_XDECREF((PyObject*)y); Py_XDECREF((PyObject*)z); if (PyErr_Occurred()) { Py_XDECREF(result); result = NULL; } return (PyObject*)result; } static PyObject * Pympfr_fms(PyObject *self, PyObject *args) { PympfrObject *result, *x, *y, *z; if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("fms() requires 'mpfr','mpfr','mpfr' arguments."); return NULL; } result = (PympfrObject*)Pympfr_new(0); x = Pympfr_From_Real(PyTuple_GET_ITEM(args, 0), 0); y = Pympfr_From_Real(PyTuple_GET_ITEM(args, 1), 0); z = Pympfr_From_Real(PyTuple_GET_ITEM(args, 2), 0); if (!result || !x || !y || !z) { TYPE_ERROR("fms() requires 'mpfr','mpfr','mpfr' arguments."); goto done; } mpfr_clear_flags(); result->rc = mpfr_fms(result->f, x->f, y->f, z->f, context->ctx.mpfr_round); SUBNORMALIZE(result); MERGE_FLAGS; CHECK_FLAGS("fms()"); done: Py_XDECREF((PyObject*)x); Py_XDECREF((PyObject*)y); Py_XDECREF((PyObject*)z); if (PyErr_Occurred()) { Py_XDECREF(result); result = NULL; } return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_factorial, "factorial(n) -> mpfr\n\n" "Return the floating-point approximation to the factorial of n.\n\n" "See fac(n) to get the exact integer result."); static PyObject * Pympfr_factorial(PyObject *self, PyObject *other) { PympfrObject *result; long n; n = clong_From_Integer(other); if ((n == -1) && PyErr_Occurred()) { TYPE_ERROR("factorial() requires 'int' argument"); return NULL; } if (n < 0) { VALUE_ERROR("factorial() of negative number"); return NULL; } if (!(result = (PympfrObject*)Pympfr_new(0))) return NULL; mpfr_clear_flags(); mpfr_fac_ui(result->f, n, context->ctx.mpfr_round); MERGE_FLAGS; CHECK_FLAGS("factorial()"); done: return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_is_lessgreater, "is_lessgreater(x,y) -> boolean\n\n" "Return True if x > y or x < y. Return False if x == y or either x\n" "and/or y is NaN."); static PyObject * Pympfr_is_lessgreater(PyObject *self, PyObject *args) { PyObject *other; int temp; PARSE_TWO_MPFR_ARGS(other, "is_lessgreater() requires 'mpfr','mpfr' arguments"); temp = mpfr_lessgreater_p(Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other)); Py_DECREF(self); Py_DECREF(other); if (temp) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_g_mpfr_is_unordered, "is_unordered(x,y) -> boolean\n\n" "Return True if either x and/or y is NaN."); static PyObject * Pympfr_is_unordered(PyObject *self, PyObject *args) { PyObject *other; int temp; PARSE_TWO_MPFR_ARGS(other, "unordered() requires 'mpfr','mpfr' arguments"); temp = mpfr_unordered_p(Pympfr_AS_MPFR(self), Pympfr_AS_MPFR(other)); Py_DECREF(self); Py_DECREF(other); if (temp) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(doc_g_mpfr_check_range, "check_range(x) -> mpfr\n\n" "Return a new 'mpfr' with exponent that lies within the current range\n" "of emin and emax."); static PyObject * Pympfr_check_range(PyObject *self, PyObject *other) { PympfrObject *result = NULL; if (self && Pympfr_Check(self)) { if ((result = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(self))))) { mpfr_set(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); result->round_mode = ((PympfrObject*)self)->round_mode; result->rc = ((PympfrObject*)self)->rc; mpfr_clear_flags(); result->rc = mpfr_check_range(result->f, result->rc, result->round_mode); } } else if (Pympfr_Check(other)) { if ((result = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(other))))) { mpfr_set(result->f, Pympfr_AS_MPFR(other), context->ctx.mpfr_round); result->round_mode = ((PympfrObject*)other)->round_mode; result->rc = ((PympfrObject*)other)->rc; mpfr_clear_flags(); result->rc = mpfr_check_range(result->f, result->rc, result->round_mode); } } else { TYPE_ERROR("check_range() requires 'mpfr' argument"); } MERGE_FLAGS; CHECK_FLAGS("check_range()"); done: return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_fsum, "fsum(iterable) -> mpfr\n\n" "Return an accurate sum of the values in the iterable."); static PyObject * Pympfr_fsum(PyObject *self, PyObject *other) { PympfrObject *temp, *result; mpfr_ptr *tab; int errcode; Py_ssize_t i, seq_length = 0; if (!(result = (PympfrObject*)Pympfr_new(0))) return NULL; if (!(other = PySequence_List(other))) { Py_DECREF((PyObject*)result); TYPE_ERROR("argument must be an iterable"); return NULL; } /* other contains a new list containing all the values from the * iterable. Now make sure each item in the list is an mpfr. */ seq_length = PyList_GET_SIZE(other); for (i=0; i < seq_length; i++) { if (!(temp = Pympfr_From_Real(PyList_GET_ITEM(other, i), 0))) { Py_DECREF(other); Py_DECREF((PyObject*)result); TYPE_ERROR("all items in iterable must be real numbers"); return NULL; } errcode = PyList_SetItem(other, i,(PyObject*)temp); if (errcode < 0) { Py_DECREF(other); Py_DECREF((PyObject*)result); TYPE_ERROR("all items in iterable must be real numbers"); return NULL; } } /* create an array of pointers to the mpfr_t field of a Pympfr object */ if (!(tab = (mpfr_ptr *)GMPY_MALLOC((sizeof(mpfr_srcptr) * seq_length)))) { Py_DECREF(other); Py_DECREF((PyObject*)result); return PyErr_NoMemory(); } for (i=0; i < seq_length; i++) { temp = (PympfrObject*)PyList_GET_ITEM(other, i); tab[i] = temp->f; } result->rc = mpfr_sum(result->f, tab, (unsigned long)seq_length, context->ctx.mpfr_round); Py_DECREF(other); GMPY_FREE(tab); return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpfr_degrees, "degrees(x) -> mpfr\n\n" "Convert angle x from radians to degrees."); static PyObject * Pympfr_degrees(PyObject *self, PyObject *other) { PympfrObject *result, *temp; PARSE_ONE_MPFR_OTHER("degrees() requires 'mpfr' argument"); result = (PympfrObject*)Pympfr_new(0); temp = (PympfrObject*)Pympfr_new(context->ctx.mpfr_prec + 20); if (!result || !temp) { Py_XDECREF((PyObject*)temp); Py_XDECREF((PyObject*)result); Py_DECREF(other); return NULL; } mpfr_clear_flags(); mpfr_const_pi(temp->f, MPFR_RNDN); mpfr_ui_div(temp->f, 180, temp->f, MPFR_RNDN); mpfr_mul(result->f, temp->f, Pympfr_AS_MPFR(self), MPFR_RNDN); Py_DECREF((PyObject*)temp); MPFR_CLEANUP_SELF("degrees()"); } PyDoc_STRVAR(doc_g_mpfr_radians, "radians(x) -> mpfr\n\n" "Convert angle x from degrees to radians."); static PyObject * Pympfr_radians(PyObject *self, PyObject *other) { PympfrObject *result, *temp; PARSE_ONE_MPFR_OTHER("radians() requires 'mpfr' argument"); result = (PympfrObject*)Pympfr_new(0); temp = (PympfrObject*)Pympfr_new(context->ctx.mpfr_prec + 20); if (!result || !temp) { Py_XDECREF((PyObject*)temp); Py_XDECREF((PyObject*)result); Py_DECREF(other); return NULL; } mpfr_clear_flags(); mpfr_const_pi(temp->f, MPFR_RNDN); mpfr_div_ui(temp->f, temp->f, 180, MPFR_RNDN); mpfr_mul(result->f, Pympfr_AS_MPFR(self), temp->f, MPFR_RNDN); Py_DECREF((PyObject*)temp); MPFR_CLEANUP_SELF("radians()"); } PyDoc_STRVAR(doc_mpfr_format, "x.__format__(fmt) -> string\n\n" "Return a Python string by formatting 'x' using the format string\n" "'fmt'. A valid format string consists of:\n" " optional alignment code:\n" " '<' -> left shifted in field\n" " '>' -> right shifted in field\n" " '^' -> centered in field\n" " optional leading sign code\n" " '+' -> always display leading sign\n" " '-' -> only display minus for negative values\n" " ' ' -> minus for negative values, space for positive values\n" " optional width.precision\n" " optional rounding mode:\n" " 'U' -> round toward plus Infinity\n" " 'D' -> round toward minus Infinity\n" " 'Y' -> round away from zero\n" " 'Z' -> round toward zero\n" " 'N' -> round to nearest\n" " optional conversion code:\n" " 'a','A' -> hex format\n" " 'b' -> binary format\n" " 'e','E' -> scientific format\n" " 'f','F' -> fixed point format\n" " 'g','G' -> fixed or float format\n\n" "The default format is '.6f'."); static PyObject * Pympfr_format(PyObject *self, PyObject *args) { PyObject *result = 0, *mpfrstr = 0; char *buffer = 0, *newbuf = 0, *fmtcode = 0, *p1, *p2, *p3; char mpfrfmt[100], fmt[30]; int buflen; int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0; int seenround = 0, seenconv = 0; if (!Pympfr_Check(self)) { TYPE_ERROR("requires mpfr type"); return NULL; } if (!PyArg_ParseTuple(args, "s", &fmtcode)) return NULL; p2 = mpfrfmt; p3 = fmt; *(p2++) = '%'; for (p1 = fmtcode; *p1 != '\00'; p1++) { if (*p1 == '<' || *p1 == '>' || *p1 == '^') { if (seenalign || seensign || seendecimal || seendigits || seenround) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(p3++) = *p1; seenalign = 1; continue; } } if (*p1 == '+' || *p1 == ' ') { if (seensign || seendecimal || seendigits || seenround) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(p2++) = *p1; seensign = 1; continue; } } if (*p1 == '-') { if (seensign || seendecimal || seendigits || seenround) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { seensign = 1; continue; } } if (*p1 == '.') { if (seendecimal || seendigits || seenround) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(p2++) = *p1; seendecimal = 1; continue; } } if (isdigit(*p1)) { if (seendigits || seenround) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else if (seendecimal) { *(p2++) = *p1; continue; } else { if (p3 == fmt) { *(p3++) = '>'; seenalign = 1; } *(p3++) = *p1; continue; } } if (!seendigits) { seendigits = 1; *(p2++) = 'R'; } if (*p1 == 'U' || *p1 == 'D' || *p1 == 'Y' || *p1 == 'Z' || *p1 == 'N' ) { if (seenround) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(p2++) = *p1; seenround = 1; continue; } } if (*p1 == 'a' || *p1 == 'A' || *p1 == 'b' || *p1 == 'e' || *p1 == 'E' || *p1 == 'f' || *p1 == 'F' || *p1 == 'g' || *p1 == 'G' ) { *(p2++) = *p1; seenconv = 1; break; } VALUE_ERROR("Invalid conversion specification"); return NULL; } if (!seendigits) *(p2++) = 'R'; if (!seenconv) *(p2++) = 'f'; *(p2) = '\00'; *(p3) = '\00'; buflen = mpfr_asprintf(&buffer, mpfrfmt, Pympfr_AS_MPFR(self)); /* If there isn't a decimal point in the output and the output * only consists of digits, then append .0 */ if (strlen(buffer) == strspn(buffer, "+- 0123456789")) { newbuf = GMPY_MALLOC(buflen + 3); if (!newbuf) { mpfr_free_str(buffer); return PyErr_NoMemory(); } *newbuf = '\0'; strcat(newbuf, buffer); strcat(newbuf, ".0"); mpfr_free_str(buffer); mpfrstr = Py_BuildValue("s", newbuf); GMPY_FREE(newbuf); } else { mpfrstr = Py_BuildValue("s", buffer); mpfr_free_str(buffer); } if (!mpfrstr) { return NULL; } result = PyObject_CallMethod(mpfrstr, "__format__", "(s)", fmt); Py_DECREF(mpfrstr); return result; } PyDoc_STRVAR(doc_mpfr_sizeof, "x.__sizeof__()\n\n" "Returns the amount of memory consumed by x."); static PyObject * Pympfr_sizeof(PyObject *self, PyObject *other) { return PyIntOrLong_FromSize_t(sizeof(PympfrObject) + \ (((Pympfr_AS_MPFR(self))->_mpfr_prec + mp_bits_per_limb - 1) / \ mp_bits_per_limb) * sizeof(mp_limb_t)); } #ifdef PY3 static PyNumberMethods mpfr_number_methods = { (binaryfunc) Pympfr_add_fast, /* nb_add */ (binaryfunc) Pympfr_sub_fast, /* nb_subtract */ (binaryfunc) Pympfr_mul_fast, /* nb_multiply */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympfr_neg, /* nb_negative */ (unaryfunc) Pympfr_pos, /* nb_positive */ (unaryfunc) Pympfr_abs, /* nb_absolute */ (inquiry) Pympfr_nonzero, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ (unaryfunc) Pympfr_To_PyLong, /* nb_int */ 0, /* nb_reserved */ (unaryfunc) Pympfr_To_PyFloat, /* nb_float */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pympfr_truediv_fast, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ 0, /* nb_index */ }; #else static PyNumberMethods mpfr_number_methods = { (binaryfunc) Pympfr_add_fast, /* nb_add */ (binaryfunc) Pympfr_sub_fast, /* nb_subtract */ (binaryfunc) Pympfr_mul_fast, /* nb_multiply */ (binaryfunc) Pympfr_div2_fast, /* nb_divide */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympfr_neg, /* nb_negative */ (unaryfunc) Pympfr_pos, /* nb_positive */ (unaryfunc) Pympfr_abs, /* nb_absolute */ (inquiry) Pympfr_nonzero, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ 0, /* nb_coerce */ (unaryfunc) Pympfr_To_PyInt, /* nb_int */ (unaryfunc) Pympfr_To_PyLong, /* nb_long */ (unaryfunc) Pympfr_To_PyFloat, /* nb_float */ 0, /* nb_oct */ 0, /* nb_hex */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_divide */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pympfr_truediv_fast, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ }; #endif static PyGetSetDef Pympfr_getseters[] = { {"precision", (getter)Pympfr_getprec_attrib, NULL, "precision in bits", NULL}, {"rc", (getter)Pympfr_getrc_attrib, NULL, "return code", NULL}, {"imag", (getter)Pympfr_getimag_attrib, NULL, "imaginary component", NULL}, {"real", (getter)Pympfr_getreal_attrib, NULL, "real component", NULL}, {NULL} }; static PyMethodDef Pympfr_methods [] = { { "__ceil__", Pympfr_ceil, METH_NOARGS, doc_mpfr_ceil }, { "__floor__", Pympfr_floor, METH_NOARGS, doc_mpfr_floor }, { "__format__", Pympfr_format, METH_VARARGS, doc_mpfr_format }, { "__round__", Pympfr_round10, METH_VARARGS, doc_g_mpfr_round10 }, { "__sizeof__", Pympfr_sizeof, METH_NOARGS, doc_mpfr_sizeof }, { "__trunc__", Pympfr_trunc, METH_NOARGS, doc_mpfr_trunc }, { "as_integer_ratio", Pympfr_integer_ratio, METH_NOARGS, doc_mpfr_integer_ratio }, { "as_mantissa_exp", Pympfr_mantissa_exp, METH_NOARGS, doc_mpfr_mantissa_exp }, { "as_simple_fraction", (PyCFunction)Pympfr_simple_fraction, METH_VARARGS | METH_KEYWORDS, doc_mpfr_simple_fraction }, { "conjugate", Pympfr_conjugate, METH_NOARGS, doc_mpfr_conjugate }, { "digits", Pympfr_digits, METH_VARARGS, doc_mpfr_digits }, { "is_integer", Pympfr_is_integer, METH_NOARGS, doc_mpfr_is_integer }, { NULL, NULL, 1 } }; static PyTypeObject Pympfr_Type = { /* PyObject_HEAD_INIT(&PyType_Type) */ #ifdef PY3 PyVarObject_HEAD_INIT(NULL, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "mpfr", /* tp_name */ sizeof(PympfrObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor) Pympfr_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) Pympfr_To_Repr, /* tp_repr */ &mpfr_number_methods, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc) Pympfr_hash, /* tp_hash */ 0, /* tp_call */ (reprfunc) Pympfr_To_Str, /* tp_str */ (getattrofunc) 0, /* tp_getattro */ (setattrofunc) 0, /* tp_setattro */ 0, /* tp_as_buffer */ #ifdef PY3 Py_TPFLAGS_DEFAULT, /* tp_flags */ #else Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */ #endif "Multiple precision real", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)&mpany_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ Pympfr_methods, /* tp_methods */ 0, /* tp_members */ Pympfr_getseters, /* tp_getset */ }; gmpy2-2.0.7/src/gmpy_mpc.h0000666000000000000000000003132112542614506014040 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpc.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MPC_H #define GMPY_MPC_H #ifdef __cplusplus extern "C" { #endif /* gmpy_mpc C API extension header file. * * Provide interface to the MPC (Multiple Precision Complex) library. * * Version 2.00, April 2011 (created) casevh * * This file is expected to be included from gmpy.h */ #if defined(MS_WIN32) && defined(_MSC_VER) # pragma comment(lib,"mpc.lib") #endif typedef struct { PyObject_HEAD mpc_t c; Py_hash_t hash_cache; int rc; int round_mode; } PympcObject; static PyTypeObject Pympc_Type; #define Pympc_AS_MPC(obj) (((PympcObject *)(obj))->c) #define Pympc_Check(v) (((PyObject*)v)->ob_type == &Pympc_Type) /* * Define macros for comparing with zero, checking if either component is * 'nan' or 'inf', etc. */ #define MPC_IS_ZERO_P(x) \ (mpfr_zero_p(mpc_realref(Pympc_AS_MPC(x))) && \ mpfr_zero_p(mpc_imagref(Pympc_AS_MPC(x)))) #define MPC_IS_NAN_P(x) \ (mpfr_nan_p(mpc_realref(Pympc_AS_MPC(x))) || \ mpfr_nan_p(mpc_imagref(Pympc_AS_MPC(x)))) #define MPC_IS_INF_P(x) \ (mpfr_inf_p(mpc_realref(Pympc_AS_MPC(x))) || \ mpfr_inf_p(mpc_imagref(Pympc_AS_MPC(x)))) #define MPC_IS_FINITE_P(x) \ (mpfr_number_p(mpc_realref(Pympc_AS_MPC(x))) && \ mpfr_number_p(mpc_imagref(Pympc_AS_MPC(x)))) /* Verify that an object is an mpc and that both components have valid exp */ #define Pympc_CheckAndExp(v) \ (Pympc_Check(v) && \ (mpfr_zero_p(mpc_realref(Pympc_AS_MPC(v))) || \ (mpfr_regular_p(mpc_realref(Pympc_AS_MPC(v))) && \ ((mpc_realref(Pympc_AS_MPC(v))->_mpfr_exp >= context->ctx.emin)) && \ ((mpc_realref(Pympc_AS_MPC(v))->_mpfr_exp <= context->ctx.emax)) \ ) \ ) && \ (mpfr_zero_p(mpc_imagref(Pympc_AS_MPC(v))) || \ (mpfr_regular_p(mpc_imagref(Pympc_AS_MPC(v))) && \ ((mpc_imagref(Pympc_AS_MPC(v))->_mpfr_exp >= context->ctx.emin)) && \ ((mpc_imagref(Pympc_AS_MPC(v))->_mpfr_exp <= context->ctx.emax)) \ ) \ ) \ ) #define MPC_CHECK_UNDERFLOW(mpct, msg) \ if (MPC_IS_ZERO_P(mpct) && mpct->rc) { \ context->ctx.underflow = 1; \ if (context->ctx.trap_underflow) { \ GMPY_UNDERFLOW(msg); \ goto done; \ } \ } #define MPC_CHECK_OVERFLOW(mpct, msg) \ if (MPC_IS_INF_P(mpct)) { \ context->ctx.overflow = 1; \ if (context->ctx.trap_overflow) { \ GMPY_OVERFLOW(msg); \ goto done; \ } \ } #define MPC_CHECK_INVALID(mpct, msg) \ if (MPC_IS_NAN_P(mpct)) { \ context->ctx.invalid = 1; \ if (context->ctx.trap_invalid) { \ GMPY_INVALID(msg); \ goto done; \ } \ } #define MPC_CHECK_INEXACT(mpct, msg) \ if (mpct->rc) { \ context->ctx.inexact = 1; \ if (context->ctx.trap_inexact) { \ GMPY_INEXACT(msg); \ goto done; \ } \ } #define MPC_CHECK_FLAGS(mpct, NAME) \ MPC_CHECK_INVALID(mpct, "'mpc' invalid operation in "NAME); \ MPC_CHECK_UNDERFLOW(mpct, "'mpc' underflow in "NAME); \ MPC_CHECK_OVERFLOW(mpct, "'mpc' overflow in "NAME); \ MPC_CHECK_INEXACT(mpct, "'mpc' inexact result in "NAME); #define MPC_SUBNORMALIZE(mpct) \ if (context->ctx.subnormalize) { \ int rcr, rci; \ rcr = MPC_INEX_RE(mpct->rc); \ rci = MPC_INEX_IM(mpct->rc); \ rcr = mpfr_subnormalize(mpc_realref(mpct->c), rcr, GET_REAL_ROUND(context)); \ rci = mpfr_subnormalize(mpc_imagref(mpct->c), rci, GET_IMAG_ROUND(context)); \ mpct->rc = MPC_INEX(rcr, rci); \ } \ #define MPC_CLEANUP(mpct, NAME) \ MPC_SUBNORMALIZE(mpct); \ MPC_CHECK_FLAGS(mpct, NAME); \ done:\ if (PyErr_Occurred()) { \ Py_DECREF((PyObject*)mpct); \ mpct = NULL; \ } \ return (PyObject*)mpct; /* * Parses one, and only one, argument into "self" and converts it to an * mpc. Is faster, but not as generic, as using PyArg_ParseTuple. It * supports either gmpy.fname(z) or z.fname(). "self" must be decref'ed. * "msg" should be an error message that includes the function name and * describes the required arguments. */ #define PARSE_ONE_MPC_ARGS(msg) \ if(self && Pympc_Check(self)) { \ if (PyTuple_GET_SIZE(args) != 0) { \ TYPE_ERROR(msg); \ return NULL; \ } \ if (Pympc_CheckAndExp(self)) { \ Py_INCREF(self); \ } \ else { \ if (!(self = (PyObject*)Pympc_From_Complex(self, 0, 0))) { \ TYPE_ERROR(msg); \ return NULL; \ } \ } \ } \ else { \ if (PyTuple_GET_SIZE(args) != 1) { \ TYPE_ERROR(msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0);\ if (Pympc_CheckAndExp(self)) { \ Py_INCREF(self); \ } \ else { \ if (!(self = (PyObject*)Pympc_From_Complex(self, 0, 0))) { \ TYPE_ERROR(msg); \ return NULL; \ } \ } \ } /* * Parses one, and only one, argument into "self" and converts it to an * mpc. Is faster, but not as generic, as using PyArg_ParseTuple. It * supports either gmpy.fname(z) or z.fname(). "self" must be decref'ed. * "msg" should be an error message that includes the function name and * describes the required arguments. It assumes the functions is declared * as either METH_O or METH_NOARGS. It is faster than PARSE_ONE_MPFR and * passing a tuple as args. */ #define PARSE_ONE_MPC_OTHER(msg) \ if(self && Pympc_Check(self)) { \ if (Pympc_CheckAndExp(self)) { \ Py_INCREF(self); \ } \ else { \ if (!(self = (PyObject*)Pympc_From_Complex(self, 0, 0))) { \ TYPE_ERROR(msg); \ return NULL; \ } \ } \ } \ else { \ if (Pympc_CheckAndExp(other)) { \ self = other; \ Py_INCREF(self); \ } \ else { \ if (!(self = (PyObject*)Pympc_From_Complex(other, 0, 0))) { \ TYPE_ERROR(msg); \ return NULL; \ } \ } \ } /* * Parses two, and only two, arguments into "self" and "var" and converts * them both to mpC. Is faster, but not as generic, as using PyArg_ParseTuple. * It supports either gmpy.fname(f,f) or f.fname(f). "self" & "var" must be * decref'ed after use. "msg" should be an error message that includes the * function name and describes the required arguments. Replaces * SELF_MPF_ONE_ARG_CONVERTED(var). */ #define PARSE_TWO_MPC_ARGS(var, msg) \ if(self && Pympc_Check(self)) { \ if (PyTuple_GET_SIZE(args) != 1) { \ TYPE_ERROR(msg); \ return NULL; \ } \ self = (PyObject*)Pympc_From_Complex(self, 0, 0); \ var = (PyObject*)Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0); \ } \ else { \ if (PyTuple_GET_SIZE(args) != 2) { \ TYPE_ERROR(msg); \ return NULL; \ } \ self = (PyObject*)Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0); \ var = (PyObject*)Pympc_From_Complex(PyTuple_GET_ITEM(args, 1), 0, 0); \ } \ if (!self || !var) { \ TYPE_ERROR(msg); \ Py_XDECREF((PyObject*)var); \ Py_XDECREF((PyObject*)self); \ return NULL; \ } static PyObject * Pympc_digits(PyObject *self, PyObject *args); static PyObject * Pygmpy_mpc(PyObject *self, PyObject *args, PyObject *kwargs); static PyObject * Pympc_format(PyObject *self, PyObject *args); static PyObject * Pympc_abs(PyObject *self); static PyObject * Pympc_neg(PympcObject *self); static PyObject * Pympc_pos(PympcObject *self); static PyObject * Pympc_sqr(PyObject* self, PyObject *other); static PyObject * Pympc_pow(PyObject *base, PyObject *exp, PyObject *m); static PyObject * Pympc_conjugate(PyObject *self, PyObject *args); static PyObject * Pympc_getprec_attrib(PympcObject *self, void *closure); static PyObject * Pympc_getrc_attrib(PympcObject *self, void *closure); static PyObject * Pympc_getimag_attrib(PympcObject *self, void *closure); static PyObject * Pympc_getreal_attrib(PympcObject *self, void *closure); static int Pympc_nonzero(PympcObject *self); static PyObject * Pympc_is_NAN(PyObject *self, PyObject *other); static PyObject * Pympc_is_ZERO(PyObject *self, PyObject *other); static PyObject * Pympc_is_INF(PyObject *self, PyObject *other); static PyObject * Pympc_is_FINITE(PyObject *self, PyObject *other); static PyObject * Pympc_phase(PyObject *self, PyObject *other); static PyObject * Pympc_norm(PyObject *self, PyObject *other); static PyObject * Pympc_polar(PyObject *self, PyObject *other); static PyObject * Pympc_rect(PyObject *self, PyObject *args); static PyObject * Pympc_proj(PyObject *self, PyObject *other); static PyObject * Pympc_log(PyObject *self, PyObject *other); static PyObject * Pympc_log10(PyObject *self, PyObject *other); static PyObject * Pympc_exp(PyObject *self, PyObject *other); static PyObject * Pympc_sin(PyObject *self, PyObject *other); static PyObject * Pympc_cos(PyObject *self, PyObject *other); static PyObject * Pympc_tan(PyObject *self, PyObject *other); static PyObject * Pympc_sinh(PyObject *self, PyObject *other); static PyObject * Pympc_cosh(PyObject *self, PyObject *other); static PyObject * Pympc_tanh(PyObject *self, PyObject *other); static PyObject * Pympc_asin(PyObject *self, PyObject *other); static PyObject * Pympc_acos(PyObject *self, PyObject *other); static PyObject * Pympc_atan(PyObject *self, PyObject *other); static PyObject * Pympc_asinh(PyObject *self, PyObject *other); static PyObject * Pympc_acosh(PyObject *self, PyObject *other); static PyObject * Pympc_atanh(PyObject *self, PyObject *other); static PyObject * Pympc_sqrt(PyObject *self, PyObject *other); static PyObject * Pympc_sin_cos(PyObject *self, PyObject *other); static PyObject * Pympc_fma(PyObject *self, PyObject *args); static PyObject * Pympc_fms(PyObject *self, PyObject *args); static PyObject * Pympc_div_2exp(PyObject *self, PyObject *args); static PyObject * Pympc_mul_2exp(PyObject *self, PyObject *args); static Py_hash_t Pympc_hash(PympcObject *self); static PyObject * Pympc_add_fast(PyObject *x, PyObject *y); static PyObject * Pympc_add(PyObject *self, PyObject *args); static PyObject * Pympc_sub_fast(PyObject *x, PyObject *y); static PyObject * Pympc_sub(PyObject *self, PyObject *args); static PyObject * Pympc_mul_fast(PyObject *x, PyObject *y); static PyObject * Pympc_mul(PyObject *self, PyObject *args); static PyObject * Pympc_truediv_fast(PyObject *x, PyObject *y); #ifdef PY2 static PyObject * Pympc_div2_fast(PyObject *x, PyObject *y); #endif static PyObject * Pympc_div(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpc.c0000666000000000000000000013634612542614506014050 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpc.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ PyDoc_STRVAR(doc_mpc_digits, "c.digits(base=10, prec=0) -> ((mant, exp, prec), (mant, exp, prec))\n\n" "Returns up to 'prec' digits in the given base. If 'prec' is 0, as many\n" "digits that are available given c's precision are returned. 'base' must\n" "be between 2 and 62. The result consists of 2 three-element tuples that\n" "contain the mantissa, exponent, and number of bits of precision of the\n" "real and imaginary components."); /* TODO: support keyword arguments. */ static PyObject * Pympc_digits(PyObject *self, PyObject *args) { int base = 10; int prec = 0; PyObject *result; if (self && Pympc_Check(self)) { if (!PyArg_ParseTuple(args, "|ii", &base, &prec)) return NULL; Py_INCREF(self); } else { if(!PyArg_ParseTuple(args, "O&|ii", Pympc_convert_arg, &self, &base, &prec)) return NULL; } result = Pympc_To_PyStr((PympcObject*)self, base, prec); Py_DECREF(self); return result; } PyDoc_STRVAR(doc_g_mpc, "mpc() -> mpc(0.0+0.0j)\n\n" " If no argument is given, return mpc(0.0+0.0j).\n\n" "mpc(c[, precision=0]) -> mpc\n\n" " Return a new 'mpc' object from an existing complex number\n" " (either a Python complex object or another 'mpc' object). If\n" " the precision is not specified, then the precision is taken\n" " from the current context. The rounding mode is always taken\n" " from the current context.\n\n" "mpc(r[, i=0[, precision=0]]) -> mpc\n\n" " Return a new 'mpc' object by converting two non-complex numbers\n" " into the real and imaginary components of an 'mpc' object. If\n" " the precision is not specified, then the precision is taken from\n" " the current context. The rounding mode is always taken from the\n" " current context.\n\n" "mpc(s[, [precision=0[, base=10]]) -> mpc\n\n" " Return a new 'mpc' object by converting a string s into a complex\n" " number. If base is omitted, then a base-10 representation is\n" " assumed otherwise a base between 2 and 36 can be specified. If\n" " the precision is not specified, then the precision is taken from\n" " the current context. The rounding mode is always taken from the\n" " current context.\n\n" "Note: The precision can be specified either a single number that\n" " is used for both the real and imaginary components, or as a\n" " tuple that can specify different precisions for the real\n" " and imaginary components."); static PyObject * Pygmpy_mpc(PyObject *self, PyObject *args, PyObject *kwargs) { PympcObject *result = NULL; PympfrObject *tempreal = NULL, *tempimag = NULL; PyObject *arg0 = NULL, *arg1 = NULL, *prec = NULL; int base = 10; /* Assumes mpfr_prec_t is the same as a long. */ mpfr_prec_t rbits = 0, ibits = 0; Py_ssize_t argc; static char *kwlist_c[] = {"c", "precision", NULL}; static char *kwlist_r[] = {"r", "i", "precision", NULL}; static char *kwlist_s[] = {"s", "precision", "base", NULL}; argc = PyTuple_Size(args); if (argc == 0) { if ((result = (PympcObject*)Pympc_new(0,0))) { mpc_set_ui(result->c, 0, GET_MPC_ROUND(context)); } return (PyObject*)result; } arg0 = PyTuple_GetItem(args, 0); if (PyStrOrUnicode_Check(arg0)) { /* First argument is a string */ if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi", kwlist_s, &arg0, &prec, &base))) return NULL; if (prec) { if (PyIntOrLong_Check(prec)) { rbits = (mpfr_prec_t)PyIntOrLong_AsLong(prec); ibits = rbits; } else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) { rbits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 0)); ibits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 1)); } if (PyErr_Occurred()) { VALUE_ERROR("invalid value for precision in gmpy2.mpc()."); return NULL; } } if (base < 2 || base > 36) { VALUE_ERROR("base for mpc() must be in the interval 2 ... 36."); return NULL; } result = Pympc_From_PyStr(arg0, base, rbits, ibits); } else if (PyComplex_Check(arg0) || Pympc_Check(arg0)) { /* First argument is a complex number */ if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist_c, &arg0, &prec))) return NULL; if (prec) { if (PyIntOrLong_Check(prec)) { rbits = (mpfr_prec_t)PyIntOrLong_AsLong(prec); ibits = rbits; } else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) { rbits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 0)); ibits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 1)); } if (PyErr_Occurred()) { VALUE_ERROR("invalid value for precision in mpc()."); return NULL; } } if (PyComplex_Check(arg0)) { result = Pympc_From_PyComplex(arg0, rbits, ibits); } else { result = Pympc_From_Pympc(arg0, rbits, ibits); } } else if (isReal(arg0)) { /* First argument is a real number */ if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO", kwlist_r, &arg0, &arg1, &prec))) return NULL; if (prec) { if (PyIntOrLong_Check(prec)) { rbits = (mpfr_prec_t)PyIntOrLong_AsLong(prec); ibits = rbits; } else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) { rbits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 0)); ibits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 1)); } if (PyErr_Occurred()) { VALUE_ERROR("invalid value for precision in mpc()."); return NULL; } } if (arg1 && !isReal(arg1)) { TYPE_ERROR("invalid type for imaginary component in mpc()"); return NULL; } if (arg0) { tempreal = Pympfr_From_Real(arg0, rbits); } else { if ((tempreal = (PympfrObject*)Pympfr_new(rbits))) { mpfr_set_ui(Pympfr_AS_MPFR(tempreal), 0, context->ctx.mpfr_round); } } if (arg1) { tempimag = Pympfr_From_Real(arg1, ibits); } else { if ((tempimag = (PympfrObject*)Pympfr_new(ibits))) { mpfr_set_ui(Pympfr_AS_MPFR(tempimag), 0, context->ctx.mpfr_round); } } result = (PympcObject*)Pympc_new(rbits, ibits); if (!tempreal || !tempimag || !result) { Py_XDECREF(tempreal); Py_XDECREF(tempimag); Py_XDECREF(result); TYPE_ERROR("mpc() requires string or numeric argument."); return NULL; } mpc_set_fr_fr(Pympc_AS_MPC(result), Pympfr_AS_MPFR(tempreal), Pympfr_AS_MPFR(tempimag), GET_MPC_ROUND(context)); Py_DECREF(tempreal); Py_DECREF(tempimag); } else { TYPE_ERROR("mpc() requires numeric or string argument"); } return (PyObject*)result; } PyDoc_STRVAR(doc_mpc_format, "x.__format__(fmt) -> string\n\n" "Return a Python string by formatting 'x' using the format string\n" "'fmt'. A valid format string consists of:\n" " optional alignment code:\n" " '<' -> left shifted in field\n" " '>' -> right shifted in field\n" " '^' -> centered in field\n" " optional leading sign code\n" " '+' -> always display leading sign\n" " '-' -> only display minus for negative values\n" " ' ' -> minus for negative values, space for positive values\n" " optional width.real_precision.imag_precision\n" " optional rounding mode:\n" " 'U' -> round toward plus infinity\n" " 'D' -> round toward minus infinity\n" " 'Z' -> round toward zero\n" " 'N' -> round to nearest\n" " optional output style:\n" " 'P' -> Python style, 1+2j, (default)\n" " 'M' -> MPC style, (1 2)\n" " optional conversion code:\n" " 'a','A' -> hex format\n" " 'b' -> binary format\n" " 'e','E' -> scientific format\n" " 'f','F' -> fixed point format\n" " 'g','G' -> fixed or scientific format\n\n" "The default format is 'f'."); static PyObject * Pympc_format(PyObject *self, PyObject *args) { PyObject *result = 0, *tempstr = 0; char *realbuf = 0, *imagbuf = 0, *tempbuf = 0, *fmtcode = 0; char *p, *rfmtptr, *ifmtptr, *fmtptr; char rfmt[100], ifmt[100], fmt[30]; int rbuflen, ibuflen; int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0; int seenround = 0, seenconv = 0, seenstyle = 0, mpcstyle = 0; if (!Pympc_Check(self)) { TYPE_ERROR("requires 'mpc' object"); return NULL; } if (!PyArg_ParseTuple(args, "s", &fmtcode)) return NULL; rfmtptr = rfmt; ifmtptr = ifmt; fmtptr = fmt; *(rfmtptr++) = '%'; *(ifmtptr++) = '%'; for (p = fmtcode; *p != '\00'; p++) { if (*p == '<' || *p == '>' || *p == '^') { if (seenalign || seensign || seendecimal || seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(fmtptr++) = *p; seenalign = 1; continue; } } if (*p == '+' || *p == ' ' || *p == '-') { if (seensign || seendecimal || seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(rfmtptr++) = *p; *(ifmtptr++) = *p; seensign = 1; continue; } } if (!seensign) { *(rfmtptr++) = '-'; *(ifmtptr++) = '-'; seensign = 1; } if (*p == '.') { if (seendecimal == 2 || seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { if (!seendecimal) { *(rfmtptr++) = *p; *(ifmtptr++) = *p; } seendecimal++; if (seendecimal == 2) { while (isdigit(*(ifmtptr-1))) ifmtptr--; } continue; } } if (isdigit(*p)) { if (seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else if (seendecimal == 1) { *(rfmtptr++) = *p; *(ifmtptr++) = *p; continue; } else if (seendecimal == 2) { *(ifmtptr++) = *p; continue; } else { if (fmtptr == fmt) { *(fmtptr++) = '>'; seenalign = 1; } *(fmtptr++) = *p; continue; } } if (!seendigits) { seendigits = 1; *(rfmtptr++) = 'R'; *(ifmtptr++) = 'R'; } if (*p == 'U' || *p == 'D' || *p == 'Y' || *p == 'Z' || *p == 'N' ) { if (seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(rfmtptr++) = *p; *(ifmtptr++) = *p; seenround = 1; continue; } } if (*p == 'P' || *p == 'M') { if (seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { if (*p == 'M') mpcstyle = 1; seenstyle = 1; continue; } } if (*p == 'a' || *p == 'A' || *p == 'b' || *p == 'e' || *p == 'E' || *p == 'f' || *p == 'F' || *p == 'g' || *p == 'G' ) { *(rfmtptr++) = *p; *(ifmtptr++) = *p; seenconv = 1; break; } VALUE_ERROR("Invalid conversion specification"); return NULL; } if (!seensign) { *(rfmtptr++) = '-'; *(ifmtptr++) = '-'; } if (!seendigits) { *(rfmtptr++) = 'R'; *(ifmtptr++) = 'R'; } if (!seenconv) { *(rfmtptr++) = 'f'; *(ifmtptr++) = 'f'; } *(rfmtptr) = '\00'; *(ifmtptr) = '\00'; *(fmtptr) = '\00'; /* Format the real part.... */ rbuflen = mpfr_asprintf(&realbuf, rfmt, mpc_realref(Pympc_AS_MPC(self))); if (rbuflen < 0) { mpfr_free_str(realbuf); SYSTEM_ERROR("Internal error in mpfr_asprintf"); return NULL; } /* Format the imaginary part. If Python style is wanted, convert the '-' * or ' ' sign indicator to '+'. */ if (!mpcstyle) { if (ifmt[1] == ' ' || ifmt[1] == '-' || ifmt[1] == '+') { ifmt[1] = '+'; } else { mpfr_free_str(realbuf); VALUE_ERROR("Invalid conversion specification for imag"); return NULL; } } ibuflen = mpfr_asprintf(&imagbuf, ifmt, mpc_imagref(Pympc_AS_MPC(self))); if (ibuflen < 0) { mpfr_free_str(realbuf); mpfr_free_str(imagbuf); SYSTEM_ERROR("Internal error in mpfr_asprintf"); return NULL; } /* Combine the real and imaginary components into a single buffer. * Include space for '(', ' ', and 'j)' and possibly appending '.0' twice. */ tempbuf = GMPY_MALLOC(rbuflen + ibuflen + 10); if (!tempbuf) { mpfr_free_str(realbuf); mpfr_free_str(imagbuf); return PyErr_NoMemory(); } tempbuf[0] = '\00'; if (mpcstyle) strcat(tempbuf, "("); strcat(tempbuf, realbuf); /* If there isn't a decimal point in the output and the output * is short and only consists of digits, then append .0 */ if (strlen(realbuf) < 50 && strlen(realbuf) == strspn(realbuf, "+- 0123456789")) { strcat(tempbuf, ".0"); } if (mpcstyle) strcat(tempbuf, " "); else { /* Need to insert + if imag is nan or +inf. */ if (mpfr_nan_p(mpc_imagref(Pympc_AS_MPC(self))) || (mpfr_inf_p(mpc_imagref(Pympc_AS_MPC(self))) && mpfr_sgn(mpc_imagref(Pympc_AS_MPC(self))) > 0)) { strcat(tempbuf, "+"); } } strcat(tempbuf, imagbuf); if (strlen(imagbuf) < 50 && strlen(imagbuf) == strspn(imagbuf, "+- 0123456789")) { strcat(tempbuf, ".0"); } if (mpcstyle) strcat(tempbuf, ")"); else strcat(tempbuf, "j"); mpfr_free_str(realbuf); mpfr_free_str(imagbuf); tempstr = Py_BuildValue("s", tempbuf); if (!tempstr) { GMPY_FREE(tempbuf); return NULL; } result = PyObject_CallMethod(tempstr, "__format__", "(s)", fmt); Py_DECREF(tempstr); return result; } static PyObject * Pympc_abs(PyObject *self) { PympfrObject *result = 0; PympcObject *tempx = 0; result = (PympfrObject*)Pympfr_new(0); tempx = Pympc_From_Complex(self, 0, 0); if (!tempx || !result) { SYSTEM_ERROR("Can't convert argument to 'mpc'."); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)result); return NULL; } result->rc = mpc_abs(result->f, tempx->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)tempx); MPFR_SUBNORMALIZE(result); MPFR_CHECK_INVALID(result, "invalid operation in 'mpc' __abs__"); MPFR_CHECK_UNDERFLOW(result, "underflow in 'mpc' __abs__"); MPFR_CHECK_OVERFLOW(result, "overflow in 'mpc' __abs__"); MPFR_CHECK_INEXACT(result, "inexact result in 'mpc' __abs__"); done: if (PyErr_Occurred()) { Py_DECREF((PyObject*)result); result = NULL; } return (PyObject*)result; } static PyObject * Pympc_neg(PympcObject *self) { PympcObject *result = 0; if (!(result = (PympcObject*)Pympc_new(0, 0))) return NULL; if (!(self = Pympc_From_Complex((PyObject*)self, 0, 0))) { SYSTEM_ERROR("__neg__() requires 'mpc' argument"); Py_DECREF(result); return NULL; } result->rc = mpc_neg(result->c, self->c, GET_MPC_ROUND(context)); MPC_CLEANUP(result, "__neg__"); } static PyObject * Pympc_pos(PympcObject *self) { PympcObject *result = 0; if (!(result = Pympc_From_Complex((PyObject*)self, 0, 0))) { SYSTEM_ERROR("__pos__ requires 'mpc' argument"); return NULL; } MPC_CLEANUP(result, "__pos__"); } /* Support Pympany_square */ static PyObject * Pympc_sqr(PyObject* self, PyObject *other) { PympcObject *result; PARSE_ONE_MPC_OTHER("square() requires 'mpc' argument"); if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); return NULL; } result->rc = mpc_sqr(result->c, Pympc_AS_MPC(self), GET_MPC_ROUND(context)); Py_DECREF(self); MPC_CLEANUP(result, "square()"); } static PyObject * Pympc_pow(PyObject *base, PyObject *exp, PyObject *m) { PympcObject *tempb, *tempe, *result; if (m != Py_None) { TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers"); return NULL; } tempb = Pympc_From_Complex(base, 0, 0); tempe = Pympc_From_Complex(exp, 0, 0); if (!tempe || !tempb) { Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); Py_RETURN_NOTIMPLEMENTED; } result = (PympcObject*)Pympc_new(0, 0); if (!result) { Py_DECREF((PyObject*)tempe); Py_DECREF((PyObject*)tempb); return NULL; } if (MPC_IS_ZERO_P(tempb) && MPC_IS_ZERO_P(tempe)) { mpc_set_ui(result->c, 1, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)tempe); Py_DECREF((PyObject*)tempb); return (PyObject*)result; } if (MPC_IS_ZERO_P(tempb) && (!mpfr_zero_p(mpc_imagref(tempe->c)) || mpfr_sgn(mpc_realref(tempe->c)) < 0)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("zero cannot be raised to a negative or complex power"); Py_DECREF((PyObject*)tempe); Py_DECREF((PyObject*)tempb); Py_DECREF((PyObject*)result); return NULL; } } result->rc = mpc_pow(result->c, tempb->c, tempe->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)tempe); Py_DECREF((PyObject*)tempb); MPC_CLEANUP(result, "pow()"); } /* Implement the conjugate() method. */ PyDoc_STRVAR(doc_mpc_conjugate, "x.conjugate() -> mpc\n\n" "Returns the conjugate of x."); static PyObject * Pympc_conjugate(PyObject *self, PyObject *args) { PympcObject *result; PARSE_ONE_MPC_ARGS("conjugate() requires 'mpc' argument"); if (!(result = (PympcObject*)Pympc_new(0,0))) { Py_DECREF(self); return NULL; } result->rc = mpc_conj(result->c, Pympc_AS_MPC(self), GET_MPC_ROUND(context)); Py_DECREF(self); MPC_CLEANUP(result, "conjugate()"); } /* Implement the .precision attribute of an mpfr. */ static PyObject * Pympc_getprec_attrib(PympcObject *self, void *closure) { mpfr_prec_t rprec = 0, iprec = 0; mpc_get_prec2(&rprec, &iprec, self->c); return Py_BuildValue("(nn)", rprec, iprec); } /* Implement the .rc attribute of an mpfr. */ static PyObject * Pympc_getrc_attrib(PympcObject *self, void *closure) { return Py_BuildValue("(ii)", MPC_INEX_RE(self->rc), MPC_INEX_IM(self->rc)); } /* Implement the .imag attribute of an mpfr. */ static PyObject * Pympc_getimag_attrib(PympcObject *self, void *closure) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(0))) mpc_imag(result->f, self->c, context->ctx.mpfr_round); return (PyObject*)result; } /* Implement the .real attribute of an mpfr. */ static PyObject * Pympc_getreal_attrib(PympcObject *self, void *closure) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(0))) mpc_real(result->f, self->c, context->ctx.mpfr_round); return (PyObject*)result; } /* Implement the nb_bool slot. */ static int Pympc_nonzero(PympcObject *self) { return !MPC_IS_ZERO_P(self->c); } /* To work with the MPC_IS_ macros, NAN, INF, FINITE, and ZERO are * all upper-case. */ #define MPC_TEST_OTHER(NAME, msg) \ static PyObject * \ Pympc_is_##NAME(PyObject *self, PyObject *other)\ {\ if(self && Pympc_Check(self)) {\ Py_INCREF(self);\ }\ else if(Pympc_Check(other)) {\ self = other;\ Py_INCREF((PyObject*)self);\ }\ else if (!(self = (PyObject*)Pympc_From_Complex(other, 0, 0))) {\ PyErr_SetString(PyExc_TypeError, msg);\ return NULL;\ }\ if (MPC_IS_##NAME##_P(self)) {\ Py_DECREF(self);\ Py_RETURN_TRUE;\ }\ else {\ Py_DECREF(self);\ Py_RETURN_FALSE;\ }\ } MPC_TEST_OTHER(NAN, "is_nan() requires 'mpc' argument"); MPC_TEST_OTHER(INF, "is_infinite() requires 'mpc' argument"); MPC_TEST_OTHER(FINITE, "is_finite() requires 'mpc' argument"); MPC_TEST_OTHER(ZERO, "is_zero() requires 'mpc' argument"); PyDoc_STRVAR(doc_mpc_phase, "phase(x) -> mpfr\n\n" "Return the phase angle, also known as argument, of a complex x."); static PyObject * Pympc_phase(PyObject *self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPC_OTHER("phase() requires 'mpc' argument"); if (!(result = (PympfrObject*)Pympfr_new(0))) { Py_DECREF(self); return NULL; } result->rc = mpc_arg(result->f, Pympc_AS_MPC(self), context->ctx.mpfr_round); Py_DECREF((PyObject*)self); MPFR_SUBNORMALIZE(result); MPFR_CHECK_OVERFLOW(result, "overflow in 'mpc' phase()"); MPFR_CHECK_INVALID(result, "invalid operation 'mpc' phase()"); MPFR_CHECK_UNDERFLOW(result, "underflow in 'mpc' phase()"); MPFR_CHECK_INEXACT(result, "inexact operation in 'mpc' phase()"); done: if (PyErr_Occurred()) { Py_DECREF((PyObject*)result); result = NULL; } return (PyObject*)result; } PyDoc_STRVAR(doc_mpc_norm, "norm(x) -> mpfr\n\n" "Return the norm of a complex x. The norm(x) is defined as\n" "x.real**2 + x.imag**2. abs(x) is the square root of norm(x).\n"); static PyObject * Pympc_norm(PyObject *self, PyObject *other) { PympfrObject *result; PARSE_ONE_MPC_OTHER("norm() requires 'mpc' argument"); if (!(result = (PympfrObject*)Pympfr_new(0))) { Py_DECREF(self); return NULL; } result->rc = mpc_norm(result->f, Pympc_AS_MPC(self), context->ctx.mpfr_round); Py_DECREF((PyObject*)self); MPFR_SUBNORMALIZE(result); MPFR_CHECK_OVERFLOW(result, "overflow in 'mpc' norm()"); MPFR_CHECK_INVALID(result, "invalid operation 'mpc' norm()"); MPFR_CHECK_UNDERFLOW(result, "underflow in 'mpc' norm()"); MPFR_CHECK_INEXACT(result, "inexact operation in 'mpc' norm()"); done: if (PyErr_Occurred()) { Py_DECREF((PyObject*)result); result = NULL; } return (PyObject*)result; } PyDoc_STRVAR(doc_mpc_polar, "polar(x) -> (abs(x), phase(x))\n\n" "Return the polar coordinate form of a complex x that is in\n" "rectangular form."); static PyObject * Pympc_polar(PyObject *self, PyObject *other) { PyObject *abs, *phase, *result; PARSE_ONE_MPC_OTHER("norm() requires 'mpc' argument"); if (!(abs = Pympc_abs(self))) { Py_DECREF(self); return NULL; } if (!(phase = Pympc_phase(self, other))) { Py_DECREF(abs); Py_DECREF(self); return NULL; } result = Py_BuildValue("(NN)", abs, phase); if (!result) { Py_DECREF(abs); Py_DECREF(phase); } Py_DECREF(self); return result; } PyDoc_STRVAR(doc_mpc_rect, "rect(x) -> mpc\n\n" "Return the polar coordinate form of a complex x that is in\n" "rectangular form."); /* Note: does not properly check for inexact or underflow */ static PyObject * Pympc_rect(PyObject *self, PyObject *args) { PyObject *other; PympcObject *result; PARSE_TWO_MPFR_ARGS(other, "rect() requires 'mpfr','mpfr' arguments"); if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); Py_DECREF(other); return NULL; } mpfr_cos(mpc_realref(result->c), Pympfr_AS_MPFR(other), GET_REAL_ROUND(context)); mpfr_mul(mpc_realref(result->c), mpc_realref(result->c), Pympfr_AS_MPFR(self), GET_REAL_ROUND(context)); mpfr_sin(mpc_imagref(result->c), Pympfr_AS_MPFR(other), GET_IMAG_ROUND(context)); mpfr_mul(mpc_imagref(result->c), mpc_imagref(result->c), Pympfr_AS_MPFR(self), GET_IMAG_ROUND(context)); Py_DECREF(self); Py_DECREF(other); MPC_CLEANUP(result, "rect()"); } PyDoc_STRVAR(doc_mpc_proj, "proj(x) -> mpc\n\n" "Returns the projection of a complex x on to the Riemann sphere."); static PyObject * Pympc_proj(PyObject *self, PyObject *other) { PympcObject *result; PARSE_ONE_MPC_OTHER("proj() requires 'mpc' argument"); if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); return NULL; } result->rc = mpc_proj(result->c, Pympc_AS_MPC(self), GET_MPC_ROUND(context)); Py_DECREF(self); MPC_CLEANUP(result, "proj()"); } #define MPC_UNIOP(NAME) \ static PyObject * \ Pympc_##NAME(PyObject* self, PyObject *other) \ { \ PympcObject *result; \ PARSE_ONE_MPC_OTHER(#NAME "() requires 'mpc' argument"); \ if (!(result = (PympcObject*)Pympc_new(0, 0))) { \ Py_DECREF(self); \ return NULL; \ } \ result->rc = mpc_##NAME(result->c, Pympc_AS_MPC(self), GET_MPC_ROUND(context)); \ Py_DECREF(self); \ MPC_CLEANUP(result, #NAME"()"); \ } MPC_UNIOP(log) MPC_UNIOP(log10) MPC_UNIOP(exp) MPC_UNIOP(sin) MPC_UNIOP(cos) MPC_UNIOP(tan) MPC_UNIOP(sinh) MPC_UNIOP(cosh) MPC_UNIOP(tanh) MPC_UNIOP(asin) MPC_UNIOP(acos) MPC_UNIOP(atan) MPC_UNIOP(asinh) MPC_UNIOP(acosh) MPC_UNIOP(atanh) MPC_UNIOP(sqrt) static PyObject * Pympc_sin_cos(PyObject *self, PyObject *other) { PympcObject *s, *c; PyObject *result; int code; PARSE_ONE_MPC_OTHER("sin_cos() requires 'mpc' argument"); s = (PympcObject*)Pympc_new(0, 0); c = (PympcObject*)Pympc_new(0, 0); result = PyTuple_New(2); if (!s || !c || !result) { Py_DECREF(self); return NULL; } code = mpc_sin_cos(s->c, c->c, Pympc_AS_MPC(self), GET_MPC_ROUND(context), GET_MPC_ROUND(context)); s->rc = MPC_INEX1(code); c->rc = MPC_INEX2(code); MPC_SUBNORMALIZE(s); MPC_SUBNORMALIZE(c); MPC_CHECK_FLAGS(s, "sin_cos()"); MPC_CHECK_FLAGS(c, "sin_cos()"); done: Py_DECREF(self); if (PyErr_Occurred()) { Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)c); Py_XDECREF(result); result = NULL; } else { PyTuple_SET_ITEM(result, 0, (PyObject*)s); PyTuple_SET_ITEM(result, 1, (PyObject*)c); } return result; } static PyObject * Pympc_fma(PyObject *self, PyObject *args) { PympcObject *result, *x, *y, *z; if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("fma() requires 'mpc','mpc','mpc' arguments."); return NULL; } result = (PympcObject*)Pympc_new(0, 0); x = Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0); y = Pympc_From_Complex(PyTuple_GET_ITEM(args, 1), 0, 0); z = Pympc_From_Complex(PyTuple_GET_ITEM(args, 2), 0, 0); if (!result || !x || !y || !z) { TYPE_ERROR("fma() requires 'mpc','mpc','mpc' arguments."); goto done; } result->rc = mpc_fma(result->c, x->c, y->c, z->c, context->ctx.mpfr_round); MPC_SUBNORMALIZE(result); MPC_CHECK_FLAGS(result, "fma()"); done: Py_XDECREF((PyObject*)x); Py_XDECREF((PyObject*)y); Py_XDECREF((PyObject*)z); if (PyErr_Occurred()) { Py_XDECREF(result); result = NULL; } return (PyObject*)result; } static PyObject * Pympc_fms(PyObject *self, PyObject *args) { PympcObject *result, *x, *y, *z; if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("fms() requires 'mpc','mpc','mpc' arguments."); return NULL; } result = (PympcObject*)Pympc_new(0, 0); x = Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0); y = Pympc_From_Complex(PyTuple_GET_ITEM(args, 1), 0, 0); z = Pympc_From_Complex(PyTuple_GET_ITEM(args, 2), 0, 0); if (!result || !x || !y || !z) { TYPE_ERROR("fms() requires 'mpc','mpc','mpc' arguments."); goto done; } mpc_neg(z->c, z->c, GET_MPC_ROUND(context)); result->rc = mpc_fma(result->c, x->c, y->c, z->c, context->ctx.mpfr_round); MPC_SUBNORMALIZE(result); MPC_CHECK_FLAGS(result, "fms()"); done: Py_XDECREF((PyObject*)x); Py_XDECREF((PyObject*)y); Py_XDECREF((PyObject*)z); if (PyErr_Occurred()) { Py_XDECREF(result); result = NULL; } return (PyObject*)result; } static PyObject * Pympc_div_2exp(PyObject *self, PyObject *args) { PympcObject *result = 0; unsigned long exp = 0; if (!PyArg_ParseTuple(args, "O&k", Pympc_convert_arg, &self, &exp)) { TYPE_ERROR("div_2exp() requires 'mpc', 'int' arguments"); return NULL; } if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); return NULL; } result->rc = mpc_div_2ui(Pympc_AS_MPC(result), Pympc_AS_MPC(self), exp, GET_MPC_ROUND(context)); Py_DECREF(self); MPC_CLEANUP(result, "div_2exp()"); } static PyObject * Pympc_mul_2exp(PyObject *self, PyObject *args) { PympcObject *result = 0; unsigned long exp = 0; if (!PyArg_ParseTuple(args, "O&k", Pympc_convert_arg, &self, &exp)) { TYPE_ERROR("mul_2exp() requires 'mpc', 'int' arguments"); return NULL; } if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); return NULL; } result->rc = mpc_mul_2ui(Pympc_AS_MPC(result), Pympc_AS_MPC(self), exp, GET_MPC_ROUND(context)); Py_DECREF(self); MPC_CLEANUP(result, "mul_2exp()"); } static Py_hash_t Pympc_hash(PympcObject *self) { Py_uhash_t hashreal, hashimag, combined; if (self->hash_cache != -1) return self->hash_cache; hashreal = (Py_uhash_t)_mpfr_hash(mpc_realref(self->c)); if (hashreal == (Py_uhash_t)-1) return -1; hashimag = (Py_uhash_t)_mpfr_hash(mpc_imagref(self->c)); if (hashimag == (Py_uhash_t)-1) return -1; combined = hashreal + _PyHASH_IMAG * hashimag; if (combined == (Py_uhash_t)-1) combined = (Py_uhash_t)-2; self->hash_cache = combined; return (Py_hash_t)combined; } static PyObject * Pympc_add_fast(PyObject *x, PyObject *y) { PympcObject *result; if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) { if (!(result = (PympcObject*)Pympc_new(0, 0))) { return NULL; } result->rc = mpc_add(result->c, Pympc_AS_MPC(x), Pympc_AS_MPC(y), GET_MPC_ROUND(context)); MPC_CLEANUP(result, "addition"); return (PyObject*)result; } else { return Pybasic_add(x, y); } } static PyObject * Pympc_add(PyObject *self, PyObject *args) { PympcObject *result; PyObject *other; PARSE_TWO_MPC_ARGS(other, "add() requires 'mpc','mpc' arguments"); if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); Py_DECREF(other); return NULL; } result->rc = mpc_add(result->c, Pympc_AS_MPC(self), Pympc_AS_MPC(other), GET_MPC_ROUND(context)); Py_DECREF(self); Py_DECREF(other); MPC_CLEANUP(result, "add()"); } static PyObject * Pympc_sub_fast(PyObject *x, PyObject *y) { PympcObject *result; if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) { if (!(result = (PympcObject*)Pympc_new(0, 0))) { return NULL; } result->rc = mpc_sub(result->c, Pympc_AS_MPC(x), Pympc_AS_MPC(y), GET_MPC_ROUND(context)); MPC_CLEANUP(result, "subtraction"); return (PyObject*)result; } else { return Pybasic_sub(x, y); } } static PyObject * Pympc_sub(PyObject *self, PyObject *args) { PympcObject *result; PyObject *other; PARSE_TWO_MPC_ARGS(other, "sub() requires 'mpc','mpc' arguments"); if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); Py_DECREF(other); return NULL; } result->rc = mpc_sub(result->c, Pympc_AS_MPC(self), Pympc_AS_MPC(other), GET_MPC_ROUND(context)); Py_DECREF(self); Py_DECREF(other); MPC_CLEANUP(result, "sub()"); } static PyObject * Pympc_mul_fast(PyObject *x, PyObject *y) { PympcObject *result; if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) { if (!(result = (PympcObject*)Pympc_new(0, 0))) { return NULL; } result->rc = mpc_mul(result->c, Pympc_AS_MPC(x), Pympc_AS_MPC(y), GET_MPC_ROUND(context)); MPC_CLEANUP(result, "multiplication"); return (PyObject*)result; } else { return Pybasic_mul(x, y); } } static PyObject * Pympc_mul(PyObject *self, PyObject *args) { PympcObject *result; PyObject *other; PARSE_TWO_MPC_ARGS(other, "mul() requires 'mpc','mpc' arguments"); if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); Py_DECREF(other); return NULL; } result->rc = mpc_mul(result->c, Pympc_AS_MPC(self), Pympc_AS_MPC(other), GET_MPC_ROUND(context)); Py_DECREF(self); Py_DECREF(other); MPC_CLEANUP(result, "mul()"); } static PyObject * Pympc_truediv_fast(PyObject *x, PyObject *y) { PympcObject *result; if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) { if (MPC_IS_ZERO_P(y)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("'mpc' division by zero"); return NULL; } } if (!(result = (PympcObject*)Pympc_new(0, 0))) { return NULL; } result->rc = mpc_div(result->c, Pympc_AS_MPC(x), Pympc_AS_MPC(y), GET_MPC_ROUND(context)); MPC_CLEANUP(result, "division"); return (PyObject*)result; } else { return Pybasic_truediv(x, y); } } #ifdef PY2 static PyObject * Pympc_div2_fast(PyObject *x, PyObject *y) { PympcObject *result; if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) { if (MPC_IS_ZERO_P(y)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("'mpc' division by zero"); return NULL; } } if (!(result = (PympcObject*)Pympc_new(0, 0))) { return NULL; } result->rc = mpc_div(result->c, Pympc_AS_MPC(x), Pympc_AS_MPC(y), GET_MPC_ROUND(context)); MPC_CLEANUP(result, "division"); return (PyObject*)result; } else { return Pybasic_div2(x, y); } } #endif static PyObject * Pympc_div(PyObject *self, PyObject *args) { PympcObject *result; PyObject *other; PARSE_TWO_MPC_ARGS(other, "div() requires 'mpc','mpc' arguments"); if (!(result = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF(self); Py_DECREF(other); return NULL; } if (MPC_IS_ZERO_P(Pympc_AS_MPC(other))) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("'mpc' division by zero"); Py_DECREF(self); Py_DECREF(other); return NULL; } } result->rc = mpc_div(result->c, Pympc_AS_MPC(self), Pympc_AS_MPC(other), GET_MPC_ROUND(context)); Py_DECREF(self); Py_DECREF(other); MPC_CLEANUP(result, "div()"); } PyDoc_STRVAR(doc_mpc_sizeof, "x.__sizeof__()\n\n" "Returns the amount of memory consumed by x."); static PyObject * Pympc_sizeof(PyObject *self, PyObject *other) { return PyIntOrLong_FromSize_t(sizeof(PympcObject) + \ (((mpc_realref(Pympc_AS_MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \ mp_bits_per_limb) * sizeof(mp_limb_t)) + \ (((mpc_imagref(Pympc_AS_MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \ mp_bits_per_limb) * sizeof(mp_limb_t))); } static PyMethodDef Pympc_methods[] = { { "__complex__", Pympc_To_PyComplex, METH_VARARGS, doc_mpc_complex }, { "__format__", Pympc_format, METH_VARARGS, doc_mpc_format }, { "__sizeof__", Pympc_sizeof, METH_NOARGS, doc_mpc_sizeof }, { "conjugate", Pympc_conjugate, METH_NOARGS, doc_mpc_conjugate }, { "digits", Pympc_digits, METH_VARARGS, doc_mpc_digits }, { NULL, NULL, 1 } }; #ifdef PY3 static PyNumberMethods mpc_number_methods = { (binaryfunc) Pympc_add_fast, /* nb_add */ (binaryfunc) Pympc_sub_fast, /* nb_subtract */ (binaryfunc) Pympc_mul_fast, /* nb_multiply */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympc_neg, /* nb_negative */ (unaryfunc) Pympc_pos, /* nb_positive */ (unaryfunc) Pympc_abs, /* nb_absolute */ (inquiry) Pympc_nonzero, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ (unaryfunc) Pympc_To_PyLong, /* nb_int */ 0, /* nb_reserved */ (unaryfunc) Pympc_To_PyFloat, /* nb_float */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pympc_truediv_fast, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ 0, /* nb_index */ }; #else static PyNumberMethods mpc_number_methods = { (binaryfunc) Pympc_add_fast, /* nb_add */ (binaryfunc) Pympc_sub_fast, /* nb_subtract */ (binaryfunc) Pympc_mul_fast, /* nb_multiply */ (binaryfunc) Pympc_div2_fast, /* nb_divide */ (binaryfunc) Pybasic_rem, /* nb_remainder */ (binaryfunc) Pybasic_divmod, /* nb_divmod */ (ternaryfunc) Pympany_pow, /* nb_power */ (unaryfunc) Pympc_neg, /* nb_negative */ (unaryfunc) Pympc_pos, /* nb_positive */ (unaryfunc) Pympc_abs, /* nb_absolute */ (inquiry) Pympc_nonzero, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ 0, /* nb_coerce */ (unaryfunc) Pympc_To_PyIntOrLong, /* nb_int */ (unaryfunc) Pympc_To_PyLong, /* nb_long */ (unaryfunc) Pympc_To_PyFloat, /* nb_float */ 0, /* nb_oct */ 0, /* nb_hex */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_divide */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ (binaryfunc) Pybasic_floordiv, /* nb_floor_divide */ (binaryfunc) Pympc_truediv_fast, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ }; #endif static PyGetSetDef Pympc_getseters[] = { {"precision", (getter)Pympc_getprec_attrib, NULL, "precision in bits", NULL}, {"rc", (getter)Pympc_getrc_attrib, NULL, "return code", NULL}, {"imag", (getter)Pympc_getimag_attrib, NULL, "imaginary component", NULL}, {"real", (getter)Pympc_getreal_attrib, NULL, "real component", NULL}, {NULL} }; static PyTypeObject Pympc_Type = { /* PyObject_HEAD_INIT(&PyType_Type) */ #ifdef PY3 PyVarObject_HEAD_INIT(NULL, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "mpc", /* tp_name */ sizeof(PympcObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor) Pympc_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) Pympc_To_Repr, /* tp_repr */ &mpc_number_methods, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc) Pympc_hash, /* tp_hash */ 0, /* tp_call */ (reprfunc) Pympc_To_Str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ #ifdef PY3 Py_TPFLAGS_DEFAULT, /* tp_flags */ #else Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */ #endif "MPC-based complex number", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)&mpany_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ Pympc_methods, /* tp_methods */ 0, /* tp_members */ Pympc_getseters, /* tp_getset */ }; gmpy2-2.0.7/src/gmpy_mpany.h0000666000000000000000000001074212542614506014411 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_context.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MPANY_H #define GMPY_MPANY_H #ifdef __cplusplus extern "C" { #endif /* Forward declarations begin here. */ static PyObject * Pympany_square(PyObject *self, PyObject *other); static PyObject * Pympany_digits(PyObject *self, PyObject *args); static PyObject * Pympany_sign(PyObject *self, PyObject *other); static PyObject * Pympany_add(PyObject *self, PyObject *args); static PyObject * Pympany_sub(PyObject *self, PyObject *args); static PyObject * Pympany_mul(PyObject *self, PyObject *args); static PyObject * Pympany_div(PyObject *self, PyObject *args); static PyObject * Pympany_to_binary(PyObject *self, PyObject *other); static PyObject * Pympany_pow(PyObject *base, PyObject *exp, PyObject *mod); static PyObject * Pympany_printf(PyObject *self, PyObject *args); #ifdef WITHMPFR static PyObject * Pympany_is_nan(PyObject *self, PyObject *other); static PyObject * Pympany_is_inf(PyObject *self, PyObject *other); static PyObject * Pympany_is_infinite(PyObject *self, PyObject *other); static PyObject * Pympany_is_zero(PyObject *self, PyObject *other); static PyObject * Pympany_log(PyObject *self, PyObject *other); static PyObject * Pympany_exp(PyObject *self, PyObject *other); static PyObject * Pympany_cos(PyObject *self, PyObject *other); static PyObject * Pympany_sin(PyObject *self, PyObject *other); static PyObject * Pympany_tan(PyObject *self, PyObject *other); static PyObject * Pympany_acos(PyObject *self, PyObject *other); static PyObject * Pympany_asin(PyObject *self, PyObject *other); static PyObject * Pympany_atan(PyObject *self, PyObject *other); static PyObject * Pympany_cosh(PyObject *self, PyObject *other); static PyObject * Pympany_sinh(PyObject *self, PyObject *other); static PyObject * Pympany_tanh(PyObject *self, PyObject *other); static PyObject * Pympany_acosh(PyObject *self, PyObject *other); static PyObject * Pympany_asinh(PyObject *self, PyObject *other); static PyObject * Pympany_atanh(PyObject *self, PyObject *other); static PyObject * Pympany_sqrt(PyObject *self, PyObject *other); static PyObject * Pympany_sin_cos(PyObject *self, PyObject *other); static PyObject * Pympany_fma(PyObject *self, PyObject *other); static PyObject * Pympany_fms(PyObject *self, PyObject *other); static PyObject * Pympany_div_2exp(PyObject *self, PyObject *other); static PyObject * Pympany_mul_2exp(PyObject *self, PyObject *other); #endif static PyObject * mpany_richcompare(PyObject *a, PyObject *b, int op); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_mpany.c0000666000000000000000000010363212542614506014405 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_mpany.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Generic module-level methods for gmpy types. * * These methods are designed to accept any number type as input and call * the appropriate type-specific method. For example, gmpy2.digits(n) will * call gmpy2.mpz(n).digits() if n is an integer, gmpy2.mpq(n).digits() if * n is a rational, or gmpy2.mpf(n).digits() is n is a float. */ /* gmpy_square is only intended to be used at the module level! * gmpy_square uses the METH_O/METH_NOARGS calling convention! * gmpy_square assumes mpX_square also use the METH_O/METH_NOARGS convention! */ PyDoc_STRVAR(doc_mpany_square, "square(x) -> number\n\n" "Return x * x. If x is an integer, then the result is an 'mpz'.\n" "If x is a rational, then the result is an 'mpq'. If x is a float,\n" "then the result is an 'mpf'. If x is a complex number, then the\n" "result is an 'mpc'."); static PyObject * Pympany_square(PyObject *self, PyObject *other) { if (isInteger(other)) return Pympz_square(self, other); else if (isRational(other)) return Pympq_square(self, other); #ifdef WITHMPFR else if (isReal(other)) return Pympfr_sqr(self, other); #endif #ifdef WITHMPC else if (isComplex(other)) return Pympc_sqr(self, other); #endif TYPE_ERROR("square() argument type not supported"); return NULL; } /* gmpy_digits is only intended to be used at the module level! * gmpy_digits uses the METH_VARARGS calling convention! * gmpy_digits assumes mpX_digits also use the METH_VARARGS convention! */ PyDoc_STRVAR(doc_g_mpany_digits, "digits(x[, base[, prec]]) -> string\n\n" "Return string representing x. Calls mpz.digits, mpq.digits,\n" "mpfr.digits, or mpc.digits as appropriate."); static PyObject * Pympany_digits(PyObject *self, PyObject *args) { PyObject *temp; if (PyTuple_GET_SIZE(args) == 0) { TYPE_ERROR("digits() requires at least one argument"); return NULL; } temp = PyTuple_GET_ITEM(args, 0); if (isInteger(temp)) return Pympz_digits(self, args); else if (isRational(temp)) return Pympq_digits(self, args); #ifdef WITHMPFR else if (isReal(temp)) return Pympfr_digits(self, args); #endif #ifdef WITHMPC else if (isComplex(temp)) return Pympc_digits(self, args); #endif TYPE_ERROR("digits() argument type not supported"); return NULL; } /* gmpy_sign is only intended to be used at the module level! * gmpy_sign uses the METH_O/METH_NOARGS calling convention! * gmpy_sign assumes mpX_sign also use the METH_O/METH_NOARGS convention! */ PyDoc_STRVAR(doc_g_mpany_sign, "sign(x) -> number\n\n" "Return -1 if x < 0, 0 if x == 0, or +1 if x >0."); static PyObject * Pympany_sign(PyObject *self, PyObject *other) { if (isInteger(other)) return Pympz_sign(self, other); else if (isRational(other)) return Pympq_sign(self, other); #ifdef WITHMPFR else if (isReal(other)) return Pympfr_sign(self, other); #endif TYPE_ERROR("sign() argument type not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_add, "add(x, y) -> number\n\n" "Return x + y."); static PyObject * Pympany_add(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("add() requires 2 arguments."); return NULL; } if (isInteger(PyTuple_GET_ITEM(args, 0)) && isInteger(PyTuple_GET_ITEM(args, 1))) return Pympz_add(self, args); if (isRational(PyTuple_GET_ITEM(args, 0)) && isRational(PyTuple_GET_ITEM(args, 1))) return Pympq_add(self, args); #ifdef WITHMPFR if (isReal(PyTuple_GET_ITEM(args, 0)) && isReal(PyTuple_GET_ITEM(args, 1))) return Pympfr_add(self, args); #endif #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0)) && isComplex(PyTuple_GET_ITEM(args, 1))) return Pympc_add(self, args); #endif TYPE_ERROR("add() argument types not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_sub, "sub(x, y) -> number\n\n" "Return x - y."); static PyObject * Pympany_sub(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("sub() requires 2 arguments."); return NULL; } if (isInteger(PyTuple_GET_ITEM(args, 0)) && isInteger(PyTuple_GET_ITEM(args, 1))) return Pympz_sub(self, args); if (isRational(PyTuple_GET_ITEM(args, 0)) && isRational(PyTuple_GET_ITEM(args, 1))) return Pympq_sub(self, args); #ifdef WITHMPFR if (isReal(PyTuple_GET_ITEM(args, 0)) && isReal(PyTuple_GET_ITEM(args, 1))) return Pympfr_sub(self, args); #endif #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0)) && isComplex(PyTuple_GET_ITEM(args, 1))) return Pympc_sub(self, args); #endif TYPE_ERROR("sub() argument types not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_mul, "mul(x, y) -> number\n\n" "Return x * y."); static PyObject * Pympany_mul(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("mul() requires 2 arguments."); return NULL; } if (isInteger(PyTuple_GET_ITEM(args, 0)) && isInteger(PyTuple_GET_ITEM(args, 1))) return Pympz_mul(self, args); if (isRational(PyTuple_GET_ITEM(args, 0)) && isRational(PyTuple_GET_ITEM(args, 1))) return Pympq_mul(self, args); #ifdef WITHMPFR if (isReal(PyTuple_GET_ITEM(args, 0)) && isReal(PyTuple_GET_ITEM(args, 1))) return Pympfr_mul(self, args); #endif #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0)) && isComplex(PyTuple_GET_ITEM(args, 1))) return Pympc_mul(self, args); #endif TYPE_ERROR("mul() argument types not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_div, "div(x, y) -> number\n\n" "Return x / y."); static PyObject * Pympany_div(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("div() requires 2 arguments."); return NULL; } if (isInteger(PyTuple_GET_ITEM(args, 0)) && isInteger(PyTuple_GET_ITEM(args, 1))) return Pympz_div(self, args); if (isRational(PyTuple_GET_ITEM(args, 0)) && isRational(PyTuple_GET_ITEM(args, 1))) return Pympq_div(self, args); #ifdef WITHMPFR if (isReal(PyTuple_GET_ITEM(args, 0)) && isReal(PyTuple_GET_ITEM(args, 1))) return Pympfr_div(self, args); #endif #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0)) && isComplex(PyTuple_GET_ITEM(args, 1))) return Pympc_div(self, args); #endif TYPE_ERROR("div() argument types not supported"); return NULL; } PyDoc_STRVAR(doc_to_binary, "to_binary(x) -> bytes\n" "Return a Python byte sequence that is a portable binary\n" "representation of a gmpy2 object x. The byte sequence can\n" "be passed to gmpy2.from_binary() to obtain an exact copy of\n" "x's value. Works with mpz, xmpz, mpq, mpfr, and mpc types. \n" "Raises TypeError if x is not a gmpy2 object."); static PyObject * Pympany_to_binary(PyObject *self, PyObject *other) { if(Pympz_Check(other)) return Pympz_To_Binary((PympzObject*)other); else if(Pyxmpz_Check(other)) return Pyxmpz_To_Binary((PyxmpzObject*)other); else if(Pympq_Check(other)) return Pympq_To_Binary((PympqObject*)other); #ifdef WITHMPFR else if(Pympfr_Check(other)) return Pympfr_To_Binary((PympfrObject*)other); #endif #ifdef WITHMPC else if(Pympc_Check(other)) return Pympc_To_Binary((PympcObject*)other); #endif TYPE_ERROR("to_binary() argument type not supported"); return NULL; } static PyObject * Pympany_pow(PyObject *base, PyObject *exp, PyObject *mod) { #ifndef WITHMPFR PyObject *result = 0, *temp; #endif if (isInteger(base) && isInteger(exp)) return Pympz_pow(base, exp, mod); else if (isRational(base) && isRational(exp)) return Pympq_pow(base, exp, mod); #ifdef WITHMPFR else if (isReal(base) && isReal(exp)) return Pympfr_pow(base, exp, mod); #else /* Support mpz**float and float**mpz. */ if (CHECK_MPZANY(base) && PyFloat_Check(exp)) { temp = PyFloat_FromDouble(mpz_get_d(Pympz_AS_MPZ(base))); if (temp) { result = PyNumber_Power(temp, exp, mod); Py_DECREF(temp); } return result; } if (CHECK_MPZANY(exp) && PyFloat_Check(base)) { temp = PyFloat_FromDouble(mpz_get_d(Pympz_AS_MPZ(exp))); if (temp) { result = PyNumber_Power(base, temp, mod); Py_DECREF(temp); } return result; } #endif #ifdef WITHMPC else if (isComplex(base) && isComplex(exp)) return Pympc_pow(base, exp, mod); #endif Py_RETURN_NOTIMPLEMENTED; } PyDoc_STRVAR(doc_printf, "_printf(fmt, x) -> string\n\n" "Return a Python string by formatting 'x' using the format string\n" "'fmt'.\n\n" "WARNING: Invalid format strings will cause a crash. Please see the\n" " GMP and MPFR manuals for details on the format code. 'mpc'\n" " objects are not supported."); static PyObject * Pympany_printf(PyObject *self, PyObject *args) { PyObject *result = 0, *x = 0; char *buffer = 0, *fmtcode = 0; void *generic; int buflen; if (!PyArg_ParseTuple(args, "sO", &fmtcode, &x)) return NULL; if (CHECK_MPZANY(x) || Pympq_Check(x)) { if (CHECK_MPZANY(x)) generic = Pympz_AS_MPZ(x); else generic = Pympq_AS_MPQ(x); buflen = gmp_asprintf(&buffer, fmtcode, generic); if (buflen < 0) { VALUE_ERROR("printf() could not format the 'mpz' or 'mpq' object"); } else { result = Py_BuildValue("s", buffer); GMPY_FREE(buffer); } return result; } #ifdef WITHMPFR else if(Pympfr_Check(x)) { generic = Pympfr_AS_MPFR(x); buflen = mpfr_asprintf(&buffer, fmtcode, generic); if (buflen < 0) { VALUE_ERROR("printf() could not format the 'mpfr' object"); } else { result = Py_BuildValue("s", buffer); GMPY_FREE(buffer); } return result; } #endif #ifdef WITHMPC else if(Pympc_Check(x)) { TYPE_ERROR("printf() does not support 'mpc'"); return NULL; } #endif else { TYPE_ERROR("printf() argument type not supported"); return NULL; } } #ifdef WITHMPC #define MPANY_MPFR_MPC(NAME) \ static PyObject * \ Pympany_##NAME(PyObject *self, PyObject *other) \ { \ if (isReal(other)) \ return Pympfr_##NAME(self, other); \ else if (isComplex(other)) \ return Pympc_##NAME(self, other); \ TYPE_ERROR(#NAME"() argument type not supported"); \ return NULL; \ } #else #define MPANY_MPFR_MPC(NAME) \ static PyObject * \ Pympany_##NAME(PyObject *self, PyObject *other) \ { \ if (isReal(other)) \ return Pympfr_##NAME(self, other); \ TYPE_ERROR(#NAME"() argument type not supported"); \ return NULL; \ } #endif #ifdef WITHMPFR PyDoc_STRVAR(doc_mpany_is_nan, "is_nan(x) -> boolean\n\n" "Return True if x is NaN (Not-A-Number)."); static PyObject * Pympany_is_nan(PyObject *self, PyObject *other) { if (isReal(other)) return Pympfr_is_nan(self, other); #ifdef WITHMPC else if (isComplex(other)) return Pympc_is_NAN(self, other); #endif TYPE_ERROR("is_nan() argument type not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_is_inf, "is_inf(x) -> boolean\n\n" "Return True if x is +Infinity or -Infinity.\n" "Note: is_inf() is deprecated; please use is_infinite()."); static PyObject * Pympany_is_inf(PyObject *self, PyObject *other) { if (isReal(other)) return Pympfr_is_inf(self, other); #ifdef WITHMPC else if (isComplex(other)) return Pympc_is_INF(self, other); #endif TYPE_ERROR("is_inf() argument type not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_is_infinite, "is_infinite(x) -> boolean\n\n" "Return True if x is +Infinity or -Infinity. If x is an mpc, return True\n" "if either x.real or x.imag is infinite."); static PyObject * Pympany_is_infinite(PyObject *self, PyObject *other) { if (isReal(other)) return Pympfr_is_inf(self, other); #ifdef WITHMPC else if (isComplex(other)) return Pympc_is_INF(self, other); #endif TYPE_ERROR("is_infinite() argument type not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_is_finite, "is_finite(x) -> boolean\n\n" "Return True if x is an actual number (i.e. not NaN or Infinity). If x is\n" "an mpc, return True if both x.real and x.imag are finite."); static PyObject * Pympany_is_finite(PyObject *self, PyObject *other) { if (isReal(other)) return Pympfr_is_number(self, other); #ifdef WITHMPC else if (isComplex(other)) return Pympc_is_FINITE(self, other); #endif TYPE_ERROR("is_finite() argument type not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_is_zero, "is_zero(x) -> boolean\n\n" "Return True if x is zero."); static PyObject * Pympany_is_zero(PyObject *self, PyObject *other) { if (isReal(other)) return Pympfr_is_zero(self, other); #ifdef WITHMPC else if (isComplex(other)) return Pympc_is_ZERO(self, other); #endif TYPE_ERROR("is_zero() argument type not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_log, "log(x) -> number\n\n" "Return the natural logarithm of x.\n"); MPANY_MPFR_MPC(log) PyDoc_STRVAR(doc_mpany_log10, "log10(x) -> number\n\n" "Return base-10 logarithm of x."); MPANY_MPFR_MPC(log10) PyDoc_STRVAR(doc_mpany_exp, "exp(x) -> number\n\n" "Return the exponential of x.\n"); MPANY_MPFR_MPC(exp) PyDoc_STRVAR(doc_mpany_cos, "cos(x) -> number\n\n" "Return the cosine of x; x in radians.\n"); MPANY_MPFR_MPC(cos) PyDoc_STRVAR(doc_mpany_sin, "sin(x) -> number\n\n" "Return the sine of x; x in radians.\n"); MPANY_MPFR_MPC(sin) PyDoc_STRVAR(doc_mpany_tan, "tan(x) -> number\n\n" "Return the tangent of x; x in radians.\n"); MPANY_MPFR_MPC(tan) PyDoc_STRVAR(doc_mpany_acos, "acos(x) -> number\n\n" "Return the arc-cosine of x; x in radians.\n"); MPANY_MPFR_MPC(acos) PyDoc_STRVAR(doc_mpany_asin, "asin(x) -> number\n\n" "Return the arc-sine of x; x in radians.\n"); MPANY_MPFR_MPC(asin) PyDoc_STRVAR(doc_mpany_atan, "atan(x) -> number\n\n" "Return the arc-tangent of x; x in radians.\n"); MPANY_MPFR_MPC(atan) PyDoc_STRVAR(doc_mpany_cosh, "cosh(x) -> number\n\n" "Return the hyperbolic cosine of x.\n"); MPANY_MPFR_MPC(cosh) PyDoc_STRVAR(doc_mpany_sinh, "sinh(x) -> number\n\n" "Return the hyberbolic sine of x.\n"); MPANY_MPFR_MPC(sinh) PyDoc_STRVAR(doc_mpany_tanh, "tanh(x) -> number\n\n" "Return the hyperbolic tangent of x.\n"); MPANY_MPFR_MPC(tanh) PyDoc_STRVAR(doc_mpany_acosh, "acosh(x) -> number\n\n" "Return the inverse hyperbolic cosine of x.\n"); MPANY_MPFR_MPC(acosh) PyDoc_STRVAR(doc_mpany_asinh, "asinh(x) -> number\n\n" "Return the inverse hyperbolic sine of x.\n"); MPANY_MPFR_MPC(asinh) PyDoc_STRVAR(doc_mpany_atanh, "atanh(x) -> number\n\n" "Return the inverse hyperbolic tangent of x.\n"); MPANY_MPFR_MPC(atanh) PyDoc_STRVAR(doc_mpany_sqrt, "sqrt(x) -> number\n\n" "Return the square root of x. If x is integer, rational, or real,\n" "then an 'mpfr' will be returned. If x is complex, then an 'mpc' will\n" "be returned. If context.allow_complex is True, negative values of x\n" "will return an 'mpc'.\n"); MPANY_MPFR_MPC(sqrt) PyDoc_STRVAR(doc_mpany_sin_cos, "sin_cos(x) -> (number, number)\n\n" "Return a tuple containing the sine and cosine of x; x in radians.\n"); MPANY_MPFR_MPC(sin_cos) PyDoc_STRVAR(doc_mpany_fma, "fma(x, y, z) -> number\n\n" "Return correctly rounded result of (x * y) + z."); static PyObject * Pympany_fma(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("fma() requires 3 arguments."); return NULL; } if (isReal(PyTuple_GET_ITEM(args, 0)) && isReal(PyTuple_GET_ITEM(args, 1)) && isReal(PyTuple_GET_ITEM(args, 2))) return Pympfr_fma(self, args); #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0)) && isComplex(PyTuple_GET_ITEM(args, 1)) && isComplex(PyTuple_GET_ITEM(args, 2))) return Pympc_fma(self, args); #endif TYPE_ERROR("fma() argument types not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_fms, "fms(x, y, z) -> number\n\n" "Return correctly rounded result of (x * y) - z."); static PyObject * Pympany_fms(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("fms() requires 3 arguments."); return NULL; } if (isReal(PyTuple_GET_ITEM(args, 0)) && isReal(PyTuple_GET_ITEM(args, 1)) && isReal(PyTuple_GET_ITEM(args, 2))) return Pympfr_fms(self, args); #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0)) && isComplex(PyTuple_GET_ITEM(args, 1)) && isComplex(PyTuple_GET_ITEM(args, 2))) return Pympc_fms(self, args); #endif TYPE_ERROR("fms() argument types not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_div_2exp, "div_2exp(x, n) -> number\n\n" "Return 'mpfr' or 'mpc' divided by 2**n."); static PyObject * Pympany_div_2exp(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("div_2exp() requires 2 arguments."); return NULL; } if (isReal(PyTuple_GET_ITEM(args, 0))) return Pympfr_div_2exp(self, args); #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0))) return Pympc_div_2exp(self, args); #endif TYPE_ERROR("div_2exp() argument types not supported"); return NULL; } PyDoc_STRVAR(doc_mpany_mul_2exp, "mul_2exp(x, n) -> number\n\n" "Return 'mpfr' or 'mpc' multiplied by 2**n."); static PyObject * Pympany_mul_2exp(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("mul_2exp() requires 2 arguments."); return NULL; } if (isReal(PyTuple_GET_ITEM(args, 0))) return Pympfr_mul_2exp(self, args); #ifdef WITHMPC if (isComplex(PyTuple_GET_ITEM(args, 0))) return Pympc_mul_2exp(self, args); #endif TYPE_ERROR("mul_2exp() argument types not supported"); return NULL; } #endif /* COMPARING */ static PyObject *_cmp_to_object(int c, int op) { PyObject *result; switch (op) { case Py_LT: c = c < 0; break; case Py_LE: c = c <= 0; break; case Py_EQ: c = c == 0; break; case Py_NE: c = c != 0; break; case Py_GT: c = c > 0; break; case Py_GE: c = c >= 0; break; } result = c ? Py_True : Py_False; Py_INCREF(result); return result; } static PyObject * mpany_richcompare(PyObject *a, PyObject *b, int op) { int c, overflow; mpir_si temp_si; mpz_t tempz; PyObject *tempa = 0, *tempb = 0; PyObject *result = 0; if (CHECK_MPZANY(a)) { if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); c = mpz_cmp(Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else { c = mpz_cmp_si(Pympz_AS_MPZ(a), temp_si); } return _cmp_to_object(c, op); } if (CHECK_MPZANY(b)) { return _cmp_to_object(mpz_cmp(Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)), op); } if (isInteger(b)) { tempb = (PyObject*)Pympz_From_Integer(b); if (!tempb) return NULL; c = mpz_cmp(Pympz_AS_MPZ(a), Pympz_AS_MPZ(tempb)); Py_DECREF(tempb); return _cmp_to_object(c, op); } if (isRational(b)) { tempa = (PyObject*)Pympq_From_Rational(a); tempb = (PyObject*)Pympq_From_Rational(b); if (!tempa || !tempb) { Py_XDECREF(a); Py_XDECREF(b); return NULL; } c = mpq_cmp(Pympq_AS_MPQ(tempa), Pympq_AS_MPQ(tempb)); Py_DECREF(tempa); Py_DECREF(tempb); return _cmp_to_object(c, op); } if (PyFloat_Check(b)) { double d = PyFloat_AS_DOUBLE(b); if (Py_IS_NAN(d)) { result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else if (Py_IS_INFINITY(d)) { if (d < 0.0) return _cmp_to_object(1, op); else return _cmp_to_object(-1, op); } else { return _cmp_to_object(mpz_cmp_d(Pympz_AS_MPZ(a), d), op); } } if (isDecimal(b)) { tempa = (PyObject*)Pympq_From_Rational(a); tempb = (PyObject*)Pympq_From_Decimal(b); if (!tempa || !tempb) { Py_XDECREF(a); Py_XDECREF(b); return NULL; } if (!mpz_cmp_si(mpq_denref(Pympq_AS_MPQ(tempb)), 0)) { if (!mpz_cmp_si(mpq_numref(Pympq_AS_MPQ(tempb)), 0)) { result = (op == Py_NE) ? Py_True : Py_False; Py_DECREF(tempa); Py_DECREF(tempb); Py_INCREF(result); return result; } else if (mpz_cmp_si(mpq_numref(Pympq_AS_MPQ(tempb)), 0) < 0) { Py_DECREF(tempa); Py_DECREF(tempb); return _cmp_to_object(1, op); } else { Py_DECREF(tempa); Py_DECREF(tempb); return _cmp_to_object(-1, op); } } else { c = mpq_cmp(Pympq_AS_MPQ(tempa), Pympq_AS_MPQ(tempb)); Py_DECREF(tempa); Py_DECREF(tempb); return _cmp_to_object(c, op); } } } if (Pympq_Check(a)) { if (Pympq_Check(b)) { return _cmp_to_object(mpq_cmp(Pympq_AS_MPQ(a), Pympq_AS_MPQ(b)), op); } if (isRational(b)) { tempb = (PyObject*)Pympq_From_Rational(b); c = mpq_cmp(Pympq_AS_MPQ(a), Pympq_AS_MPQ(tempb)); Py_DECREF(tempb); return _cmp_to_object(c, op); } if (PyFloat_Check(b)) { double d = PyFloat_AS_DOUBLE(b); if (Py_IS_NAN(d)) { result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else if (Py_IS_INFINITY(d)) { if (d < 0.0) return _cmp_to_object(1, op); else return _cmp_to_object(-1, op); } else { tempb = (PyObject*)Pympq_new(); if (!tempb) return NULL; mpq_set_d(Pympq_AS_MPQ(tempb), d); c = mpq_cmp(Pympq_AS_MPQ(a), Pympq_AS_MPQ(tempb)); Py_DECREF(tempb); return _cmp_to_object(c, op); } } if (isDecimal(b)) { if (!(tempb = (PyObject*)Pympq_From_Decimal(b))) return NULL; if (!mpz_cmp_si(mpq_denref(Pympq_AS_MPQ(tempb)), 0)) { if (!mpz_cmp_si(mpq_numref(Pympq_AS_MPQ(tempb)), 0)) { result = (op == Py_NE) ? Py_True : Py_False; Py_DECREF(tempb); Py_INCREF(result); return result; } else if (mpz_cmp_si(mpq_numref(Pympq_AS_MPQ(tempb)), 0) < 0) { Py_DECREF(tempb); return _cmp_to_object(1, op); } else { Py_DECREF(tempb); return _cmp_to_object(-1, op); } } else { c = mpq_cmp(Pympq_AS_MPQ(a), Pympq_AS_MPQ(tempb)); Py_DECREF(tempb); return _cmp_to_object(c, op); } } } #ifdef WITHMPFR if (Pympfr_Check(a)) { if (Pympfr_Check(b)) { mpfr_clear_flags(); c = mpfr_cmp(Pympfr_AS_MPFR(a), Pympfr_AS_MPFR(b)); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } if (PyFloat_Check(b)) { double d = PyFloat_AS_DOUBLE(b); mpfr_clear_flags(); c = mpfr_cmp_d(Pympfr_AS_MPFR(a), d); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } if (isInteger(b)) { tempb = (PyObject*)Pympz_From_Integer(b); if (!tempb) return NULL; mpfr_clear_flags(); c = mpfr_cmp_z(Pympfr_AS_MPFR(a), Pympz_AS_MPZ(tempb)); Py_DECREF(tempb); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } if (isRational(b)) { tempb = (PyObject*)Pympq_From_Rational(b); if (!tempb) return NULL; mpfr_clear_flags(); c = mpfr_cmp_q(Pympfr_AS_MPFR(a), Pympq_AS_MPQ(tempb)); Py_DECREF(tempb); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } if (isDecimal(b)) { tempb = (PyObject*)Pympq_From_Decimal(b); if (!tempb) return NULL; if (!mpz_cmp_si(mpq_denref(Pympq_AS_MPQ(tempb)), 0)) { if (!mpz_cmp_si(mpq_numref(Pympq_AS_MPQ(tempb)), 0)) { context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_DECREF(tempb); Py_INCREF(result); return result; } else if (mpz_cmp_si(mpq_numref(Pympq_AS_MPQ(tempb)), 0) < 0) { Py_DECREF(tempb); return _cmp_to_object(1, op); } else { Py_DECREF(tempb); return _cmp_to_object(-1, op); } } else { mpfr_clear_flags(); c = mpfr_cmp_q(Pympfr_AS_MPFR(a), Pympq_AS_MPQ(tempb)); Py_DECREF(tempb); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } } if (isReal(b)) { tempb = (PyObject*)Pympfr_From_Real(b, 0); if (!tempb) return NULL; mpfr_clear_flags(); c = mpfr_cmp(Pympfr_AS_MPFR(a), Pympfr_AS_MPFR(tempb)); Py_DECREF(tempb); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } } #endif #ifdef WITHMPC if (Pympc_Check(a)) { if (!(op == Py_EQ || op == Py_NE)) { TYPE_ERROR("no ordering relation is defined for complex numbers"); return NULL; } if (Pympc_Check(b)) { mpfr_clear_flags(); c = mpc_cmp(Pympc_AS_MPC(a), Pympc_AS_MPC(b)); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } if (PyComplex_Check(b)) { PympcObject *tempmpc; if (!(tempmpc = Pympc_From_PyComplex(b, 53, 53))) return NULL; mpfr_clear_flags(); c = mpc_cmp(Pympc_AS_MPC(a), Pympc_AS_MPC(tempmpc)); Py_DECREF((PyObject*)tempmpc); if (mpfr_erangeflag_p()) { /* Set erange and check if an exception should be raised. */ context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { return _cmp_to_object(c, op); } } /* a.imag must be 0 or else all further comparisons will be NE */ if (!mpfr_zero_p(mpc_imagref(Pympc_AS_MPC(a)))) { /* if a.real is NaN, possibly raise exception */ if (mpfr_nan_p(mpc_realref(Pympc_AS_MPC(a)))) { context->ctx.erange = 1; if (context->ctx.trap_erange) { GMPY_ERANGE("comparison with NaN"); return NULL; } } result = (op == Py_NE) ? Py_True : Py_False; Py_INCREF(result); return result; } else { PyObject *tempmpfr; tempmpfr = Pympfr_new(mpfr_get_prec(mpc_realref(Pympc_AS_MPC(a)))); if (!tempmpfr) return NULL; mpc_real(Pympfr_AS_MPFR(tempmpfr), Pympc_AS_MPC(a), context->ctx.mpfr_round); result = mpany_richcompare(tempmpfr, b, op); Py_DECREF(tempmpfr); return result; } } #endif Py_RETURN_NOTIMPLEMENTED; } gmpy2-2.0.7/src/gmpy_misc.h0000666000000000000000000000542612542614506014223 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_misc.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_MISC_H #define GMPY_MISC_H #ifdef __cplusplus extern "C" { #endif static PyObject * Pygmpy_get_license(PyObject *self, PyObject *args); static PyObject * Pygmpy_get_version(PyObject *self, PyObject *args); static PyObject * Pygmpy_get_cvsid(PyObject *self, PyObject *args); static PyObject * Pygmpy_get_mp_version(PyObject *self, PyObject *args); static PyObject * Pygmpy_get_mpfr_version(PyObject *self, PyObject *args); static PyObject * Pygmpy_get_mpc_version(PyObject *self, PyObject *args); static PyObject * Pygmpy_get_mp_limbsize(PyObject *self, PyObject *args); static PyObject * Pygmpy_get_cache(PyObject *self, PyObject *args); static PyObject * Pygmpy_set_cache(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_misc.c0000666000000000000000000001266412542614506014220 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_misc.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Miscellaneous module-level functions and helper functions. */ PyDoc_STRVAR(doc_license, "license() -> string\n\n" "Return string giving license information."); static PyObject * Pygmpy_get_license(PyObject *self, PyObject *args) { return Py_BuildValue("s", gmpy_license); } PyDoc_STRVAR(doc_version, "version() -> string\n\n" "Return string giving current GMPY2 version."); static PyObject * Pygmpy_get_version(PyObject *self, PyObject *args) { return Py_BuildValue("s", gmpy_version); } PyDoc_STRVAR(doc_cvsid, "_cvsid() -> string\n\n" "Return string giving current GMPY2 cvs Id."); static PyObject * Pygmpy_get_cvsid(PyObject *self, PyObject *args) { return Py_BuildValue("s", _gmpy_cvs); } PyDoc_STRVAR(doc_mp_version, "mp_version() -> string\n\n" "Return string giving the name and version of the multiple precision\n" "library used."); static PyObject * Pygmpy_get_mp_version(PyObject *self, PyObject *args) { #ifndef __MPIR_VERSION return Py2or3String_FromFormat("%s %s", "GMP", gmp_version); #else return Py2or3String_FromFormat("%s %s", "MPIR", mpir_version); #endif } PyDoc_STRVAR(doc_mpfr_version, "mpfr_version() -> string\n\n" "Return string giving current MPFR version. Return None if MPFR\n" "support is not available."); static PyObject * Pygmpy_get_mpfr_version(PyObject *self, PyObject *args) { #ifdef WITHMPFR return Py2or3String_FromFormat("%s %s", "MPFR", MPFR_VERSION_STRING); #else Py_RETURN_NONE; #endif } PyDoc_STRVAR(doc_mpc_version, "mpc_version() -> string\n\n" "Return string giving current MPC version. Return None if MPC\n" "support is not available."); static PyObject * Pygmpy_get_mpc_version(PyObject *self, PyObject *args) { #ifdef WITHMPC return Py2or3String_FromFormat("%s %s", "MPC", MPC_VERSION_STRING); #else Py_RETURN_NONE; #endif } PyDoc_STRVAR(doc_mp_limbsize, "mp_limbsize() -> integer\n\n\ Return the number of bits per limb."); static PyObject * Pygmpy_get_mp_limbsize(PyObject *self, PyObject *args) { return Py_BuildValue("i", mp_bits_per_limb); } /* * access cache options */ PyDoc_STRVAR(doc_get_cache, "get_cache() -> (cache_size, object_size)\n\n\ Return the current cache size (number of objects) and maximum size\n\ per object (number of limbs) for all GMPY2 objects."); static PyObject * Pygmpy_get_cache(PyObject *self, PyObject *args) { return Py_BuildValue("(ii)", global.cache_size, global.cache_obsize); } PyDoc_STRVAR(doc_set_cache, "set_cache(cache_size, object_size)\n\n\ Set the current cache size (number of objects) and the maximum size\n\ per object (number of limbs). Raises ValueError if cache size exceeds\n\ 1000 or object size exceeds 16384."); static PyObject * Pygmpy_set_cache(PyObject *self, PyObject *args) { int newcache = -1, newsize = -1; if (!PyArg_ParseTuple(args, "ii", &newcache, &newsize)) return NULL; if (newcache<0 || newcache>MAX_CACHE) { VALUE_ERROR("cache size must between 0 and 1000"); return NULL; } if (newsize<0 || newsize>MAX_CACHE_LIMBS) { VALUE_ERROR("object size must between 0 and 16384"); return NULL; } global.cache_size = newcache; global.cache_obsize = newsize; set_zcache(); set_pympzcache(); set_pympqcache(); set_pyxmpzcache(); #ifdef WITHMPFR set_pympfrcache(); #endif #ifdef WITHMPC set_pympccache(); #endif Py_RETURN_NONE; } gmpy2-2.0.7/src/gmpy_convert.h0000666000000000000000000002464212542614506014751 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_convert.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_CONVERT_H #define GMPY_CONVERT_H #ifdef __cplusplus extern "C" { #endif /* The following functions identify and classify the numeric types that are * supported by gmpy2. * * These checks are currently implemented as functions but may be * implemented as macros in the future. */ /* Checks for mpz, xmpz, and the integer types included with Python. */ static int isInteger(PyObject* obj); /* Checks for the Fraction type included with Python. */ static int isFraction(PyObject* obj); /* Combined mpq, isInteger() and isFraction() check. */ static int isRational(PyObject* obj); #ifdef WITHMPFR /* Checks for the Decimal type included with Python. */ static int isDecimal(PyObject* obj); /* Combined mpfr, PyFloat, isDecimal() and isRational() check. */ static int isReal(PyObject* obj); #endif #ifdef WITHMPC /* Combined mpc, PyComplex, and isReal() check. */ static int isComplex(PyObject* obj); #endif /********* Integer Conversions *********/ /* conversions with Pympz */ #ifdef PY2 static PympzObject * Pympz_From_PyInt(PyObject *self); #endif static PympzObject * Pympz_From_PyStr(PyObject *s, int base); static PympzObject * Pympz_From_PyLong(PyObject *obj); static PympzObject * Pympz_From_Pyxmpz(PyObject *self); static PympzObject * Pympz_From_PyFloat(PyObject *self); static PympzObject * Pympz_From_Number(PyObject *obj); static PyObject * Pympz_To_PyLong(PympzObject *self); static PyObject * Pympz_To_PyIntOrLong(PympzObject *self); static PyObject * Pympz_To_PyFloat(PympzObject *self); static PyObject * Pympz_To_PyStr(PympzObject *self, int base, int option); /* conversions with Pyxmpz */ #ifdef PY2 static PyxmpzObject * Pyxmpz_From_PyInt(PyObject *self); #endif static PyxmpzObject * Pyxmpz_From_PyStr(PyObject *s, int base); static PyxmpzObject * Pyxmpz_From_PyLong(PyObject *obj); static PyxmpzObject * Pyxmpz_From_Pyxmpz(PyObject *self); static PyxmpzObject * Pyxmpz_From_Pympz(PyObject *self); static PyxmpzObject * Pyxmpz_From_PyFloat(PyObject *self); static PyxmpzObject * Pyxmpz_From_Number(PyObject *obj); static PyObject * Pyxmpz_To_PyLong(PyxmpzObject *self); static PyObject * Pyxmpz_To_PyIntOrLong(PyxmpzObject *self); static PyObject * Pyxmpz_To_PyStr(PyxmpzObject *self, int base, int option); /* for str() and repr() */ static PyObject * Pympz_To_Str(PympzObject *self); static PyObject * Pympz_To_Repr(PympzObject *self); static PyObject * Pyxmpz_To_Str(PyxmpzObject *self); static PyObject * Pyxmpz_To_Repr(PyxmpzObject *self); /* Miscellaneous integer conversion functions. */ static int mpz_set_PyStr(mpz_ptr z, PyObject *s, int base); static PyObject * mpz_ascii(mpz_t z, int base, int option); static PyObject * xmpz_ascii(mpz_t z, int base, int option); #if 0 static int Pympz_convert_arg(PyObject *arg, PyObject **ptr); #endif /* The following functions convert isInteger() objects into C types. */ #ifdef WITHMPFR /* Should only be used by MPFR/MPC related code. */ static long clong_From_Integer(PyObject *obj); #endif /* MPIR 2.6.0 introduces two new data types: mpir_si and mpir_ui. On all * platforms except 64-bit Windows, those data types correspond to "long" and * "unsigned long". On 64-bit Windows, those data type correspond to * "long long" and "unsigned long long". */ /* Should be used by all MPIR/GMP related code. */ static mpir_si SI_From_Integer(PyObject *obj); static mpir_ui UI_From_Integer(PyObject *obj); static Py_ssize_t ssize_t_From_Integer(PyObject *obj); /********* Pympq Conversions *********/ /* Conversions with Pympq */ #ifdef PY2 static PympqObject * Pympq_From_PyInt(PyObject *self); static PyObject * Pympq_To_PyInt(PympqObject *self); #endif static PympqObject * Pympq_From_PyLong(PyObject *self); static PympqObject * Pympq_From_Pympz(PyObject *self); static PympqObject * Pympq_From_Pyxmpz(PyObject *obj); static PympqObject * Pympq_From_PyFloat(PyObject *self); static PympqObject * Pympq_From_Fraction(PyObject *obj); static PympqObject * Pympq_From_PyStr(PyObject *stringarg, int base); /* NOTE: Pympq_From_Decimal returns an invalid mpq object when attempting to * convert a NaN or Infinity. If the denominator is 0, then interpret * the numerator as: * -1: -Infinity * 0: Nan * 1: Infinity * * If the numerator is 0 and the denominator is not 0, then the sign of * the denominator is the sign of the 0. */ static PympqObject * Pympq_From_Decimal(PyObject* obj); static PympqObject * Pympq_From_Number(PyObject* obj); static PyObject * Pympq_To_PyLong(PympqObject *self); static PympzObject * Pympq_To_Pympz(PyObject *self); static PyxmpzObject * Pympq_To_Pyxmpz(PyObject *self); static PyObject * Pympq_To_PyFloat(PympqObject *self); static PyObject * Pympq_To_PyStr(PympqObject *self, int base, int option); /* support str() and repr() */ static PyObject * Pympq_To_Str(PympqObject *self); static PyObject * Pympq_To_Repr(PympqObject *self); /* Miscellaneous rational conversion functions. */ int Pympq_convert_arg(PyObject *arg, PyObject **ptr); #ifdef WITHMPFR /********* Pympfr Conversions *********/ /* Conversions with Pympfr */ #ifdef PY2 static PympfrObject * Pympfr_From_PyInt(PyObject *self, mpfr_prec_t bits); static PyObject * Pympfr_To_PyInt(PympfrObject *self); #endif static PympfrObject * Pympfr_From_Pympfr(PyObject *self, mpfr_prec_t bits); static PympfrObject * Pympfr_From_PyFloat(PyObject *self, mpfr_prec_t bits); static PympfrObject * Pympfr_From_PyLong(PyObject *self, mpfr_prec_t bits); static PympfrObject * Pympfr_From_Pympz(PyObject *self, mpfr_prec_t bits); static PympfrObject * Pympfr_From_Real(PyObject* obj, mpfr_prec_t bits); static PympfrObject * Pympfr_From_Pympq(PyObject *self, mpfr_prec_t bits); static PympfrObject * Pympfr_From_PyStr(PyObject *s, int base, mpfr_prec_t bits); static PympfrObject * Pympfr_From_Decimal(PyObject *obj, mpfr_prec_t bits); static PympfrObject * Pympfr_From_Real(PyObject* obj, mpfr_prec_t bits); static PympzObject * Pympfr_To_Pympz(PyObject *self); static PyxmpzObject * Pympfr_To_Pyxmpz(PyObject *self); static PympqObject * Pympfr_To_Pympq(PyObject *self); static PyObject * Pympfr_To_PyLong(PympfrObject *self); static PyObject * Pympfr_To_PyFloat(PympfrObject *self); static PyObject * Pympfr_To_PyStr(PympfrObject *self, int base, int digits); /* support str() and repr() */ static PyObject * Pympfr_To_Str(PympfrObject *self); static PyObject * Pympfr_To_Repr(PympfrObject *self); /* Miscellaneous */ static int Pympfr_convert_arg(PyObject *arg, PyObject **ptr); static PympqObject * stern_brocot(PympfrObject* self, PympfrObject *err, mpfr_prec_t prec, int mayz); #endif #ifdef WITHMPC /********* Pympc Conversions *********/ /* Conversions with Pympc */ #ifdef PY2 static PympcObject * Pympc_From_PyInt(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PyObject * Pympc_To_PyIntOrLong(PyObject *self); #endif static PympcObject * Pympc_From_Pympc(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PympcObject * Pympc_From_PyComplex(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PympcObject * Pympc_From_Pympfr(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PympcObject * Pympc_From_PyFloat(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PympcObject * Pympc_From_Pympz(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PympcObject * Pympc_From_Pympq(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PympcObject * Pympc_From_PyLong(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec); static PympcObject * Pympc_From_PyStr(PyObject *s, int base, mpfr_prec_t rbits, mpfr_prec_t ibits); static PympcObject * Pympc_From_Complex(PyObject* obj, mpfr_prec_t rprec, mpfr_prec_t iprec); static PyObject * Pympc_To_PyFloat(PyObject *self); static PyObject * Pympc_To_PyLong(PyObject *self); static PyObject * Pympc_To_PyStr(PympcObject *self, int base, int digits); static PyObject * Pympc_To_PyComplex(PyObject *self, PyObject *other); /* support str() and repr() */ static PyObject * Pympc_To_Str(PympcObject *self); static PyObject * Pympc_To_Repr(PympcObject *self); /* Miscellaneous */ static PyObject * raw_mpfr_ascii(mpfr_t self, int base, int digits, int round); int Pympc_convert_arg(PyObject *arg, PyObject **ptr); #endif #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_convert.c0000666000000000000000000022330612542614506014742 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_convert.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file contains all the conversion functions for gmpy2. * * Overview * -------- * gmpy2 tries to optimize the performance and accuracy of conversions from * other numeric types. gmpy2 uses a LBYL (Look Before You Leap) approach and * identifies the numeric type before conversion before conversion to a gmpy2 * type. The basic operations (+, -, *, /) are optimized to directly work with * some basic types such as C longs or doubles. * * Support for the Decimal type is a challenge. For the basic operations, it * is most accurate to convert a Decimal instance into an mpq and then use * MPFR's functions to accurately operate on an mpfr and mpq. This approach is * challenging because (1) a large exponent can create a very large mpq and * (2) the changes made to C-coded version of Decimal in Python 3.3. * */ static int isInteger(PyObject* obj) { if (Pympz_Check(obj)) return 1; if (PyIntOrLong_Check(obj)) return 1; if (Pyxmpz_Check(obj)) return 1; return 0; } static int isFraction(PyObject* obj) { if (!strcmp(Py_TYPE(obj)->tp_name, "Fraction")) return 1; return 0; } static int isDecimal(PyObject* obj) { #if PY_VERSION_HEX < 0x03030000 if (!strcmp(Py_TYPE(obj)->tp_name, "Decimal")) return 1; #else if (!strcmp(Py_TYPE(obj)->tp_name, "decimal.Decimal")) return 1; #endif return 0; } static int isRational(PyObject* obj) { if (Pympz_Check(obj)) return 1; if (PyIntOrLong_Check(obj)) return 1; if (Pympq_Check(obj)) return 1; if (Pyxmpz_Check(obj)) return 1; if (isFraction(obj)) return 1; return 0; } #ifdef WITHMPFR static int isReal(PyObject* obj) { if (Pympz_Check(obj)) return 1; if (PyIntOrLong_Check(obj)) return 1; if (Pympq_Check(obj)) return 1; if (Pympfr_Check(obj)) return 1; if (Pyxmpz_Check(obj)) return 1; if (PyFloat_Check(obj)) return 1; if (isDecimal(obj)) return 1; if (isFraction(obj)) return 1; return 0; } #endif #ifdef WITHMPC static int isComplex(PyObject* obj) { if (Pympz_Check(obj)) return 1; if (PyIntOrLong_Check(obj)) return 1; if (Pympq_Check(obj)) return 1; if (Pympfr_Check(obj)) return 1; if (Pyxmpz_Check(obj)) return 1; if (Pympc_Check(obj)) return 1; if (PyFloat_Check(obj)) return 1; if (PyComplex_Check(obj)) return 1; if (isDecimal(obj)) return 1; if (isFraction(obj)) return 1; return 0; } #endif static PyxmpzObject * Pyxmpz_From_Pyxmpz(PyObject *self) { PyxmpzObject *newob; if ((newob = (PyxmpzObject*)Pyxmpz_new())) mpz_set(newob->z, Pyxmpz_AS_MPZ(self)); return newob; } static PympzObject * Pympz_From_Pyxmpz(PyObject *self) { PympzObject *newob; if ((newob = (PympzObject*)Pympz_new())) mpz_set(newob->z, Pyxmpz_AS_MPZ(self)); return newob; } static PyxmpzObject * Pyxmpz_From_Pympz(PyObject *self) { PyxmpzObject *newob; if ((newob = (PyxmpzObject*)Pyxmpz_new())) mpz_set(newob->z, Pyxmpz_AS_MPZ(self)); return newob; } #ifdef PY2 static PympzObject * Pympz_From_PyInt(PyObject *self) { PympzObject *newob; if ((newob = (PympzObject*)Pympz_new())) mpz_set_si(newob->z, PyInt_AS_LONG(self)); return newob; } static PyxmpzObject * Pyxmpz_From_PyInt(PyObject *self) { PyxmpzObject *newob; if ((newob = (PyxmpzObject*)Pyxmpz_new())) mpz_set_si(newob->z, PyInt_AsLong(self)); return newob; } #endif static PympzObject * Pympz_From_PyFloat(PyObject *self) { PympzObject *newob; if ((newob = (PympzObject*)Pympz_new())) { double d = PyFloat_AsDouble(self); if (Py_IS_NAN(d)) { Py_DECREF((PyObject*)newob); VALUE_ERROR("'mpz' does not support NaN"); return NULL; } if (Py_IS_INFINITY(d)) { Py_DECREF((PyObject*)newob); OVERFLOW_ERROR("'mpz' does not support Infinity"); return NULL; } mpz_set_d(newob->z, d); } return newob; } static PyxmpzObject * Pyxmpz_From_PyFloat(PyObject *self) { PyxmpzObject *newob; if ((newob = (PyxmpzObject*)Pyxmpz_new())) { double d = PyFloat_AsDouble(self); if (Py_IS_NAN(d)) { Py_DECREF((PyObject*)newob); VALUE_ERROR("'xmpz' does not support NaN"); return NULL; } if (Py_IS_INFINITY(d)) { Py_DECREF((PyObject*)newob); OVERFLOW_ERROR("'xmpz' does not support Infinity"); return NULL; } mpz_set_d(newob->z, d); } return newob; } /* For fast conversion between PyLong and mpz, we use code located in * mpz_pylong.c. */ static PympzObject * Pympz_From_PyLong(PyObject * obj) { PympzObject *newob; if (!(newob = (PympzObject*)Pympz_new())) return NULL; mpz_set_PyIntOrLong(newob->z, obj); return newob; } static PyxmpzObject * Pyxmpz_From_PyLong(PyObject * obj) { PyxmpzObject *newob; if (!(newob = (PyxmpzObject*)Pyxmpz_new())) return NULL; mpz_set_PyIntOrLong(newob->z, obj); return newob; } /* mpz_set_PyStr returns -1 on error, 1 if successful. */ static int mpz_set_PyStr(mpz_ptr z, PyObject *s, int base) { unsigned char *cp; Py_ssize_t len, i; PyObject *ascii_str = NULL; if (PyBytes_Check(s)) { len = PyBytes_Size(s); cp = (unsigned char*)PyBytes_AsString(s); } else { ascii_str = PyUnicode_AsASCIIString(s); if (!ascii_str) { VALUE_ERROR("string contains non-ASCII characters"); return -1; } len = PyBytes_Size(ascii_str); cp = (unsigned char*)PyBytes_AsString(ascii_str); } /* Don't allow NULL characters */ for (i=0; iz, s, base) == -1) { Py_DECREF((PyObject*)newob); return NULL; } return newob; } static PyxmpzObject * Pyxmpz_From_PyStr(PyObject *s, int base) { PyxmpzObject *newob; if (!(newob = (PyxmpzObject*)Pyxmpz_new())) return NULL; if (mpz_set_PyStr(newob->z, s, base) == -1) { Py_DECREF((PyObject*)newob); return NULL; } return newob; } /* For fast mpz to PyLong conversion, we use code located in mpz_pylong. */ static PyObject * Pympz_To_PyLong(PympzObject *self) { return mpz_get_PyLong(Pympz_AS_MPZ(self)); } static PyObject * Pyxmpz_To_PyLong(PyxmpzObject *self) { return mpz_get_PyLong(Pyxmpz_AS_MPZ(self)); } /* The _To_PyIntOrLong functions should be used when converting a number back * to a Python value since is automatically returns an "int" or "long" when * using Python 2.x. The _To_PyLong functions (above) should only be used * when a PyLong is specifically needed for Python 2.x. */ static PyObject * Pympz_To_PyIntOrLong(PympzObject *self) { #ifdef PY3 return Pympz_To_PyLong(self); #else if (mpz_fits_slong_p(self->z)) /* cast is safe since we know if first in a signed long */ return PyInt_FromLong((long)mpz_get_si(self->z)); else return Pympz_To_PyLong(self); #endif } static PyObject * Pyxmpz_To_PyIntOrLong(PyxmpzObject *self) { #ifdef PY3 return Pyxmpz_To_PyLong(self); #else if (mpz_fits_slong_p(self->z)) /* cast is safe since we know if first in a signed long */ return PyInt_FromLong((long)mpz_get_si(self->z)); else return Pyxmpz_To_PyLong(self); #endif } static PyObject * Pympz_To_PyFloat(PympzObject *self) { double res = mpz_get_d(self->z); if (Py_IS_INFINITY(res)) { OVERFLOW_ERROR("'mpz' too large to convert to float"); return NULL; } return PyFloat_FromDouble(res); } /* Format an mpz into any base (2 to 62). Bits in the option parameter * control various behaviors: * bit 0: if set, output is wrapped with 'mpz(...)' * bit 1: if set, a '+' is included for positive numbers * bit 2: if set, a ' ' is included for positive nubmers * bit 3: if set, a '0b', '0o', or '0x' is included for binary, octal, hex * bit 4: if set, no prefix is included for binary, octal, hex * * Note: if neither bit 3 or 4 is set, prefixes that match the platform default * are included. * * If base < 0, capital letters are used */ static char* ztag = "mpz("; static PyObject * mpz_ascii(mpz_t z, int base, int option) { PyObject *result; char *buffer, *p; int negative = 0; size_t size; if (!((base == 0) || ((base >= -36) && (base <= -2)) || ((base >= 2) && (base <= 62)) )) { VALUE_ERROR("base must be in the interval 2 ... 62"); return NULL; } /* Allocate extra space for: * * minus sign and trailing NULL byte (2) * 'mpz()' tag (5) * '0x' prefix (2) * 'L' suffix (1) * ----- * 10 */ size = mpz_sizeinbase(z, (base < 0 ? -base : base)) + 11; TEMP_ALLOC(buffer, size); if (mpz_sgn(z) < 0) { negative = 1; mpz_neg(z, z); } p = buffer; if (option & 1) { strcpy(p, ztag); p += strlen(p); } if (negative) *(p++) = '-'; else if (option & 2) *(p++) = '+'; else if (option & 4) *(p++) = ' '; if (option & 8) { if (base == 2) { *(p++) = '0'; *(p++) = 'b'; } else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; } else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; } else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; } } else if (!(option & 24)) { #ifdef PY2 if (base == 8) { *(p++) = '0'; } #else if (base == 2) { *(p++) = '0'; *(p++) = 'b'; } else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; } #endif else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; } else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; } } mpz_get_str(p, base, z); /* Doesn't return number of characters */ p = buffer + strlen(buffer); /* Address of NULL byte */ #ifdef PY2 if ((option & 1) && !mpz_fits_slong_p(z)) *(p++) = 'L'; #endif if (option & 1) *(p++) = ')'; *(p++) = '\00'; result = Py_BuildValue("s", buffer); if (negative == 1) { mpz_neg(z, z); } TEMP_FREE(buffer, size); return result; } /* Format an xmpz into any base (2 to 62). If with_tag != 0, the the output * is wrapped with 'xmpz(...)'. If with_sign > 0, a plus or minus leading * sign is always included. If with_sign < 0, a space is included instead of * a plus sign. */ static char* xztag = "xmpz("; static PyObject * xmpz_ascii(mpz_t z, int base, int option) { PyObject *result; char *buffer, *p; int negative = 0; size_t size; if (!((base == 0) || ((base >= -36) && (base <= -2)) || ((base >= 2) && (base <= 62)) )) { VALUE_ERROR("base must be in the interval 2 ... 62"); return NULL; } /* Allocate extra space for: * * minus sign and trailing NULL byte (2) * 'gmpy2.xmpz()' tag (6) * '0x' prefix (2) * 'L' suffix (1) * ----- * 11 */ size = mpz_sizeinbase(z, base) + 12; TEMP_ALLOC(buffer, size); if (mpz_sgn(z) < 0) { negative = 1; mpz_neg(z, z); } p = buffer; if (option & 1) { strcpy(p, xztag); p += strlen(p); } if (negative) *(p++) = '-'; else if (option & 2) *(p++) = '+'; else if (option & 4) *(p++) = ' '; if (option & 8) { if (base == 2) { *(p++) = '0'; *(p++) = 'b'; } else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; } else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; } else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; } } else if (!(option & 24)) { #ifdef PY2 if (base == 8) { *(p++) = '0'; } #else if (base == 2) { *(p++) = '0'; *(p++) = 'b'; } else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; } #endif else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; } else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; } } mpz_get_str(p, base, z); /* Doesn't return number of characters */ p = buffer + strlen(buffer); /* Address of NULL byte */ #ifdef PY2 if ((option & 1) && !mpz_fits_slong_p(z)) *(p++) = 'L'; #endif if (option & 1) *(p++) = ')'; *(p++) = '\00'; result = Py_BuildValue("s", buffer); if (negative == 1) { mpz_neg(z, z); } TEMP_FREE(buffer, size); return result; } static PyObject * Pympz_To_PyStr(PympzObject *self, int base, int option) { return mpz_ascii(self->z, base, option); } static PyObject * Pyxmpz_To_PyStr(PyxmpzObject *self, int base, int option) { return xmpz_ascii(self->z, base, option); } /* Number conversion routines * * The routines anynum2mpX will attempt to convert any number-like object into * into a gmpy object. These routines are intended for construction of mpXs. * The accepted number-like objects are: * 1) int (Python 2.x) * 2) long (Python 2.x and 3.x) * 3) float * 4) Decimal * 5) Fraction * 6) other gmpy objects * * The routine Pympz_From_Integer will only convert integer-like objects into to a * gmpy mpz. The accepted integer-like objects are: * 1) int * 2) long * 3) mpz * 4) xmpz * * The routine Pympq_From_Rational will convert an integer- and rational-like * object into a gmpy mpq. The accepted objects are: * 1) int * 2) long * 3) Fraction * 4) mpz * 5) mpq * 6) xmpz */ static PympzObject* Pympz_From_Number(PyObject* obj) { PympzObject* newob = 0; PympqObject* temp = 0; if (Pympz_Check(obj)) { Py_INCREF(obj); newob = (PympzObject *) obj; #ifdef PY2 } else if (PyInt_Check(obj)) { newob = Pympz_From_PyInt(obj); #endif } else if (PyLong_Check(obj)) { newob = Pympz_From_PyLong(obj); } else if (Pympq_Check(obj)) { newob = Pympq_To_Pympz(obj); } #ifdef WITHMPFR else if (Pympfr_Check(obj)) { newob = Pympfr_To_Pympz(obj); } #endif else if (PyFloat_Check(obj)) { newob = Pympz_From_PyFloat(obj); } else if (Pyxmpz_Check(obj)) { newob = Pympz_From_Pyxmpz(obj); } else if (isDecimal(obj)) { PyObject *s = PyNumber_Long(obj); if (s) { newob = Pympz_From_PyLong(s); Py_DECREF(s); } } else if (isFraction(obj)) { temp = Pympq_From_Fraction(obj); if (temp) { newob = Pympq_To_Pympz((PyObject *)temp); Py_DECREF((PyObject*)temp); } } return newob; } static PyxmpzObject* Pyxmpz_From_Number(PyObject* obj) { PyxmpzObject* newob = NULL; PympqObject* temp = NULL; if (Pympz_Check(obj)) { newob = Pyxmpz_From_Pympz(obj); #ifdef PY2 } else if (PyInt_Check(obj)) { newob = Pyxmpz_From_PyInt(obj); #endif } else if (PyLong_Check(obj)) { newob = Pyxmpz_From_PyLong(obj); } else if (Pympq_Check(obj)) { newob = Pympq_To_Pyxmpz(obj); } #ifdef WITHMPFR else if (Pympfr_Check(obj)) { newob = Pympfr_To_Pyxmpz(obj); } #endif else if (PyFloat_Check(obj)) { newob = Pyxmpz_From_PyFloat(obj); } else if (Pyxmpz_Check(obj)) { newob = Pyxmpz_From_Pyxmpz(obj); } else if (isDecimal(obj)) { PyObject *s = PyNumber_Long(obj); if (s) { newob = Pyxmpz_From_PyLong(s); Py_DECREF(s); } } else if (isFraction(obj)) { temp = Pympq_From_Fraction(obj); if (temp) { newob = Pympq_To_Pyxmpz((PyObject *)temp); Py_DECREF((PyObject*)temp); } } return newob; } /* Convert an Integer-like object (as determined by isInteger) to * a Pympz. Returns NULL and raises a TypeError if obj is not an * Integer-like object. */ static PympzObject* Pympz_From_Integer(PyObject* obj) { PympzObject* newob = 0; if (Pympz_Check(obj)) { Py_INCREF(obj); newob = (PympzObject*) obj; #ifdef PY2 } else if (PyInt_Check(obj)) { newob = Pympz_From_PyInt(obj); #endif } else if (PyLong_Check(obj)) { newob = Pympz_From_PyLong(obj); } else if (Pyxmpz_Check(obj)) { newob = Pympz_From_Pyxmpz(obj); } if (!newob) TYPE_ERROR("conversion error in Pympz_From_Integer"); return newob; } /* Convert an Integer-like object (as determined by isInteger) to a * C long or C unsigned long. */ static long clong_From_Integer(PyObject *obj) { if (PyIntOrLong_Check(obj)) { return PyLong_AsLong(obj); } else if (CHECK_MPZANY(obj)) { if (mpz_fits_slong_p(Pympz_AS_MPZ(obj))) { return (long)mpz_get_si(Pympz_AS_MPZ(obj)); } else { OVERFLOW_ERROR("overflow in clong_From_Integer"); return -1; } } TYPE_ERROR("conversion error in clong_From_Integer"); return -1; } /* * Convert an Integer-like object (as determined by isInteger) to * a mpir_si. On all platforms except 64-bit Windows, mpir_si is the same * as a C long. Returns -1 and raises OverflowError if the the number is * too large. Returns -1 and raises TypeError if obj was not an * Integer-like object. */ #ifndef _WIN64 /* Working with C long. */ static mpir_si SI_From_Integer(PyObject *obj) { if (PyLong_Check(obj)) { return PyLong_AsLong(obj); } #ifdef PY2 else if (PyInt_Check(obj)) { return PyInt_AsLong(obj); } #endif else if (CHECK_MPZANY(obj)) { if (mpz_fits_slong_p(Pympz_AS_MPZ(obj))) { return mpz_get_si(Pympz_AS_MPZ(obj)); } else { OVERFLOW_ERROR("overflow in SI_From_Integer"); return -1; } } TYPE_ERROR("conversion error in SI_From_Integer"); return -1; } /* Working with C unsigned long. */ static mpir_ui UI_From_Integer(PyObject *obj) { if (PyLong_Check(obj)) { return PyLong_AsUnsignedLong(obj); } #ifdef PY2 if (PyInt_Check(obj)) { long temp = PyInt_AsLong(obj); /* Create an OverflowError for negative values. */ if (temp < 0) { OVERFLOW_ERROR("can't convert negative value to unsigned int"); return (mpir_ui)-1; } return temp; } #endif else if (CHECK_MPZANY(obj)) { if (mpz_fits_ulong_p(Pympz_AS_MPZ(obj))) { return mpz_get_ui(Pympz_AS_MPZ(obj)); } else { OVERFLOW_ERROR("overflow in UI_From_Integer"); return (mpir_ui)-1; } } TYPE_ERROR("conversion error in UI_From_Integer"); return (mpir_ui)-1; } #define MP_BITCNT_FROM_INTEGER(obj) UI_From_Integer(obj) #define PyLong_AsSIAndOverflow(a,b) PyLong_AsLongAndOverflow(a,b) #else /* Working with C long long. Can also assume using > MPIR 2.5. */ static mpir_si SI_From_Integer(PyObject *obj) { if (PyLong_Check(obj)) { return PyLong_AsLongLong(obj); } #ifdef PY2 else if (PyInt_Check(obj)) { return (mpir_si)PyInt_AsLong(obj); } #endif else if (CHECK_MPZANY(obj)) { if (mpz_fits_si_p(Pympz_AS_MPZ(obj))) { return mpz_get_si(Pympz_AS_MPZ(obj)); } else { OVERFLOW_ERROR("overflow in SI_From_Integer"); return -1; } } TYPE_ERROR("conversion error in SI_From_Integer"); return -1; } static mpir_ui UI_From_Integer(PyObject *obj) { if (PyLong_Check(obj)) { /* Returns an OverflowError for negative values. */ return PyLong_AsUnsignedLongLong(obj); } #ifdef PY2 else if (PyInt_Check(obj)) { long temp = PyInt_AsLong(obj); /* Create an OverflowError for negative values. */ if (temp < 0) { OVERFLOW_ERROR("can't convert negative value to unsigned int"); return (mpir_ui)-1; } return (mpir_ui)temp; } #endif else if (CHECK_MPZANY(obj)) { if (mpz_fits_ui_p(Pympz_AS_MPZ(obj))) { return mpz_get_ui(Pympz_AS_MPZ(obj)); } else { OVERFLOW_ERROR("overflow in UI_From_Integer"); return (mpir_ui)-1; } } TYPE_ERROR("conversion error in UI_From_Integer"); return (mpir_ui)-1; } #define MP_BITCNT_FROM_INTEGER(obj) UI_From_Integer(obj) #define PyLong_AsSIAndOverflow(a,b) PyLong_AsLongLongAndOverflow(a,b) #endif /* * Convert an Integer-like object (as determined by isInteger) to * a Py_ssize_t. Returns -1 and raises OverflowError if the the number is * too large. Returns -1 and raises TypeError if obj was not an * Integer-like object. */ static Py_ssize_t ssize_t_From_Integer(PyObject *obj) { Py_ssize_t val; PyObject* temp; if (PyLong_Check(obj)) { return PyLong_AsSsize_t(obj); } #ifdef PY2 else if (PyInt_Check(obj)) { return PyInt_AsSsize_t(obj); } #endif else if (CHECK_MPZANY(obj)) { if (mpz_fits_slong_p(Pympz_AS_MPZ(obj))) { return (Py_ssize_t)mpz_get_si(Pympz_AS_MPZ(obj)); } else { /* This section should only be called on Win64. */ temp = mpz_get_PyLong(Pympz_AS_MPZ(obj)); if (!temp) { TYPE_ERROR("conversion error in ssize_t_From_Integer"); return -1; } else { val = PyLong_AsSsize_t(temp); Py_DECREF(temp); return val; } } } TYPE_ERROR("conversion error in ssize_t_From_Integer"); return -1; } /* * coerce any number to a mpz */ /* currently not in use */ #if 0 static int Pympz_convert_arg(PyObject *arg, PyObject **ptr) { PympzObject* newob = Pympz_From_Integer(arg); if (newob) { *ptr = (PyObject*)newob; return 1; } else { TYPE_ERROR("argument can not be converted to 'mpz'"); return 0; } } #endif /* str and repr implementations for mpz */ static PyObject * Pympz_To_Str(PympzObject *self) { /* base-10, no tag */ return Pympz_To_PyStr(self, 10, 0); } static PyObject * Pympz_To_Repr(PympzObject *self) { /* base-10, with tag */ return Pympz_To_PyStr(self, 10, 1); } /* str and repr implementations for xmpz */ static PyObject * Pyxmpz_To_Str(PyxmpzObject *self) { /* base-10, no tag */ return Pyxmpz_To_PyStr(self, 10, 0); } static PyObject * Pyxmpz_To_Repr(PyxmpzObject *self) { /* base-10, with tag */ return Pyxmpz_To_PyStr(self, 10, 1); } #ifdef PY2 static PympqObject * Pympq_From_PyInt(PyObject *self) { PympqObject *newob; if ((newob = (PympqObject*)Pympq_new())) mpq_set_si(newob->q, PyInt_AsLong(self), 1); return newob; } #endif static PympqObject * Pympq_From_Pympz(PyObject *self) { PympqObject *newob; if ((newob = (PympqObject*)Pympq_new())) mpq_set_z(newob->q, Pympz_AS_MPZ(self)); return newob; } static PympqObject * Pympq_From_Pyxmpz(PyObject * obj) { PympqObject *newob; if ((newob = (PympqObject*)Pympq_new())) mpq_set_z(newob->q, Pyxmpz_AS_MPZ(obj)); return newob; } static PympzObject * Pympq_To_Pympz(PyObject *self) { PympzObject *newob; if ((newob = (PympzObject*)Pympz_new())) mpz_set_q(newob->z, Pympq_AS_MPQ(self)); return newob; } static PyxmpzObject * Pympq_To_Pyxmpz(PyObject *self) { PyxmpzObject *newob; if ((newob = (PyxmpzObject*)Pyxmpz_new())) mpz_set_q(newob->z, Pympq_AS_MPQ(self)); return newob; } static PympqObject * Pympq_From_PyLong(PyObject *self) { PympqObject *newob; PyObject *temp = (PyObject*)Pympz_From_PyLong(self); if (!temp) return NULL; newob = Pympq_From_Pympz(temp); Py_DECREF(temp); return newob; } static PympqObject * Pympq_From_PyFloat(PyObject *self) { PympqObject *newob; if ((newob = (PympqObject*)Pympq_new())) { double d = PyFloat_AsDouble(self); if (Py_IS_NAN(d)) { Py_DECREF((PyObject*)newob); VALUE_ERROR("'mpq' does not support NaN"); return NULL; } if (Py_IS_INFINITY(d)) { Py_DECREF((PyObject*)newob); OVERFLOW_ERROR("'mpq' does not support Infinity"); return NULL; } mpq_set_d(newob->q, d); } return newob; } /* * mpq conversion from string includes from-binary (base-256 LSB string * of bytes) and 'true' from-string (bases 2 to 62; bases 8 and 16 are * special -- decorations of leading 0/0x are allowed (but not required). * For 'true-bases' 2..62 there is a '/' separator between numerator and * denominator (if none, just numerator!); decimal point NOT allowed. * * Added in gmpy 1.02: also support a string of the form '12.34', i.e., * WITH a decimal point and WITHOUT a slash * * Binary-form: 4-byte numerator length (upper bit set if <0), then * numerator (as above for mpz), then denominator (ditto). */ static PympqObject * Pympq_From_PyStr(PyObject *stringarg, int base) { PympqObject *newob; unsigned char *cp; Py_ssize_t len; int i; PyObject *ascii_str = NULL; mpz_t temp; long expt = 0; if (!(newob = (PympqObject*)Pympq_new())) return NULL; if (PyBytes_Check(stringarg)) { len = PyBytes_Size(stringarg); cp = (unsigned char*)PyBytes_AsString(stringarg); } else { ascii_str = PyUnicode_AsASCIIString(stringarg); if (!ascii_str) { VALUE_ERROR("string contains non-ASCII characters"); goto error; } len = PyBytes_Size(ascii_str); cp = (unsigned char*)PyBytes_AsString(ascii_str); } /* Don't allow NULL characters */ for (i=0; iq), (char*)cp, base)) { if (wheredot) *wheredot = '.'; /* Restore the exponent! */ if (whereexp && (base == 10)) *whereexp = '\0'; VALUE_ERROR("invalid digits"); goto error; } /* Process the exponent. */ digits = expt - digits; mpz_inoc(temp); if (digits < 0) { mpz_ui_pow_ui(mpq_denref(newob->q), 10, (unsigned long)(-digits)); } else { mpz_ui_pow_ui(temp, 10, (unsigned long)digits); mpz_mul(mpq_numref(newob->q), mpq_numref(newob->q), temp); mpz_set_ui(mpq_denref(newob->q), 1); } mpz_cloc(temp); mpq_canonicalize(newob->q); /* Restore the decimal point. */ *wheredot = '.'; /* Restore the exponent! */ if (whereexp && !whereslash && (base == 10)) *whereexp = '\0'; goto finish; } if (whereslash) *whereslash = 0; if (-1 == mpz_set_str(mpq_numref(newob->q), (char*)cp, base)) { if (whereslash) *whereslash = '/'; VALUE_ERROR("invalid digits"); goto error; } if (whereslash) { *whereslash = '/'; if (-1 == mpz_set_str(mpq_denref(newob->q), whereslash+1, base)) { VALUE_ERROR("invalid digits"); goto error; } if (0==mpz_sgn(mpq_denref(newob->q))) { ZERO_ERROR("zero denominator in 'mpq'"); goto error; } mpq_canonicalize(newob->q); } else { mpz_inoc(temp); if (expt < 0) { mpz_ui_pow_ui(mpq_denref(newob->q), 10, (unsigned long)(-expt)); } else { mpz_ui_pow_ui(temp, 10, (unsigned long)expt); mpz_mul(mpq_numref(newob->q), mpq_numref(newob->q), temp); mpz_set_ui(mpq_denref(newob->q), 1); } mpz_cloc(temp); mpq_canonicalize(newob->q); if (whereexp && (base == 10)) *whereexp = 'E'; } } finish: Py_XDECREF(ascii_str); return newob; error: Py_DECREF((PyObject*)newob); Py_XDECREF(ascii_str); return NULL; } static PyObject * Pympq_To_PyLong(PympqObject *self) { PyObject* result; PympzObject *temp = Pympq_To_Pympz((PyObject*)self); if (!temp) return NULL; result = Pympz_To_PyLong(temp); Py_DECREF((PyObject*)temp); return result; } #ifdef PY2 static PyObject * Pympq_To_PyInt(PympqObject *self) { PyObject* result; PympzObject *temp = Pympq_To_Pympz((PyObject*)self); if (!temp) return NULL; result = Pympz_To_PyIntOrLong(temp); Py_DECREF((PyObject*)temp); return result; } #endif static PyObject * Pympq_To_PyFloat(PympqObject *self) { double res = mpq_get_d(self->q); return PyFloat_FromDouble(res); } static int qden_1(mpq_t q) { return 0 == mpz_cmp_ui(mpq_denref(q),1); } static PyObject * Pympq_To_PyStr(PympqObject *self, int base, int option) { PyObject *result = 0, *numstr = 0, *denstr = 0; char buffer[50], *p; numstr = mpz_ascii(mpq_numref(self->q), base, 0); if (!numstr) return NULL; /* Check if denominator is 1 and no tag is requested. If so, just * return the numerator. */ if (!(option & 1) && qden_1(self->q)) return numstr; denstr = mpz_ascii(mpq_denref(self->q), base, 0); if (!denstr) { Py_DECREF(numstr); return NULL; } /* Build the format string. */ p = buffer; if (option & 1) { *(p++) = 'm'; *(p++) = 'p'; *(p++) = 'q'; *(p++) = '('; } #ifdef PY2 *(p++) = '%'; *(p++) = 's'; if (!mpz_fits_slong_p(mpq_numref(self->q))) *(p++) = 'L'; if (option & 1) *(p++) = ','; else *(p++) = '/'; *(p++) = '%'; *(p++) = 's'; if (!mpz_fits_slong_p(mpq_denref(self->q))) *(p++) = 'L'; if (option & 1) *(p++) = ')'; *(p++) = '\00'; result = PyString_FromFormat(buffer, PyString_AS_STRING(numstr), PyString_AS_STRING(denstr)); #else *(p++) = '%'; *(p++) = 'U'; if (option & 1) *(p++) = ','; else *(p++) = '/'; *(p++) = '%'; *(p++) = 'U'; if (option & 1) *(p++) = ')'; *(p++) = '\00'; result = PyUnicode_FromFormat(buffer, numstr, denstr); #endif Py_DECREF(numstr); Py_DECREF(denstr); return result; } /* NOTE: Pympq_From_DecimalRaw returns an invalid mpq object when attempting to * convert a NaN or inifinity. If the denominator is 0, then interpret * the numerator as: * -1: -Infinity * 0: Nan * 1: Infinity * * If the numerator is 0 and the denominator is negative, then the value * is -0. * * These conventions are not supported by GMP/MPIR, but are used by * MPFR. */ #if PY_VERSION_HEX < 0x03030000 static PympqObject* Pympq_From_DecimalRaw(PyObject* obj) { PympqObject *result; PyObject *d_exp, *d_int, *d_sign, *d_is_special; mpir_si exp; mpz_t temp; const char *string; if (!(result = (PympqObject*)Pympq_new())) return NULL; mpq_set_si(result->q, 0, 1); d_exp = PyObject_GetAttrString(obj, "_exp"); d_int = PyObject_GetAttrString(obj, "_int"); d_sign = PyObject_GetAttrString(obj, "_sign"); d_is_special = PyObject_GetAttrString(obj, "_is_special"); if (!d_exp || !d_int || !d_sign || !d_is_special) { SYSTEM_ERROR("Object does not appear to be Decimal"); goto error; } if (PyObject_IsTrue(d_is_special)) { string = Py2or3String_AsString(d_exp); if (string[0] == 'N' || string[0] == 'n') { mpz_set_si(mpq_denref(result->q), 0); goto okay; } if (string[0] == 'F') { if (PyObject_IsTrue(d_sign)) mpq_set_si(result->q, -1, 0); else mpq_set_si(result->q, 1, 0); goto okay; } SYSTEM_ERROR("Cannot convert Decimal to mpq"); goto error; } if (mpz_set_PyStr(mpq_numref(result->q), d_int, 10) == -1) { SYSTEM_ERROR("Cannot convert Decimal to mpq"); goto error; } exp = PyIntOrLong_AsSI(d_exp); if (exp == -1 && PyErr_Occurred()) { SYSTEM_ERROR("Decimal _exp is not valid or overflow occurred"); goto error; } mpz_inoc(temp); if (exp <= 0) mpz_ui_pow_ui(mpq_denref(result->q), 10, (mpir_ui)(-exp)); else { mpz_inoc(temp); mpz_ui_pow_ui(temp, 10, (mpir_ui)(exp)); mpz_mul(mpq_numref(result->q), mpq_numref(result->q), temp); mpz_cloc(temp); } mpq_canonicalize(result->q); /* For -0, we need a negative denominator. */ if (PyObject_IsTrue(d_sign)) { if (!mpz_cmp_si(mpq_numref(result->q), 0)) mpz_set_si(mpq_denref(result->q), -1); else mpz_mul_si(mpq_numref(result->q), mpq_numref(result->q), -1); } okay: Py_DECREF(d_exp); Py_DECREF(d_int); Py_DECREF(d_sign); Py_DECREF(d_is_special); return result; error: Py_XDECREF(d_exp); Py_XDECREF(d_int); Py_XDECREF(d_sign); Py_XDECREF(d_is_special); Py_DECREF((PyObject*)result); return NULL; } #else static PympqObject* Pympq_From_DecimalRaw(PyObject* obj) { PympqObject *result; PyObject *temp = NULL, *d_is_inf = NULL, *d_is_nan = NULL; PyObject *d_is_zero = NULL, *d_is_signed = NULL, *s = NULL; if (!(result = (PympqObject*)Pympq_new())) return NULL; d_is_inf = PyObject_GetAttrString(obj, "is_infinite"); d_is_nan = PyObject_GetAttrString(obj, "is_nan"); d_is_zero = PyObject_GetAttrString(obj, "is_zero"); d_is_signed = PyObject_GetAttrString(obj, "is_signed"); if (!d_is_inf || !d_is_nan || !d_is_zero || !d_is_signed) { SYSTEM_ERROR("Object does not appear to be Decimal"); goto error; } if (!(temp = PyObject_CallFunctionObjArgs(d_is_nan, NULL))) goto error; if (PyObject_IsTrue(temp)) { mpz_set_si(mpq_numref(result->q), 0); mpz_set_si(mpq_denref(result->q), 0); goto okay; } Py_DECREF(temp); if (!(temp = PyObject_CallFunctionObjArgs(d_is_inf, NULL))) goto error; if (PyObject_IsTrue(temp)) { Py_DECREF(temp); if (!(temp = PyObject_CallFunctionObjArgs(d_is_signed, NULL))) goto error; if (PyObject_IsTrue(temp)) { mpz_set_si(mpq_numref(result->q), -1); mpz_set_si(mpq_denref(result->q), 0); } else { mpz_set_si(mpq_numref(result->q), 1); mpz_set_si(mpq_denref(result->q), 0); } goto okay; } Py_DECREF(temp); if (!(temp = PyObject_CallFunctionObjArgs(d_is_zero, NULL))) goto error; if (PyObject_IsTrue(temp)) { Py_DECREF(temp); if (!(temp = PyObject_CallFunctionObjArgs(d_is_signed, NULL))) goto error; if (PyObject_IsTrue(temp)) { mpz_set_si(mpq_numref(result->q), 0); mpz_set_si(mpq_denref(result->q), -1); } else { mpz_set_si(mpq_numref(result->q), 0); mpz_set_si(mpq_denref(result->q), 1); } goto okay; } Py_DECREF(result); s = PyObject_Str(obj); if (s) { result = Pympq_From_PyStr(s, 10); Py_DECREF(s); } okay: Py_DECREF(temp); Py_DECREF(d_is_inf); Py_DECREF(d_is_nan); Py_DECREF(d_is_zero); Py_DECREF(d_is_signed); return result; error: Py_XDECREF(temp); Py_XDECREF(d_is_inf); Py_XDECREF(d_is_nan); Py_XDECREF(d_is_zero); Py_XDECREF(d_is_signed); Py_DECREF((PyObject*)result); return NULL; } #endif static PympqObject* Pympq_From_Decimal(PyObject* obj) { PympqObject *result; if ((result = Pympq_From_DecimalRaw(obj))) { if (!mpz_cmp_si(mpq_numref(result->q), 0)) { if (mpz_cmp_si(mpq_denref(result->q), 0) < 0) { VALUE_ERROR("'mpq' does not support -0"); goto error; } else if (mpz_cmp_si(mpq_denref(result->q), 0) == 0) { VALUE_ERROR("'mpq' does not support NaN"); goto error; } } else if (!mpz_cmp_si(mpq_denref(result->q), 0)) { OVERFLOW_ERROR("'mpq' does not support Infinity"); goto error; } } return result; error: Py_DECREF((PyObject*)result); return NULL; } static PympqObject* Pympq_From_Fraction(PyObject* obj) { PympqObject *result; PyObject *num, *den; if (!(result = (PympqObject*)Pympq_new())) return NULL; mpq_set_si(result->q, 0, 1); num = PyObject_GetAttrString(obj, "numerator"); den = PyObject_GetAttrString(obj, "denominator"); if (!num || !PyIntOrLong_Check(num) || !den || !PyIntOrLong_Check(den)) { SYSTEM_ERROR("Object does not appear to be Fraction"); Py_XDECREF(num); Py_XDECREF(den); Py_DECREF((PyObject*)result); return NULL; } mpz_set_PyIntOrLong(mpq_numref(result->q), num); mpz_set_PyIntOrLong(mpq_denref(result->q), den); Py_DECREF(num); Py_DECREF(den); return result; } static PympqObject* Pympq_From_Number(PyObject* obj) { PympqObject* newob = 0; if (Pympq_Check(obj)) { Py_INCREF(obj); newob = (PympqObject *) obj; } else if (Pympz_Check(obj)) { newob = Pympq_From_Pympz(obj); #ifdef PY2 } else if (PyInt_Check(obj)) { newob = Pympq_From_PyInt(obj); #endif } #ifdef WITHMPFR else if (Pympfr_Check(obj)) { newob = Pympfr_To_Pympq(obj); } #endif else if (PyFloat_Check(obj)) { newob = Pympq_From_PyFloat(obj); } else if (PyLong_Check(obj)) { newob = Pympq_From_PyLong(obj); } else if (Pyxmpz_Check(obj)) { newob = Pympq_From_Pyxmpz(obj); } else if (isDecimal(obj)) { newob = Pympq_From_Decimal(obj); } else if (isFraction(obj)) { newob = Pympq_From_Fraction(obj); } return newob; } /* Convert an integer or mpz to mpq. */ static PympqObject* Pympq_From_Rational(PyObject* obj) { PympqObject* newob = 0; if (Pympq_Check(obj)) { Py_INCREF(obj); newob = (PympqObject *) obj; } else if (Pympz_Check(obj)) { newob = Pympq_From_Pympz(obj); #ifdef PY2 } else if (PyInt_Check(obj)) { newob = Pympq_From_PyInt(obj); #endif } else if (PyLong_Check(obj)) { newob = Pympq_From_PyLong(obj); } else if (Pyxmpz_Check(obj)) { newob = Pympq_From_Pyxmpz(obj); } else if (isFraction(obj)) { newob = Pympq_From_Fraction(obj); } return newob; } /* * coerce any number to a mpq */ int Pympq_convert_arg(PyObject *arg, PyObject **ptr) { PympqObject* newob = Pympq_From_Number(arg); if (newob) { *ptr = (PyObject*)newob; return 1; } else { if (!PyErr_Occurred()) { TYPE_ERROR("argument can not be converted to 'mpq'"); } return 0; } } /* str and repr implementations for mpq */ static PyObject * Pympq_To_Str(PympqObject *self) { /* base-10, no tag */ return Pympq_To_PyStr(self, 10, 0); } static PyObject * Pympq_To_Repr(PympqObject *self) { /* base-10, with tag */ return Pympq_To_PyStr(self, 10, 1); } #ifdef WITHMPFR /* Functions that operate strictly on mpfr. */ /* Make a copy of an mpfr object. If bits is 0, the new object will have * the same precision as the original object. If the requested precision * is less than the precision of the original object, the new object * will be rounded to requested precision using the current rounding mode. */ static PympfrObject * Pympfr_From_Pympfr(PyObject *self, mpfr_prec_t bits) { PympfrObject *result; if (bits == 0) bits = mpfr_get_prec(Pympfr_AS_MPFR(self)); if ((result = (PympfrObject*)Pympfr_new(bits))) { result->rc = mpfr_set(result->f, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); } return result; } static PympfrObject * Pympfr_From_PyFloat(PyObject *self, mpfr_prec_t bits) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(bits))) { result->rc = mpfr_set_d(result->f, PyFloat_AS_DOUBLE(self), context->ctx.mpfr_round); } return result; } static PympfrObject * Pympfr_From_Pympz(PyObject *self, mpfr_prec_t bits) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(bits))) { result->rc = mpfr_set_z(result->f, Pympz_AS_MPZ(self), context->ctx.mpfr_round); } return result; } #define Pympfr_From_Pyxmpz Pympfr_From_Pympz static PympzObject * Pympfr_To_Pympz(PyObject *self) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) { if (mpfr_nan_p(Pympfr_AS_MPFR(self))) { Py_DECREF((PyObject*)result); VALUE_ERROR("'mpz' does not support NaN"); return NULL; } if (mpfr_inf_p(Pympfr_AS_MPFR(self))) { Py_DECREF((PyObject*)result); OVERFLOW_ERROR("'mpz' does not support Infinity"); return NULL; } /* return code is ignored */ mpfr_get_z(result->z, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); } return result; } static PyxmpzObject * Pympfr_To_Pyxmpz(PyObject *self) { PyxmpzObject *result; if ((result = (PyxmpzObject*)Pyxmpz_new())) { if (mpfr_nan_p(Pympfr_AS_MPFR(self))) { Py_DECREF((PyObject*)result); VALUE_ERROR("'xmpz' does not support NaN"); return NULL; } if (mpfr_inf_p(Pympfr_AS_MPFR(self))) { Py_DECREF((PyObject*)result); OVERFLOW_ERROR("'xmpz' does not support Infinity"); return NULL; } /* return code is ignored */ mpfr_get_z(result->z, Pympfr_AS_MPFR(self), context->ctx.mpfr_round); } return result; } /* Return the simpliest rational number that approximates 'self' to the * requested precision 'err'. If 'err' is negative, then the requested * precision is -2**abs(int(err)). If 'err' is NULL, then the requested * precision is -2**prec. If 'prec' is 0, then the requested precision is * the precision of 'self'. */ static PympqObject * stern_brocot(PympfrObject* self, PympfrObject *err, mpfr_prec_t prec, int mayz) { PympqObject *result = 0; int i, negative, errsign; mpfr_t f, al, a, r1[3], r2[3], minerr, curerr, newerr, temp; #define F2Q_PREC 20 if (mpfr_nan_p(self->f)) { VALUE_ERROR("Cannot convert NaN to a number."); return NULL; } if (mpfr_inf_p(self->f)) { OVERFLOW_ERROR("Cannot convert Infinity to a number."); return NULL; } if (prec == 0) prec = mpfr_get_prec(self->f); errsign = err ? mpfr_sgn(err->f) : 0; if (errsign < 0) prec = (mpfr_prec_t)(-mpfr_get_si(err->f, context->ctx.mpfr_round)); if (errsign <= 0 && (prec < 2 || prec > mpfr_get_prec(self->f))) { VALUE_ERROR("Requested precision out-of-bounds."); return NULL; } if (!(result = (PympqObject*)Pympq_new())) return NULL; mpfr_init2(minerr, F2Q_PREC); if (errsign <= 0) { mpfr_set_ui(minerr, 1, context->ctx.mpfr_round); mpfr_div_2si(minerr, minerr, prec, context->ctx.mpfr_round); } else { mpfr_set(minerr, err->f, context->ctx.mpfr_round); } mpfr_init2(f, prec); if (mpfr_sgn(self->f) < 0) { negative = 1; mpfr_abs(f, self->f, context->ctx.mpfr_round); } else { negative = 0; mpfr_set(f, self->f, context->ctx.mpfr_round); } mpfr_init2(al, prec); mpfr_set(al, f, context->ctx.mpfr_round); mpfr_init2(a, prec); mpfr_floor(a, al); mpfr_init2(temp, prec); for (i=0; i<3; ++i) { mpfr_init2(r1[i], prec); mpfr_init2(r2[i], prec); } mpfr_set_si(r1[0], 0, context->ctx.mpfr_round); mpfr_set_si(r1[1], 0, context->ctx.mpfr_round); mpfr_set_si(r1[2], 1, context->ctx.mpfr_round); mpfr_set_si(r2[0], 0, context->ctx.mpfr_round); mpfr_set_si(r2[1], 1, context->ctx.mpfr_round); mpfr_set(r2[2], a, context->ctx.mpfr_round); mpfr_init2(curerr, F2Q_PREC); mpfr_init2(newerr, F2Q_PREC); mpfr_reldiff(curerr, f, a, context->ctx.mpfr_round); while (mpfr_cmp(curerr, minerr) > 0) { mpfr_sub(temp, al, a, context->ctx.mpfr_round); mpfr_ui_div(al, 1, temp, context->ctx.mpfr_round); mpfr_floor(a, al); mpfr_swap(r1[0], r1[1]); mpfr_swap(r1[1], r1[2]); mpfr_mul(r1[2], r1[1], a, context->ctx.mpfr_round); mpfr_add(r1[2], r1[2], r1[0], context->ctx.mpfr_round); mpfr_swap(r2[0], r2[1]); mpfr_swap(r2[1], r2[2]); mpfr_mul(r2[2], r2[1], a, context->ctx.mpfr_round); mpfr_add(r2[2], r2[2], r2[0], context->ctx.mpfr_round); mpfr_div(temp, r2[2], r1[2], context->ctx.mpfr_round); mpfr_reldiff(newerr, f, temp, context->ctx.mpfr_round); if (mpfr_cmp(curerr, newerr) <= 0) { mpfr_swap(r1[1],r1[2]); mpfr_swap(r2[1],r2[2]); break; } mpfr_swap(curerr, newerr); } if (mayz && (mpfr_cmp_ui(r1[2],1) == 0)) { Py_DECREF((PyObject*)result); result = (PympqObject*)Pympz_new(); mpfr_get_z(Pympz_AS_MPZ(result), r2[2], context->ctx.mpfr_round); if (negative) mpz_neg(Pympz_AS_MPZ(result), Pympz_AS_MPZ(result)); } else { mpfr_get_z(mpq_numref(result->q), r2[2], context->ctx.mpfr_round); mpfr_get_z(mpq_denref(result->q), r1[2], context->ctx.mpfr_round); if (negative) mpz_neg(mpq_numref(result->q), mpq_numref(result->q)); } mpfr_clear(minerr); mpfr_clear(al); mpfr_clear(a); mpfr_clear(f); for (i=0; i<3; ++i) { mpfr_clear(r1[i]); mpfr_clear(r2[i]); } mpfr_clear(curerr); mpfr_clear(newerr); mpfr_clear(temp); return result; } static PympqObject * Pympfr_To_Pympq(PyObject *self) { return stern_brocot((PympfrObject*)self, 0, 0, 0); } static PympfrObject * Pympfr_From_Pympq(PyObject *self, mpfr_prec_t bits) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(bits))) result->rc = mpfr_set_q(result->f, Pympq_AS_MPQ(self), context->ctx.mpfr_round); return result; } static PympfrObject * Pympfr_From_PyLong(PyObject *self, mpfr_prec_t bits) { PympfrObject *result; PyObject *temp = (PyObject*)Pympz_From_PyLong(self); if (!temp) return NULL; result = Pympfr_From_Pympz(temp, bits); Py_DECREF(temp); return result; } #ifdef PY2 static PympfrObject * Pympfr_From_PyInt(PyObject *self, mpfr_prec_t bits) { PympfrObject *result; if ((result = (PympfrObject*)Pympfr_new(bits))) result->rc = mpfr_set_si(result->f, PyInt_AsLong(self), context->ctx.mpfr_round); return result; } static PyObject * Pympfr_To_PyInt(PympfrObject *self) { PyObject *result; PympzObject *temp = Pympfr_To_Pympz((PyObject*)self); if (!temp) return NULL; result = Pympz_To_PyIntOrLong(temp); Py_DECREF((PyObject*)temp); return result; } #endif static PympfrObject * Pympfr_From_PyStr(PyObject *s, int base, mpfr_prec_t bits) { PympfrObject *result; char *cp, *endptr; mpfr_prec_t prec; Py_ssize_t len; PyObject *ascii_str = NULL; if (PyBytes_Check(s)) { len = PyBytes_Size(s); cp = PyBytes_AsString(s); } else { ascii_str = PyUnicode_AsASCIIString(s); if (!ascii_str) { VALUE_ERROR("string contains non-ASCII characters"); return NULL; } len = PyBytes_Size(ascii_str); cp = PyBytes_AsString(ascii_str); } if (bits > 0) prec = bits; else prec = context->ctx.mpfr_prec; if (!(result = (PympfrObject*)Pympfr_new(prec))) { Py_XDECREF(ascii_str); return NULL; } /* delegate the rest to MPFR */ result->rc = mpfr_strtofr(result->f, cp, &endptr, base, context->ctx.mpfr_round); if (len != (Py_ssize_t)(endptr - cp)) { VALUE_ERROR("invalid digits"); Py_DECREF((PyObject*)result); Py_XDECREF(ascii_str); return NULL; } Py_XDECREF(ascii_str); return result; } static PyObject * Pympfr_To_PyLong(PympfrObject *self) { PyObject *result; PympzObject *temp = Pympfr_To_Pympz((PyObject*)self); if (!temp) return NULL; result = Pympz_To_PyLong(temp); Py_DECREF((PyObject*)temp); return result; } static PyObject * Pympfr_To_PyFloat(PympfrObject *self) { double res = mpfr_get_d(self->f, context->ctx.mpfr_round); return PyFloat_FromDouble(res); } static PyObject* Pympfr_To_PyStr(PympfrObject *self, int base, int digits) { PyObject *result; char *buffer; mpfr_exp_t the_exp; /* check arguments are valid */ assert(Pympfr_Check((PyObject*)self)); if (!((base >= 2) && (base <= 62))) { VALUE_ERROR("base must be in the interval 2 ... 62"); return NULL; } if ((digits < 0) || (digits == 1)) { VALUE_ERROR("digits must be 0 or >= 2"); return NULL; } /* Process special cases first */ if (!(mpfr_regular_p(self->f))) { if (mpfr_nan_p(self->f)) { return Py_BuildValue("(sii)", "nan", 0, 0); } else if (mpfr_inf_p(self->f) && !mpfr_signbit(self->f)) { return Py_BuildValue("(sii)", "inf", 0, 0); } else if (mpfr_inf_p(self->f) && mpfr_signbit(self->f)) { return Py_BuildValue("(sii)", "-inf", 0, 0); } /* 0 is not considered a 'regular" number */ else if (mpfr_signbit(self->f)) { return Py_BuildValue("(sii)", "-0", 0, mpfr_get_prec(self->f)); } else { return Py_BuildValue("(sii)", "0", 0, mpfr_get_prec(self->f)); } } /* obtain digits-string and exponent */ buffer = mpfr_get_str(0, &the_exp, base, digits, self->f, context->ctx.mpfr_round); if (!*buffer) { SYSTEM_ERROR("Internal error in Pympfr_To_PyStr"); return NULL; } result = Py_BuildValue("(sii)", buffer, the_exp, mpfr_get_prec(self->f)); mpfr_free_str(buffer); return result; } static PympfrObject * Pympfr_From_Decimal(PyObject* obj, mpfr_prec_t bits) { PympfrObject *result = (PympfrObject*)Pympfr_new(0); PympqObject *temp = Pympq_From_DecimalRaw(obj); if (!temp || !result) { Py_XDECREF((PyObject*)temp); Py_XDECREF((PyObject*)result); return NULL; } if (!mpz_cmp_si(mpq_numref(temp->q), 0)) { if (!mpz_cmp_si(mpq_denref(temp->q), 0)) { mpfr_set_nan(result->f); } else { mpfr_set_zero(result->f, mpz_sgn(mpq_denref(temp->q))); } } else if (!mpz_cmp_si(mpq_denref(temp->q), 0)) { if (mpz_cmp_si(mpq_numref(temp->q), 0) < 0) { mpfr_set_inf(result->f, -1); } else { mpfr_set_inf(result->f, 1); } } else { Py_DECREF((PyObject*)result); result = Pympfr_From_Pympq((PyObject*)temp, bits); } Py_DECREF((PyObject*)temp); return result; } /* * If obj is a Pympfr and bits is 0 or bits is the same as the precision of * obj, then a new reference is created. * * For all other numerical types with bits = 0, the conversion is rounded to * context->ctx.mpfr_prec. */ static PympfrObject * Pympfr_From_Real(PyObject* obj, mpfr_prec_t bits) { PympfrObject* newob = 0; PympqObject* temp = 0; if (Pympfr_CheckAndExp(obj)) { /* Handle the likely case where the exponent of the mpfr is still * valid in the current context. */ if (!bits || mpfr_get_prec(Pympfr_AS_MPFR(obj)) == bits) { newob = (PympfrObject*) obj; Py_INCREF(obj); } else { newob = Pympfr_From_Pympfr((PyObject*)obj, bits); } } else if (Pympfr_Check(obj)) { /* Handle the unlikely case where the exponent is no longer valid * and mpfr_check_range needs to be called. */ if (context->ctx.trap_expbound) { GMPY_EXPBOUND("exponent of existing 'mpfr' incompatible with current context"); return NULL; } if ((newob = (PympfrObject*)Pympfr_new(mpfr_get_prec(Pympfr_AS_MPFR(obj))))) { mpfr_set(newob->f, Pympfr_AS_MPFR(obj), context->ctx.mpfr_round); newob->round_mode = ((PympfrObject*)obj)->round_mode; newob->rc = ((PympfrObject*)obj)->rc; newob->rc = mpfr_check_range(newob->f, newob->rc, newob->round_mode); } } else if (PyFloat_Check(obj)) { newob = Pympfr_From_PyFloat(obj, bits); #ifdef PY2 } else if (PyInt_Check(obj)) { newob = Pympfr_From_PyInt(obj, bits); #endif } else if (Pympq_Check(obj)) { newob = Pympfr_From_Pympq(obj, bits); } else if (Pympz_Check(obj)) { newob = Pympfr_From_Pympz(obj, bits); } else if (PyLong_Check(obj)) { newob = Pympfr_From_PyLong(obj, bits); } else if (Pyxmpz_Check(obj)) { newob = Pympfr_From_Pyxmpz(obj, bits); } else if (isDecimal(obj)) { newob = Pympfr_From_Decimal(obj, bits); } else if (isFraction(obj)) { temp = Pympq_From_Fraction(obj); if (temp) { newob = Pympfr_From_Pympq((PyObject*)temp, bits); Py_DECREF((PyObject*)temp); } } if (!newob) TYPE_ERROR("object could not be converted to 'mpfr'"); return newob; } /* * coerce any number to a mpf */ int Pympfr_convert_arg(PyObject *arg, PyObject **ptr) { PympfrObject* newob = Pympfr_From_Real(arg, 0); if (newob) { *ptr = (PyObject*)newob; return 1; } else { TYPE_ERROR("argument can not be converted to 'mpfr'"); return 0; } } /* str and repr implementations for mpfr */ static PyObject * Pympfr_To_Str(PympfrObject *self) { PyObject *result, *temp; long precision; char fmtstr[60]; precision = (long)(log10(2) * (double)mpfr_get_prec(Pympfr_AS_MPFR(self))) + 2; sprintf(fmtstr, "{0:.%ldg}", precision); temp = Py_BuildValue("s", fmtstr); if (!temp) return NULL; result = PyObject_CallMethod(temp, "format", "O", self); Py_DECREF(temp); return result; } static PyObject * Pympfr_To_Repr(PympfrObject *self) { PyObject *result, *temp; long precision, bits; char fmtstr[60]; bits = mpfr_get_prec(Pympfr_AS_MPFR(self)); precision = (long)(log10(2) * (double)bits) + 2; if (mpfr_number_p(Pympfr_AS_MPFR(self)) && bits != DBL_MANT_DIG) sprintf(fmtstr, "mpfr('{0:.%ldg}',%ld)", precision, bits); else sprintf(fmtstr, "mpfr('{0:.%ldg}')", precision); temp = Py_BuildValue("s", fmtstr); if (!temp) return NULL; result = PyObject_CallMethod(temp, "format", "O", self); Py_DECREF(temp); return result; } #endif #ifdef WITHMPC static PympcObject * Pympc_From_Pympc(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; if (rprec == 0 || iprec == 0) mpc_get_prec2(&rprec, &iprec, Pympc_AS_MPC(self)); if ((result = (PympcObject*)Pympc_new(rprec, iprec))) mpc_set(result->c, Pympc_AS_MPC(self), GET_MPC_ROUND(context)); return result; } static PympcObject * Pympc_From_PyComplex(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; if ((result = (PympcObject*)Pympc_new(rprec, iprec))) mpc_set_d_d(result->c, PyComplex_RealAsDouble(self), PyComplex_ImagAsDouble(self), GET_MPC_ROUND(context)); return result; } static PympcObject * Pympc_From_Pympfr(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; if (!rprec) rprec = mpfr_get_prec(Pympfr_AS_MPFR(self)); if ((result = (PympcObject*)Pympc_new(rprec, iprec))) result->rc = mpc_set_fr(result->c, Pympfr_AS_MPFR(self), GET_MPC_ROUND(context)); return result; } static PympcObject * Pympc_From_PyFloat(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; if (!rprec) rprec = DBL_MANT_DIG; if ((result = (PympcObject*)Pympc_new(rprec, iprec))) result->rc = mpc_set_d(result->c, PyFloat_AS_DOUBLE(self), GET_MPC_ROUND(context)); return result; } static PyObject * Pympc_To_PyFloat(PyObject *self) { TYPE_ERROR("can't covert 'mpc' to 'float'"); return NULL; } PyDoc_STRVAR(doc_mpc_complex, "Convert 'mpc' to 'complex'."); static PyObject * Pympc_To_PyComplex(PyObject *self, PyObject *other) { double real = mpfr_get_d(mpc_realref(Pympc_AS_MPC(self)), GET_REAL_ROUND(context)); double imag = mpfr_get_d(mpc_imagref(Pympc_AS_MPC(self)), GET_IMAG_ROUND(context)); return PyComplex_FromDoubles(real, imag); } static PympcObject * Pympc_From_Pympz(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; if ((result = (PympcObject*)Pympc_new(rprec, iprec))) result->rc = mpc_set_z(result->c, Pympz_AS_MPZ(self), GET_MPC_ROUND(context)); return result; } #define Pympc_From_Pyxmpz Pympc_From_Pympz static PympcObject * Pympc_From_Pympq(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; if ((result = (PympcObject*)Pympc_new(rprec, iprec))) result->rc = mpc_set_q(result->c, Pympq_AS_MPQ(self), GET_MPC_ROUND(context)); return result; } static PympcObject * Pympc_From_PyLong(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; PyObject *temp = (PyObject*)Pympz_From_PyLong(self); if (!temp) return NULL; result = Pympc_From_Pympz(temp, rprec, iprec); Py_DECREF(temp); return result; } static PyObject * Pympc_To_PyLong(PyObject *self) { TYPE_ERROR("can't covert 'mpc' to 'long'"); return NULL; } #ifdef PY2 static PympcObject * Pympc_From_PyInt(PyObject *self, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *result; if ((result = (PympcObject*)Pympc_new(rprec, iprec))) result->rc = mpc_set_si(result->c, PyInt_AsLong(self), GET_MPC_ROUND(context)); return result; } static PyObject * Pympc_To_PyIntOrLong(PyObject *self) { TYPE_ERROR("can't covert 'mpc' to 'int'"); return NULL; } #endif /* Conversion to/from MPC * Python's string representation of a complex number differs from the format * used by MPC. Both MPC and Python surround the complex number with '(' and * ')' but Python adds a 'j' after the imaginary component and MPC requires a * space between the real and imaginery components. PyStr2Pympc tries to work * around the differences as follows reading two MPFR-compatible numbers from * the string and storing into the real and imaginary components respectively. */ static PympcObject * Pympc_From_PyStr(PyObject *s, int base, mpfr_prec_t rbits, mpfr_prec_t ibits) { PympcObject *newob; PyObject *ascii_str = NULL; Py_ssize_t len; char *cp, *unwind, *tempchar, *lastchar; int firstp = 0, lastp = 0, real_rc = 0, imag_rc = 0; if (PyBytes_Check(s)) { len = PyBytes_Size(s); cp = (char*)PyBytes_AsString(s); } else if (PyUnicode_Check(s)) { ascii_str = PyUnicode_AsASCIIString(s); if (!ascii_str) { VALUE_ERROR("string contains non-ASCII characters"); return NULL; } len = PyBytes_Size(ascii_str); cp = (char*)PyBytes_AsString(ascii_str); } else { TYPE_ERROR("string required for PyStr2Pympc"); return NULL; } if (!(newob = (PympcObject*)Pympc_new(rbits, ibits))) { Py_XDECREF(ascii_str); return NULL; } /* Don't allow NULL characters */ if (strlen(cp) != len) { VALUE_ERROR("string without NULL characters expected"); Py_DECREF((PyObject*)newob); Py_XDECREF(ascii_str); return NULL; } /* Get a pointer to the last valid character (ignoring trailing * whitespace.) */ lastchar = cp + len - 1; while (isspace(*lastchar)) lastchar--; /* Skip trailing ). */ if (*lastchar == ')') { lastp = 1; lastchar--; } /* Skip trailing j. */ if (*lastchar == 'j') lastchar--; /* Skip leading whitespace. */ while (isspace(*cp)) cp++; /* Skip a leading (. */ if (*cp == '(') { firstp = 1; cp++; } if (firstp != lastp) goto invalid_string; /* Read the real component first. */ unwind = cp; real_rc = mpfr_strtofr(mpc_realref(newob->c), cp, &tempchar, base, GET_REAL_ROUND(context)); /* Verify that at least one valid character was read. */ if (cp == tempchar) goto invalid_string; /* If the next character is a j, then the real component is 0 and * we just read the imaginary componenet. */ if (*tempchar == 'j') { mpfr_set_zero(mpc_realref(newob->c), +1); cp = unwind; } else { /* Read the imaginary component next. */ cp = tempchar; } imag_rc = mpfr_strtofr(mpc_imagref(newob->c), cp, &tempchar, base, GET_IMAG_ROUND(context)); if (cp == tempchar && tempchar > lastchar) goto valid_string; if (*tempchar != 'j' && *cp != ' ') goto invalid_string; if (tempchar <= lastchar) goto invalid_string; valid_string: Py_XDECREF(ascii_str); newob->rc = MPC_INEX(real_rc, imag_rc); return newob; invalid_string: VALUE_ERROR("invalid string in mpc()"); Py_DECREF((PyObject*)newob); Py_XDECREF(ascii_str); return NULL; } static PyObject * raw_mpfr_ascii(mpfr_t self, int base, int digits, int round) { PyObject *result; char *buffer; mpfr_exp_t the_exp; /* Process special cases first */ if (!(mpfr_regular_p(self))) { if (mpfr_nan_p(self)) { return Py_BuildValue("(sii)", "nan", 0, 0); } else if (mpfr_inf_p(self) && !mpfr_signbit(self)) { return Py_BuildValue("(sii)", "inf", 0, 0); } else if (mpfr_inf_p(self) && mpfr_signbit(self)) { return Py_BuildValue("(sii)", "-inf", 0, 0); } /* 0 is not considered a 'regular" number */ else if (mpfr_signbit(self)) { return Py_BuildValue("(sii)", "-0", 0, mpfr_get_prec(self)); } else { return Py_BuildValue("(sii)", "0", 0, mpfr_get_prec(self)); } } /* obtain digits-string and exponent */ buffer = mpfr_get_str(0, &the_exp, base, digits, self, round); if (!*buffer) { SYSTEM_ERROR("Internal error in raw_mpfr_ascii"); return NULL; } result = Py_BuildValue("(sii)", buffer, the_exp, mpfr_get_prec(self)); mpfr_free_str(buffer); return result; } static PyObject * Pympc_To_PyStr(PympcObject *self, int base, int digits) { PyObject *tempreal = 0, *tempimag = 0, *result; if (!((base >= 2) && (base <= 62))) { VALUE_ERROR("base must be in the interval 2 ... 62"); return NULL; } if ((digits < 0) || (digits == 1)) { VALUE_ERROR("digits must be 0 or >= 2"); return NULL; } tempreal = raw_mpfr_ascii(mpc_realref(self->c), base, digits, MPC_RND_RE(GET_MPC_ROUND(context))); tempimag = raw_mpfr_ascii(mpc_imagref(self->c), base, digits, MPC_RND_IM(GET_MPC_ROUND(context))); if (!tempreal || !tempimag) { Py_XDECREF(tempreal); Py_XDECREF(tempimag); return NULL; } result = Py_BuildValue("(NN)", tempreal, tempimag); if (!result) { Py_DECREF(tempreal); Py_DECREF(tempimag); } return result; } /* * If obj is a Pympc and rprec/iprec are 0/0 or the same as the precision of * obj, then a new reference is created. * * For all other numerical types with bits = 0, the conversion is rounded * according to the context. */ static PympcObject * Pympc_From_Complex(PyObject* obj, mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject* newob = 0; PympqObject* temp = 0; mpfr_prec_t pr = 0, pi = 0; int rr, ri, dr, di; if (Pympc_CheckAndExp(obj)) { /* Handle the likely case where the exponent of the mpc is still * valid in the current context. */ if (!rprec && !iprec) { Py_INCREF(obj); newob = (PympcObject*)obj; } else { mpc_get_prec2(&pr, &pi, Pympc_AS_MPC(obj)); if (rprec == pr && iprec == pi) { Py_INCREF(obj); newob = (PympcObject*)obj; } else { newob = Pympc_From_Pympc((PyObject*)obj, rprec, iprec); } } } else if (Pympc_Check(obj)) { /* Handle the unlikely case where the exponent is no longer * valid and mpfr_check_range needs to be called. */ if (context->ctx.trap_expbound) { GMPY_EXPBOUND("exponent of existing 'mpc' incompatible with current context"); return NULL; } /* Get the real and imaginary precisions. */ mpc_get_prec2(&pr, &pi, Pympc_AS_MPC(obj)); /* Get the real and imaginary inexact codes. */ rr = MPC_INEX_RE( ((PympcObject*)obj)->rc ); ri = MPC_INEX_IM( ((PympcObject*)obj)->rc ); /* Get the real and imaginary rounding modes. */ dr = MPC_RND_RE( ((PympcObject*)obj)->round_mode ); di = MPC_RND_IM( ((PympcObject*)obj)->round_mode ); if ((newob = (PympcObject*)Pympc_new(pr, pi))) { mpc_set(newob->c, Pympc_AS_MPC(obj), GET_MPC_ROUND(context)); newob->round_mode = ((PympcObject*)obj)->round_mode; rr = mpfr_check_range(mpc_realref(newob->c), rr, dr); ri = mpfr_check_range(mpc_imagref(newob->c), ri, di); newob->rc = MPC_INEX(rr, ri); } } else if (Pympfr_Check(obj)) { newob = Pympc_From_Pympfr((PyObject*)obj, rprec, iprec); } else if (PyFloat_Check(obj)) { newob = Pympc_From_PyFloat(obj, rprec, iprec); } else if (PyComplex_Check(obj)) { newob = Pympc_From_PyComplex(obj, rprec, iprec); #ifdef PY2 } else if (PyInt_Check(obj)) { newob = Pympc_From_PyInt(obj, rprec, iprec); #endif } else if (Pympq_Check(obj)) { newob = Pympc_From_Pympq(obj, rprec, iprec); } else if (Pympz_Check(obj)) { newob = Pympc_From_Pympz(obj, rprec, iprec); } else if (PyLong_Check(obj)) { newob = Pympc_From_PyLong(obj, rprec, iprec); } else if (Pyxmpz_Check(obj)) { newob = Pympc_From_Pyxmpz(obj, rprec, iprec); } else if (isDecimal(obj)) { PyObject *s = PyObject_Str(obj); if (s) { newob = Pympc_From_PyStr(s, 10, rprec, iprec); if (!newob) { Py_DECREF(s); return NULL; } Py_DECREF(s); } } else if (isFraction(obj)) { temp = Pympq_From_Fraction(obj); if (temp) { newob = Pympc_From_Pympq((PyObject *)temp, rprec, iprec); Py_DECREF((PyObject*)temp); } } return newob; } /* * coerce any number to a mpc */ int Pympc_convert_arg(PyObject *arg, PyObject **ptr) { PympcObject* newob = Pympc_From_Complex(arg, 0, 0); if (newob) { *ptr = (PyObject*)newob; return 1; } else { TYPE_ERROR("can't convert argument 'mpc'"); return 0; } } /* str and repr implementations for mpc */ static PyObject * Pympc_To_Str(PympcObject *self) { PyObject *result, *temp; mpfr_prec_t rbits, ibits; long rprec, iprec; char fmtstr[60]; mpc_get_prec2(&rbits, &ibits, Pympc_AS_MPC(self)); rprec = (long)(log10(2) * (double)rbits) + 2; iprec = (long)(log10(2) * (double)ibits) + 2; sprintf(fmtstr, "{0:.%ld.%ldg}", rprec, iprec); temp = Py_BuildValue("s", fmtstr); if (!temp) return NULL; result = PyObject_CallMethod(temp, "format", "O", self); Py_DECREF(temp); return result; } static PyObject * Pympc_To_Repr(PympcObject *self) { PyObject *result, *temp; mpfr_prec_t rbits, ibits; long rprec, iprec; char fmtstr[60]; mpc_get_prec2(&rbits, &ibits, Pympc_AS_MPC(self)); rprec = (long)(log10(2) * (double)rbits) + 2; iprec = (long)(log10(2) * (double)ibits) + 2; if (rbits != DBL_MANT_DIG || ibits !=DBL_MANT_DIG) sprintf(fmtstr, "mpc('{0:.%ld.%ldg}',(%ld,%ld))", rprec, iprec, rbits, ibits); else sprintf(fmtstr, "mpc('{0:.%ld.%ldg}')", rprec, iprec); temp = Py_BuildValue("s", fmtstr); if (!temp) return NULL; result = PyObject_CallMethod(temp, "format", "O", self); Py_DECREF(temp); return result; } #endif gmpy2-2.0.7/src/gmpy_context.h0000666000000000000000000001353012542614506014747 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_context.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_CONTEXT_H #define GMPY_CONTEXT_H #ifdef __cplusplus extern "C" { #endif typedef struct { mpfr_prec_t mpfr_prec; /* current precision in bits, for MPFR */ mpfr_rnd_t mpfr_round; /* current rounding mode for float (MPFR) */ mpfr_exp_t emax; /* maximum exponent */ mpfr_exp_t emin; /* minimum exponent */ int subnormalize; /* if 1, subnormalization is performed */ int underflow; /* did an underflow occur? */ int overflow; /* did an overflow occur? */ int inexact; /* was the result inexact? */ int invalid; /* invalid operation (i.e. NaN)? */ int erange; /* did a range error occur? */ int divzero; /* divided by zero? */ int trap_underflow; /* if 1, raise exception for underflow */ int trap_overflow; /* if 1, raise exception for overflow */ int trap_inexact; /* if 1, raise exception for inexact */ int trap_invalid; /* if 1, raise exception for invalid (NaN) */ int trap_erange; /* if 1, raise exception for range error */ int trap_divzero; /* if 1, raise exception for divide by zero */ int trap_expbound; /* if 1, raise exception if mpfr/mpc exponents */ /* are out of bounds */ #ifdef WITHMPC mpfr_prec_t real_prec; /* current precision in bits, for Re(MPC) */ mpfr_prec_t imag_prec; /* current precision in bits, for Im(MPC) */ mpfr_rnd_t real_round; /* current rounding mode for Re(MPC) */ mpfr_rnd_t imag_round; /* current rounding mode for Im(MPC) */ int allow_complex; /* if 1, allow mpfr functions to return an mpc */ #endif } gmpy_context; typedef struct { PyObject_HEAD gmpy_context ctx; } GMPyContextObject; typedef struct { PyObject_HEAD gmpy_context new_ctx; /* Context that will be returned when __enter__ * is called. */ gmpy_context old_ctx; /* Context that will restored when __exit__ is * is called. */ } GMPyContextManagerObject; static PyTypeObject GMPyContext_Type; static PyTypeObject GMPyContextManager_Type; #define GMPyContext_Check(v) (((PyObject*)v)->ob_type == &GMPyContext_Type) #define GMPyContextManager_Check(v) (((PyObject*)v)->ob_type == &GMPyContextManager_Type) #define GET_MPFR_PREC(c) (c->ctx.mpfr_prec) #define GET_REAL_PREC(c) ((c->ctx.real_prec==GMPY_DEFAULT)?GET_MPFR_PREC(c):c->ctx.real_prec) #define GET_IMAG_PREC(c) ((c->ctx.imag_prec==GMPY_DEFAULT)?GET_REAL_PREC(c):c->ctx.imag_prec) #define GET_MPFR_ROUND(c) (c->ctx.mpfr_round) #define GET_REAL_ROUND(c) ((c->ctx.real_round==GMPY_DEFAULT)?GET_MPFR_ROUND(c):c->ctx.real_round) #define GET_IMAG_ROUND(c) ((c->ctx.imag_round==GMPY_DEFAULT)?GET_REAL_ROUND(c):c->ctx.imag_round) #define GET_MPC_ROUND(c) (MPC_RND(GET_REAL_ROUND(c), GET_IMAG_ROUND(c))) static PyObject * GMPyContextManager_new(void); static void GMPyContextManager_dealloc(GMPyContextManagerObject *self); static PyObject * GMPyContextManager_repr(GMPyContextManagerObject *self); static PyObject * GMPyContextManager_enter(PyObject *self, PyObject *args); static PyObject * GMPyContextManager_exit(PyObject *self, PyObject *args); static PyObject * GMPyContext_new(void); static void GMPyContext_dealloc(GMPyContextObject *self); static PyObject * GMPyContext_repr(GMPyContextObject *self); static PyObject * GMPyContext_get_context(PyObject *self, PyObject *args); static PyObject * GMPyContext_local_context(PyObject *self, PyObject *args, PyObject *kwargs); static PyObject * GMPyContext_context(PyObject *self, PyObject *args, PyObject *kwargs); static PyObject * GMPyContext_set_context(PyObject *self, PyObject *other); static PyObject * GMPyContext_clear_flags(PyObject *self, PyObject *args); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_context.c0000666000000000000000000012111112542614506014735 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_context.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* A GMPyContextObject contains an instance of the C struct gmpy_context * and a PyObject* used to reference the enclosing instance when used as a * context manager in Python. * * gmpy2 uses a global pointer "context" to refer to the active * GMPyContextObject. * * WARNING: The context manager is not thread-safe. This may be fixed in a * future version. */ /* Create and delete Context objects. */ static PyObject * GMPyContext_new(void) { GMPyContextObject *result; if ((result = PyObject_New(GMPyContextObject, &GMPyContext_Type))) { result->ctx.mpfr_prec = DBL_MANT_DIG; result->ctx.mpfr_round = MPFR_RNDN; result->ctx.emax = MPFR_EMAX_DEFAULT; result->ctx.emin = MPFR_EMIN_DEFAULT; result->ctx.subnormalize = 0; result->ctx.underflow = 0; result->ctx.overflow = 0; result->ctx.inexact = 0; result->ctx.invalid = 0; result->ctx.erange = 0; result->ctx.divzero = 0; result->ctx.trap_underflow = 0; result->ctx.trap_overflow = 0; result->ctx.trap_inexact = 0; result->ctx.trap_invalid = 0; result->ctx.trap_erange = 0; result->ctx.trap_divzero = 0; result->ctx.trap_expbound = 0; #ifdef WITHMPC result->ctx.real_prec = -1; result->ctx.imag_prec = -1; result->ctx.real_round = -1; result->ctx.imag_round = -1; result->ctx.allow_complex = 0; #endif } return (PyObject*)result; }; static void GMPyContext_dealloc(GMPyContextObject *self) { PyObject_Del(self); }; PyDoc_STRVAR(doc_context_ieee, "ieee(bitwidth) -> context\n\n" "Return a new context corresponding to a standard IEEE floating point\n" "format. The currently supported precisions are 32, 64, and 128 bits."); static PyObject * GMPyContext_ieee(PyObject *self, PyObject *other) { long bitwidth; GMPyContextObject *result; bitwidth = PyIntOrLong_AsLong(other); if (bitwidth == -1 && PyErr_Occurred()) { TYPE_ERROR("ieee() requires 'int' argument"); return NULL; } if (bitwidth == 32) { result = (GMPyContextObject*)GMPyContext_new(); if (result) { result->ctx.subnormalize = 1; result->ctx.mpfr_prec = 24; result->ctx.emax = 128; result->ctx.emin = -148; } return (PyObject*)result; } else if (bitwidth == 64) { result = (GMPyContextObject*)GMPyContext_new(); if (result) { result->ctx.subnormalize = 1; result->ctx.mpfr_prec = 53; result->ctx.emax = 1024; result->ctx.emin = -1073; } return (PyObject*)result; } else if (bitwidth == 128) { result = (GMPyContextObject*)GMPyContext_new(); if (result) { result->ctx.subnormalize = 1; result->ctx.mpfr_prec = 113; result->ctx.emax = 16384; result->ctx.emin = -16493; } return (PyObject*)result; } else { VALUE_ERROR("bitwidth must be 32, 64, or 128"); return NULL; } } /* Create and delete ContextManager objects. */ static PyObject * GMPyContextManager_new(void) { return (PyObject*)PyObject_New(GMPyContextManagerObject, &GMPyContextManager_Type); }; static void GMPyContextManager_dealloc(GMPyContextManagerObject *self) { PyObject_Del(self); }; /* Helper function to convert to convert a rounding mode to a string. */ static PyObject * _round_to_name(int val) { if (val == MPFR_RNDN) return Py2or3String_FromString("RoundToNearest"); if (val == MPFR_RNDZ) return Py2or3String_FromString("RoundToZero"); if (val == MPFR_RNDU) return Py2or3String_FromString("RoundUp"); if (val == MPFR_RNDD) return Py2or3String_FromString("RoundDown"); if (val == MPFR_RNDA) return Py2or3String_FromString("RoundAwayZero"); if (val == GMPY_DEFAULT) return Py2or3String_FromString("Default"); return NULL; }; static PyObject * GMPyContext_repr(GMPyContextObject *self) { PyObject *format; PyObject *tuple; PyObject *result = NULL; int i = 0; #ifdef WITHMPC tuple = PyTuple_New(23); #else tuple = PyTuple_New(18); #endif if (!tuple) return NULL; #ifdef WITHMPC format = Py2or3String_FromString( "context(precision=%s, real_prec=%s, imag_prec=%s,\n" " round=%s, real_round=%s, imag_round=%s,\n" " emax=%s, emin=%s,\n" " subnormalize=%s,\n" " trap_underflow=%s, underflow=%s,\n" " trap_overflow=%s, overflow=%s,\n" " trap_inexact=%s, inexact=%s,\n" " trap_invalid=%s, invalid=%s,\n" " trap_erange=%s, erange=%s,\n" " trap_divzero=%s, divzero=%s,\n" " trap_expbound=%s,\n" " allow_complex=%s)" ); #else format = Py2or3String_FromString( "context(precision=%s,\n" " round=%s,\n" " emax=%s, emin=%s,\n" " subnormalize=%s,\n" " trap_underflow=%s, underflow=%s,\n" " trap_overflow=%s, overflow=%s,\n" " trap_inexact=%s, inexact=%s,\n" " trap_invalid=%s, invalid=%s,\n" " trap_erange=%s, erange=%s,\n" " trap_divzero=%s, divzero=%s,\n" " trap_expbound=%s)" ); #endif if (!format) { Py_DECREF(tuple); return NULL; } PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.mpfr_prec)); #ifdef WITHMPC if (self->ctx.real_prec == GMPY_DEFAULT) PyTuple_SET_ITEM(tuple, i++, Py2or3String_FromString("Default")); else PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.real_prec)); if (self->ctx.imag_prec == GMPY_DEFAULT) PyTuple_SET_ITEM(tuple, i++, Py2or3String_FromString("Default")); else PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.imag_prec)); #endif PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.mpfr_round)); #ifdef WITHMPC PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.real_round)); PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.imag_round)); #endif PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.emax)); PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.emin)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.subnormalize)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_underflow)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.underflow)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_overflow)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.overflow)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_inexact)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.inexact)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_invalid)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.invalid)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_erange)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.erange)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_divzero)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.divzero)); PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_expbound)); #ifdef WITHMPC PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.allow_complex)); #endif if (!PyErr_Occurred()) result = Py2or3String_Format(format, tuple); else SYSTEM_ERROR("internal error in GMPyContext_repr"); Py_DECREF(format); Py_DECREF(tuple); return result; }; static PyObject * GMPyContextManager_repr(GMPyContextManagerObject *self) { return Py_BuildValue("s", ""); } PyDoc_STRVAR(doc_get_context, "get_context() -> gmpy2 context\n\n" "Return a reference to the current context."); static PyObject * GMPyContext_get_context(PyObject *self, PyObject *args) { Py_INCREF((PyObject*)context); return (PyObject*)context; } PyDoc_STRVAR(doc_context_copy, "context.copy() -> gmpy2 context\n\n" "Return a copy of a context."); static PyObject * GMPyContext_context_copy(PyObject *self, PyObject *other) { GMPyContextObject *result; result = (GMPyContextObject*)GMPyContext_new(); result->ctx = ((GMPyContextObject*)self)->ctx; return (PyObject*)result; } PyDoc_STRVAR(doc_local_context, "local_context([context[,keywords]]) -> context manager\n\n" "Create a context manager object that will restore the current context\n" "when the 'with ...' block terminates. The temporary context for the\n" "'with ...' block is based on the current context if no context is\n" "specified. Keyword arguments are supported and will modify the\n" "temporary new context."); static PyObject * GMPyContext_local_context(PyObject *self, PyObject *args, PyObject *kwargs) { GMPyContextManagerObject *result; PyObject *local_args = args; int arg_context = 0; #ifdef WITHMPC static char *kwlist[] = { "precision", "real_prec", "imag_prec", "round", "real_round", "imag_round", "emax", "emin", "subnormalize", "trap_underflow", "trap_overflow", "trap_inexact", "trap_invalid", "trap_erange", "trap_divzero", "trap_expbound", "allow_complex", NULL }; #else static char *kwlist[] = { "precision", "round", "emax", "emin", "subnormalize", "trap_underflow", "trap_overflow", "trap_inexact", "trap_invalid", "trap_erange", "trap_divzero", "trap_expbound", NULL }; #endif if (PyTuple_GET_SIZE(args) == 1 && GMPyContext_Check(PyTuple_GET_ITEM(args, 0))) { arg_context = 1; if (!(local_args = PyTuple_New(0))) return NULL; } else if (PyTuple_GET_SIZE(args)) { VALUE_ERROR("local_context() only supports [context[,keyword]] arguments"); return NULL; } if (!(result = (GMPyContextManagerObject*)GMPyContextManager_new())) return NULL; if (arg_context) { result->new_ctx = ((GMPyContextObject*)PyTuple_GET_ITEM(args, 0))->ctx; } else { result->new_ctx = context->ctx; } result->old_ctx = context->ctx; #ifdef WITHMPC if (!(PyArg_ParseTupleAndKeywords(local_args, kwargs, "|llliiilliiiiiiiii", kwlist, &result->new_ctx.mpfr_prec, &result->new_ctx.real_prec, &result->new_ctx.imag_prec, &result->new_ctx.mpfr_round, &result->new_ctx.real_round, &result->new_ctx.imag_round, &result->new_ctx.emax, &result->new_ctx.emin, &result->new_ctx.subnormalize, &result->new_ctx.trap_underflow, &result->new_ctx.trap_overflow, &result->new_ctx.trap_inexact, &result->new_ctx.trap_invalid, &result->new_ctx.trap_erange, &result->new_ctx.trap_divzero, &result->new_ctx.trap_expbound, &result->new_ctx.allow_complex))) { #else if (!(PyArg_ParseTupleAndKeywords(local_args, kwargs, "|lilliiiiiiii", kwlist, &result->new_ctx.mpfr_prec, &result->new_ctx.mpfr_round, &result->new_ctx.emax, &result->new_ctx.emin, &result->new_ctx.subnormalize, &result->new_ctx.trap_underflow, &result->new_ctx.trap_overflow, &result->new_ctx.trap_inexact, &result->new_ctx.trap_invalid, &result->new_ctx.trap_erange, &result->new_ctx.trap_divzero, &result->new_ctx.trap_expbound))) { #endif VALUE_ERROR("invalid keyword arguments in local_context()"); goto error; } /* Sanity check for values. */ if (result->new_ctx.mpfr_prec < MPFR_PREC_MIN || result->new_ctx.mpfr_prec > MPFR_PREC_MAX) { VALUE_ERROR("invalid value for precision"); goto error; } #ifdef WITHMPC if (!(result->new_ctx.real_prec == GMPY_DEFAULT || (result->new_ctx.real_prec >= MPFR_PREC_MIN && result->new_ctx.real_prec <= MPFR_PREC_MAX))) { VALUE_ERROR("invalid value for real_prec"); goto error; } if (!(result->new_ctx.imag_prec == GMPY_DEFAULT || (result->new_ctx.imag_prec >= MPFR_PREC_MIN && result->new_ctx.imag_prec <= MPFR_PREC_MAX))) { VALUE_ERROR("invalid value for imag_prec"); goto error; } #endif if (!(result->new_ctx.mpfr_round == MPFR_RNDN || result->new_ctx.mpfr_round == MPFR_RNDZ || result->new_ctx.mpfr_round == MPFR_RNDU || result->new_ctx.mpfr_round == MPFR_RNDD || result->new_ctx.mpfr_round == MPFR_RNDA)) { VALUE_ERROR("invalid value for round"); goto error; } #ifdef WITHMPC if (result->new_ctx.mpfr_round == MPFR_RNDA) { /* Since RNDA is not supported for MPC, set the MPC rounding modes * to MPFR_RNDN. */ result->new_ctx.real_round = MPFR_RNDN; result->new_ctx.imag_round = MPFR_RNDN; } if (!(result->new_ctx.real_round == MPFR_RNDN || result->new_ctx.real_round == MPFR_RNDZ || result->new_ctx.real_round == MPFR_RNDU || result->new_ctx.real_round == MPFR_RNDD || result->new_ctx.real_round == GMPY_DEFAULT)) { VALUE_ERROR("invalid value for real_round"); goto error; } if (!(result->new_ctx.imag_round == MPFR_RNDN || result->new_ctx.imag_round == MPFR_RNDZ || result->new_ctx.imag_round == MPFR_RNDU || result->new_ctx.imag_round == MPFR_RNDD || result->new_ctx.imag_round == GMPY_DEFAULT)) { VALUE_ERROR("invalid value for imag_round"); goto error; } #endif if (!(result->new_ctx.emin < 0 && result->new_ctx.emax > 0)) { VALUE_ERROR("invalid values for emin and/or emax"); goto error; } if (mpfr_set_emin(result->new_ctx.emin)) { VALUE_ERROR("invalid value for emin"); goto error; } if (mpfr_set_emax(result->new_ctx.emax)) { VALUE_ERROR("invalid value for emax"); goto error; } if (arg_context) { Py_DECREF(local_args); } return (PyObject*)result; error: if (arg_context) { Py_DECREF(local_args); } Py_DECREF((PyObject*)result); return NULL; } #ifdef WITHMPC PyDoc_STRVAR(doc_context, "context() -> context manager\n\n" "Return a new context for controlling MPFR and MPC arithmetic. To load\n" "the new context, use set_context(). Options can only be specified as\n" "keyword arguments. \n\n" " precision: precision, in bits, of an MPFR result\n" " real_prec: precision, in bits, of Re(MPC)\n" " -1 implies use mpfr_prec\n" " imag_prec: precision, in bits, of Im(MPC)\n" " -1 implies use real_prec\n" " round: rounding mode for MPFR\n" " real_round: rounding mode for Re(MPC)\n" " -1 implies use mpfr_round\n" " imag_round: rounding mode for Im(MPC)\n" " -1 implies use real_round\n" " e_max: maximum allowed exponent\n" " e_min: minimum allowed exponent\n" " subnormalize: if True, subnormalized results can be returned\n" " trap_underflow: if True, raise exception for underflow\n" " if False, set underflow flag\n" " trap_overflow: if True, raise exception for overflow\n" " if False, set overflow flag and return Inf or -Inf\n" " trap_inexact: if True, raise exception for inexact result\n" " if False, set inexact flag\n" " trap_invalid: if True, raise exception for invalid operation\n" " if False, set invalid flag and return NaN\n" " trap_erange: if True, raise exception for range error\n" " if False, set erange flag\n" " trap_divzero: if True, raise exception for division by zero\n" " if False, set divzero flag and return Inf or -Inf\n" " trap_expbound: if True, raise exception when mpfr/mpc exponent\n" " no longer valid in current context\n" " if False, mpfr/mpc with exponent out-of-bounds\n" " will be coerced to either 0 or Infinity\n" " allow_complex: if True, allow mpfr functions to return mpc\n" " if False, mpfr functions cannot return an mpc\n"); #else PyDoc_STRVAR(doc_context, "context() -> context\n\n" "Return a new context for controlling MPFR arithmetic. To load the\n" "new context, use set_context(). Options can only be specified as\n" "keyword arguments. \n\n" " precision: precision, in bits, of an MPFR result\n" " round: rounding mode for MPFR\n" " e_max: maximum allowed exponent\n" " e_min: minimum allowed exponent\n" " subnormalize: if True, subnormalized results can be returned\n" " trap_underflow: if True, raise exception for underflow\n" " if False, set underflow flag\n" " trap_overflow: if True, raise exception for overflow\n" " if False, set overflow flag and return Inf or -Inf\n" " trap_inexact: if True, raise exception for inexact result\n" " if False, set inexact flag\n" " trap_invalid: if True, raise exception for invalid operation\n" " if False, set invalid flag and return NaN\n" " trap_erange: if True, raise exception for range error\n" " if False, set erange flag\n" " trap_divzero: if True, raise exception for division by zero\n" " if False, set divzero flag and return Inf or -Inf\n" " trap_expbound: if True, raise exception when mpfr/mpc exponent\n" " no longer valid in current context\n" " if False, mpfr/mpc with exponent out-of-bounds will\n" " coerced to either 0 or Infinity\n"); #endif static PyObject * GMPyContext_context(PyObject *self, PyObject *args, PyObject *kwargs) { GMPyContextObject *result; #ifdef WITHMPC static char *kwlist[] = { "precision", "real_prec", "imag_prec", "round", "real_round", "imag_round", "emax", "emin", "subnormalize", "trap_underflow", "trap_overflow", "trap_inexact", "trap_invalid", "trap_erange", "trap_divzero", "trap_expbound", "allow_complex", NULL }; #else static char *kwlist[] = { "precision", "round", "emax", "emin", "subnormalize", "trap_underflow", "trap_overflow", "trap_inexact", "trap_invalid", "trap_erange", "trap_divzero", "trap_expbound", NULL }; #endif if (PyTuple_GET_SIZE(args)) { VALUE_ERROR("context() only supports keyword arguments"); return NULL; } if (!(result = (GMPyContextObject*)GMPyContext_new())) return NULL; #ifdef WITHMPC if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|llliiilliiiiiiiii", kwlist, &result->ctx.mpfr_prec, &result->ctx.real_prec, &result->ctx.imag_prec, &result->ctx.mpfr_round, &result->ctx.real_round, &result->ctx.imag_round, &result->ctx.emax, &result->ctx.emin, &result->ctx.subnormalize, &result->ctx.trap_underflow, &result->ctx.trap_overflow, &result->ctx.trap_inexact, &result->ctx.trap_invalid, &result->ctx.trap_erange, &result->ctx.trap_divzero, &result->ctx.trap_expbound, &result->ctx.allow_complex))) { #else if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|lilliiiiiiii", kwlist, &result->ctx.mpfr_prec, &result->ctx.mpfr_round, &result->ctx.emax, &result->ctx.emin, &result->ctx.subnormalize, &result->ctx.trap_underflow, &result->ctx.trap_overflow, &result->ctx.trap_inexact, &result->ctx.trap_invalid, &result->ctx.trap_erange, &result->ctx.trap_divzero, &result->ctx.trap_expbound))) { #endif VALUE_ERROR("invalid keyword arguments in context()"); return NULL; } /* Sanity check for values. */ if (result->ctx.mpfr_prec < MPFR_PREC_MIN || result->ctx.mpfr_prec > MPFR_PREC_MAX) { Py_DECREF((PyObject*)result); VALUE_ERROR("invalid value for precision"); return NULL; } #ifdef WITHMPC if (!(result->ctx.real_prec == GMPY_DEFAULT || (result->ctx.real_prec >= MPFR_PREC_MIN && result->ctx.real_prec <= MPFR_PREC_MAX))) { Py_DECREF((PyObject*)result); VALUE_ERROR("invalid value for real_prec"); return NULL; } if (!(result->ctx.imag_prec == GMPY_DEFAULT || (result->ctx.imag_prec >= MPFR_PREC_MIN && result->ctx.imag_prec <= MPFR_PREC_MAX))) { Py_DECREF((PyObject*)result); VALUE_ERROR("invalid value for imag_prec"); return NULL; } #endif if (!(result->ctx.mpfr_round == MPFR_RNDN || result->ctx.mpfr_round == MPFR_RNDZ || result->ctx.mpfr_round == MPFR_RNDU || result->ctx.mpfr_round == MPFR_RNDD || result->ctx.mpfr_round == MPFR_RNDA)) { Py_DECREF((PyObject*)result); VALUE_ERROR("invalid value for round"); return NULL; } #ifdef WITHMPC if (result->ctx.mpfr_round == MPFR_RNDA) { /* Since RNDA is not supported for MPC, set the MPC rounding modes to MPFR_RNDN. */ result->ctx.real_round = MPFR_RNDN; result->ctx.imag_round = MPFR_RNDN; } if (!(result->ctx.real_round == MPFR_RNDN || result->ctx.real_round == MPFR_RNDZ || result->ctx.real_round == MPFR_RNDU || result->ctx.real_round == MPFR_RNDD || result->ctx.real_round == GMPY_DEFAULT)) { Py_DECREF((PyObject*)result); VALUE_ERROR("invalid value for real_round"); return NULL; } if (!(result->ctx.imag_round == MPFR_RNDN || result->ctx.imag_round == MPFR_RNDZ || result->ctx.imag_round == MPFR_RNDU || result->ctx.imag_round == MPFR_RNDD || result->ctx.imag_round == GMPY_DEFAULT)) { Py_DECREF((PyObject*)result); VALUE_ERROR("invalid value for imag_round"); return NULL; } #endif if (!(result->ctx.emin < 0 && result->ctx.emax > 0)) { VALUE_ERROR("invalid values for emin and/or emax"); Py_DECREF((PyObject*)result); return NULL; } if (mpfr_set_emin(result->ctx.emin)) { VALUE_ERROR("invalid value for emin"); Py_DECREF((PyObject*)result); return NULL; } if (mpfr_set_emax(result->ctx.emax)) { VALUE_ERROR("invalid value for emax"); Py_DECREF((PyObject*)result); return NULL; } result->ctx.underflow = 0; result->ctx.overflow = 0; result->ctx.inexact = 0; result->ctx.invalid = 0; result->ctx.erange = 0; result->ctx.divzero = 0; return (PyObject*)result; } PyDoc_STRVAR(doc_set_context, "set_context(context)\n\n" "Activate a context object controlling MPFR and MPC arithmetic.\n"); static PyObject * GMPyContext_set_context(PyObject *self, PyObject *other) { if (GMPyContext_Check(other)) { Py_INCREF((PyObject*)other); Py_DECREF((PyObject*)context); context = (GMPyContextObject*)other; mpfr_set_emin(context->ctx.emin); mpfr_set_emax(context->ctx.emax); Py_RETURN_NONE; } else { VALUE_ERROR("set_context() requires a context argument"); return NULL; } } static PyObject * GMPyContextManager_enter(PyObject *self, PyObject *args) { GMPyContextObject *result; if (!(result = (GMPyContextObject*)GMPyContext_new())) return NULL; result->ctx = ((GMPyContextManagerObject*)self)->new_ctx; Py_DECREF((PyObject*)context); context = (GMPyContextObject*)result; Py_INCREF((PyObject*)context); mpfr_set_emin(context->ctx.emin); mpfr_set_emax(context->ctx.emax); return (PyObject*)result; } static PyObject * GMPyContextManager_exit(PyObject *self, PyObject *args) { GMPyContextObject *result; if (!(result = (GMPyContextObject*)GMPyContext_new())) return NULL; result->ctx = ((GMPyContextManagerObject*)self)->old_ctx; Py_DECREF((PyObject*)context); context = (GMPyContextObject*)result; mpfr_set_emin(context->ctx.emin); mpfr_set_emax(context->ctx.emax); Py_RETURN_NONE; } static PyObject * GMPyContext_enter(PyObject *self, PyObject *args) { GMPyContextObject *result; if (!(result = (GMPyContextObject*)GMPyContext_new())) return NULL; result->ctx = ((GMPyContextObject*)self)->ctx; Py_DECREF((PyObject*)context); context = (GMPyContextObject*)result; Py_INCREF((PyObject*)context); mpfr_set_emin(context->ctx.emin); mpfr_set_emax(context->ctx.emax); return (PyObject*)result; } static PyObject * GMPyContext_exit(PyObject *self, PyObject *args) { Py_DECREF((PyObject*)context); context = (GMPyContextObject*)self; Py_INCREF((PyObject*)context); mpfr_set_emin(context->ctx.emin); mpfr_set_emax(context->ctx.emax); Py_RETURN_NONE; } PyDoc_STRVAR(doc_context_clear_flags, "clear_flags()\n\n" "Clear all MPFR exception flags."); static PyObject * GMPyContext_clear_flags(PyObject *self, PyObject *args) { ((GMPyContextObject*)self)->ctx.underflow = 0; ((GMPyContextObject*)self)->ctx.overflow = 0; ((GMPyContextObject*)self)->ctx.inexact = 0; ((GMPyContextObject*)self)->ctx.invalid = 0; ((GMPyContextObject*)self)->ctx.erange = 0; ((GMPyContextObject*)self)->ctx.divzero = 0; Py_RETURN_NONE; } /* Define the get/set functions. */ #define GETSET_BOOLEAN(NAME) \ static PyObject * \ GMPyContext_get_##NAME(GMPyContextObject *self, void *closure) \ { \ return PyBool_FromLong(self->ctx.NAME); \ }; \ static int \ GMPyContext_set_##NAME(GMPyContextObject *self, PyObject *value, void *closure) \ { \ if (!(PyBool_Check(value))) { \ TYPE_ERROR(#NAME " must be True or False"); \ return -1; \ } \ self->ctx.NAME = (value == Py_True) ? 1 : 0; \ return 0; \ } GETSET_BOOLEAN(subnormalize); GETSET_BOOLEAN(underflow); GETSET_BOOLEAN(overflow); GETSET_BOOLEAN(inexact); GETSET_BOOLEAN(invalid); GETSET_BOOLEAN(erange); GETSET_BOOLEAN(divzero); GETSET_BOOLEAN(trap_underflow); GETSET_BOOLEAN(trap_overflow); GETSET_BOOLEAN(trap_inexact); GETSET_BOOLEAN(trap_invalid); GETSET_BOOLEAN(trap_erange); GETSET_BOOLEAN(trap_divzero); GETSET_BOOLEAN(trap_expbound); #ifdef WITHMPC GETSET_BOOLEAN(allow_complex) #endif static PyObject * GMPyContext_get_precision(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromSsize_t((Py_ssize_t)(self->ctx.mpfr_prec)); } static int GMPyContext_set_precision(GMPyContextObject *self, PyObject *value, void *closure) { Py_ssize_t temp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("precision must be Python integer"); return -1; } temp = PyIntOrLong_AsSsize_t(value); if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX || PyErr_Occurred()) { VALUE_ERROR("invalid value for precision"); return -1; } self->ctx.mpfr_prec = (mpfr_prec_t)temp; return 0; } #ifdef WITHMPC static PyObject * GMPyContext_get_real_prec(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromSsize_t((Py_ssize_t)(GET_REAL_PREC(self))); } static int GMPyContext_set_real_prec(GMPyContextObject *self, PyObject *value, void *closure) { Py_ssize_t temp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("real_prec must be Python integer"); return -1; } temp = PyIntOrLong_AsSsize_t(value); if (temp == -1) { if (PyErr_Occurred()) { VALUE_ERROR("invalid value for real_prec"); return -1; } } else if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) { VALUE_ERROR("invalid value for real_prec"); return -1; } self->ctx.real_prec = (mpfr_prec_t)temp; return 0; } static PyObject * GMPyContext_get_imag_prec(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromSsize_t((Py_ssize_t)(GET_IMAG_PREC(self))); } static int GMPyContext_set_imag_prec(GMPyContextObject *self, PyObject *value, void *closure) { Py_ssize_t temp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("imag_prec must be Python integer"); return -1; } temp = PyIntOrLong_AsSsize_t(value); if (temp == -1) { if (PyErr_Occurred()) { VALUE_ERROR("invalid value for imag_prec"); return -1; } } else if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) { VALUE_ERROR("invalid value for imag_prec"); return -1; } self->ctx.imag_prec = (mpfr_prec_t)temp; return 0; } #endif static PyObject * GMPyContext_get_round(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromLong((long)(self->ctx.mpfr_round)); } static int GMPyContext_set_round(GMPyContextObject *self, PyObject *value, void *closure) { long temp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("round mode must be Python integer"); return -1; } temp = PyIntOrLong_AsLong(value); if (temp == -1 && PyErr_Occurred()) { VALUE_ERROR("invalid value for round mode"); return -1; } if (temp == MPFR_RNDN) self->ctx.mpfr_round = MPFR_RNDN; else if (temp == MPFR_RNDZ) self->ctx.mpfr_round = MPFR_RNDZ; else if (temp == MPFR_RNDU) self->ctx.mpfr_round = MPFR_RNDU; else if (temp == MPFR_RNDD) self->ctx.mpfr_round = MPFR_RNDD; else if (temp == MPFR_RNDA) { self->ctx.mpfr_round = MPFR_RNDA; #ifdef WITHMPC /* Since RNDA is not supported for MPC, set the MPC rounding modes to MPFR_RNDN. */ self->ctx.real_round = MPFR_RNDN; self->ctx.imag_round = MPFR_RNDN; #endif } else { VALUE_ERROR("invalid value for round mode"); return -1; } return 0; } #ifdef WITHMPC static PyObject * GMPyContext_get_real_round(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromLong((long)GET_REAL_ROUND(self)); } static int GMPyContext_set_real_round(GMPyContextObject *self, PyObject *value, void *closure) { long temp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("round mode must be Python integer"); return -1; } temp = PyIntOrLong_AsLong(value); if (temp == -1 && PyErr_Occurred()) { VALUE_ERROR("invalid value for round mode"); return -1; } if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ || temp == MPFR_RNDU || temp == MPFR_RNDD) { self->ctx.real_round = (int)temp; } else { VALUE_ERROR("invalid value for round mode"); return -1; } return 0; } static PyObject * GMPyContext_get_imag_round(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromLong((long)GET_IMAG_ROUND(self)); } static int GMPyContext_set_imag_round(GMPyContextObject *self, PyObject *value, void *closure) { long temp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("round mode must be Python integer"); return -1; } temp = PyIntOrLong_AsLong(value); if (temp == -1 && PyErr_Occurred()) { VALUE_ERROR("invalid value for round mode"); return -1; } if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ || temp == MPFR_RNDU || temp == MPFR_RNDD) { self->ctx.imag_round = (int)temp; } else { VALUE_ERROR("invalid value for round mode"); return -1; } return 0; } #endif static PyObject * GMPyContext_get_emin(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromLong(self->ctx.emin); } static int GMPyContext_set_emin(GMPyContextObject *self, PyObject *value, void *closure) { long exp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("emin must be Python integer"); return -1; } exp = PyIntOrLong_AsLong(value); if (exp == -1 && PyErr_Occurred()) { VALUE_ERROR("requested minimum exponent is invalid"); return -1; } if (mpfr_set_emin((mpfr_prec_t)exp)) { VALUE_ERROR("requested minimum exponent is invalid"); return -1; } self->ctx.emin = exp; mpfr_set_emin(exp); return 0; } static PyObject * GMPyContext_get_emax(GMPyContextObject *self, void *closure) { return PyIntOrLong_FromLong(self->ctx.emax); } static int GMPyContext_set_emax(GMPyContextObject *self, PyObject *value, void *closure) { long exp; if (!(PyIntOrLong_Check(value))) { TYPE_ERROR("emax must be Python integer"); return -1; } exp = PyIntOrLong_AsLong(value); if (exp == -1 && PyErr_Occurred()) { VALUE_ERROR("requested maximum exponent is invalid"); return -1; } if (mpfr_set_emax((mpfr_prec_t)exp)) { VALUE_ERROR("requested maximum exponent is invalid"); return -1; } self->ctx.emax = exp; mpfr_set_emax(exp); return 0; } #define ADD_GETSET(NAME) \ {#NAME, \ (getter)GMPyContext_get_##NAME, \ (setter)GMPyContext_set_##NAME, NULL, NULL} static PyGetSetDef GMPyContext_getseters[] = { ADD_GETSET(precision), #ifdef WITHMPC ADD_GETSET(real_prec), ADD_GETSET(imag_prec), #endif ADD_GETSET(round), #ifdef WITHMPC ADD_GETSET(real_round), ADD_GETSET(imag_round), #endif ADD_GETSET(emax), ADD_GETSET(emin), ADD_GETSET(subnormalize), ADD_GETSET(underflow), ADD_GETSET(overflow), ADD_GETSET(inexact), ADD_GETSET(invalid), ADD_GETSET(erange), ADD_GETSET(divzero), ADD_GETSET(trap_underflow), ADD_GETSET(trap_overflow), ADD_GETSET(trap_inexact), ADD_GETSET(trap_invalid), ADD_GETSET(trap_erange), ADD_GETSET(trap_divzero), ADD_GETSET(trap_expbound), #ifdef WITHMPC ADD_GETSET(allow_complex), #endif {NULL} }; static PyMethodDef GMPyContext_methods[] = { { "clear_flags", GMPyContext_clear_flags, METH_NOARGS, doc_context_clear_flags }, { "copy", GMPyContext_context_copy, METH_NOARGS, doc_context_copy }, { "__enter__", GMPyContext_enter, METH_NOARGS, NULL }, { "__exit__", GMPyContext_exit, METH_VARARGS, NULL }, { NULL, NULL, 1 } }; static PyTypeObject GMPyContext_Type = { #ifdef PY3 PyVarObject_HEAD_INIT(0, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "gmpy2 context", /* tp_name */ sizeof(GMPyContextObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) GMPyContext_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) GMPyContext_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "GMPY2 Context Object", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ GMPyContext_methods, /* tp_methods */ 0, /* tp_members */ GMPyContext_getseters, /* tp_getset */ }; static PyMethodDef GMPyContextManager_methods[] = { { "__enter__", GMPyContextManager_enter, METH_NOARGS, NULL }, { "__exit__", GMPyContextManager_exit, METH_VARARGS, NULL }, { NULL, NULL, 1 } }; static PyTypeObject GMPyContextManager_Type = { #ifdef PY3 PyVarObject_HEAD_INIT(0, 0) #else PyObject_HEAD_INIT(0) 0, /* ob_size */ #endif "gmpy2 context", /* tp_name */ sizeof(GMPyContextManagerObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) GMPyContextManager_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc) GMPyContextManager_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "GMPY2 Context manager", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ GMPyContextManager_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ }; gmpy2-2.0.7/src/gmpy_cache.h0000666000000000000000000000704512542614506014332 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_cache.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* gmpy2 caches objects so they can be reused quickly without involving a new * memory allocation or object construction. There are two different types of * object caches used in gmpy2. * * "zcache" is used to cache mpz_t objects. The cache is accessed via the * functions mpz_inoc/mpz_cloc. The function set_zcache is used to change * the size of the array used to store the cached objects. * * The "py???cache" is used to cache Py??? objects. The cache is accessed * via Py???_new/Py???_dealloc. The functions set_py???cache and * set_py???cache are used to change the size of the array used to the store * the cached objects. */ #ifndef GMPY_CACHE_H #define GMPY_CACHE_H #ifdef __cplusplus extern "C" { #endif static void set_zcache(void); static void mpz_inoc(mpz_t newo); static void mpz_cloc(mpz_t oldo); static void set_pympzcache(void); static PyObject * Pympz_new(void); static void Pympz_dealloc(PympzObject *self); static void set_pyxmpzcache(void); static PyObject * Pyxmpz_new(void); static void Pyxmpz_dealloc(PyxmpzObject *self); static void set_pympqcache(void); static PyObject * Pympq_new(void); static void Pympq_dealloc(PympqObject *self); #ifdef WITHMPFR static void set_pympfrcache(void); static PyObject * Pympfr_new(mpfr_prec_t bits); static void Pympfr_dealloc(PympfrObject *self); #endif #ifdef WITHMPC static void set_pympccache(void); static PyObject * Pympc_new(mpfr_prec_t rprec, mpfr_prec_t iprec); static void Pympc_dealloc(PympcObject *self); #endif #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_cache.c0000666000000000000000000002457212542614506014331 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_cache.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* gmpy2 caches objects so they can be reused quickly without involving a new * memory allocation or object construction. There are two different types of * object caches used in gmpy2. * * "zcache" is used to cache mpz_t objects. The cache is accessed via the * functions mpz_inoc/mpz_cloc. The function set_zcache is used to change * the size of the array used to store the cached objects. * * The "py???cache" is used to cache Py??? objects. The cache is accessed * via Py???_new/Py???_dealloc. The functions set_py???cache and * set_py???cache are used to change the size of the array used to the store * the cached objects. */ static void set_zcache(void) { if (in_zcache > global.cache_size) { int i; for(i = global.cache_size; i < in_zcache; ++i) mpz_clear(zcache[i]); in_zcache = global.cache_size; } zcache = GMPY_REALLOC(zcache, sizeof(mpz_t) * global.cache_size); } static void mpz_inoc(mpz_t newo) { if (in_zcache) { newo[0] = (zcache[--in_zcache])[0]; } else { mpz_init(newo); } } static void mpz_cloc(mpz_t oldo) { if (in_zcache_mp_alloc <= global.cache_obsize) { (zcache[in_zcache++])[0] = oldo[0]; } else { mpz_clear(oldo); } } /* Caching logic for Pympz. */ static void set_pympzcache(void) { if (in_pympzcache > global.cache_size) { int i; for (i = global.cache_size; i < in_pympzcache; ++i) { mpz_cloc(pympzcache[i]->z); PyObject_Del(pympzcache[i]); } in_pympzcache = global.cache_size; } pympzcache = GMPY_REALLOC(pympzcache, sizeof(PympzObject)*global.cache_size); } static PyObject * Pympz_new(void) { PympzObject *self; if (in_pympzcache) { self = pympzcache[--in_pympzcache]; /* Py_INCREF does not set the debugging pointers, so need to use * _Py_NewReference instead. */ _Py_NewReference((PyObject*)self); } else { if (!(self = PyObject_New(PympzObject, &Pympz_Type))) return NULL; mpz_inoc(self->z); } self->hash_cache = -1; return (PyObject*)self; } static void Pympz_dealloc(PympzObject *self) { if (in_pympzcache < global.cache_size && self->z->_mp_alloc <= global.cache_obsize) { pympzcache[in_pympzcache++] = self; } else { mpz_cloc(self->z); PyObject_Del(self); } } /* Caching logic for Pyxmpz. */ static void set_pyxmpzcache(void) { if (in_pyxmpzcache > global.cache_size) { int i; for (i = global.cache_size; i < in_pyxmpzcache; ++i) { mpz_cloc(pyxmpzcache[i]->z); PyObject_Del(pyxmpzcache[i]); } in_pyxmpzcache = global.cache_size; } pyxmpzcache = GMPY_REALLOC(pyxmpzcache, sizeof(PyxmpzObject)*global.cache_size); } static PyObject * Pyxmpz_new(void) { PyxmpzObject *self; if (in_pyxmpzcache) { self = pyxmpzcache[--in_pyxmpzcache]; /* Py_INCREF does not set the debugging pointers, so need to use * _Py_NewReference instead. */ _Py_NewReference((PyObject*)self); } else { if (!(self = PyObject_New(PyxmpzObject, &Pyxmpz_Type))) return NULL; mpz_inoc(self->z); } return (PyObject*)self; } static void Pyxmpz_dealloc(PyxmpzObject *self) { if (in_pyxmpzcache < global.cache_size && self->z->_mp_alloc <= global.cache_obsize) { pyxmpzcache[in_pyxmpzcache++] = self; } else { mpz_cloc(self->z); PyObject_Del(self); } } /* Caching logic for Pympq. */ static void set_pympqcache(void) { if (in_pympqcache > global.cache_size) { int i; for (i = global.cache_size; i < in_pympqcache; ++i) { mpq_clear(pympqcache[i]->q); PyObject_Del(pympqcache[i]); } in_pympqcache = global.cache_size; } pympqcache = GMPY_REALLOC(pympqcache, sizeof(PympqObject)*global.cache_size); } static PyObject * Pympq_new(void) { PympqObject *self; if (in_pympqcache) { self = pympqcache[--in_pympqcache]; /* Py_INCREF does not set the debugging pointers, so need to use _Py_NewReference instead. */ _Py_NewReference((PyObject*)self); } else { if (!(self = PyObject_New(PympqObject, &Pympq_Type))) return NULL; mpq_init(self->q); } self->hash_cache = -1; return (PyObject*)self; } static void Pympq_dealloc(PympqObject *self) { if (in_pympqcacheq)->_mp_alloc <= global.cache_obsize && mpq_denref(self->q)->_mp_alloc <= global.cache_obsize) { pympqcache[in_pympqcache++] = self; } else { mpq_clear(self->q); PyObject_Del(self); } } #ifdef WITHMPFR /* Caching logic for Pympfr. */ static void set_pympfrcache(void) { if (in_pympfrcache > global.cache_size) { int i; for (i = global.cache_size; i < in_pympfrcache; ++i) { mpfr_clear(pympfrcache[i]->f); PyObject_Del(pympfrcache[i]); } in_pympfrcache = global.cache_size; } pympfrcache = GMPY_REALLOC(pympfrcache, sizeof(PympfrObject)*global.cache_size); } static PyObject * Pympfr_new(mpfr_prec_t bits) { PympfrObject *self; if (!bits) bits = context->ctx.mpfr_prec; if (bits < MPFR_PREC_MIN || bits > MPFR_PREC_MAX) { VALUE_ERROR("invalid value for precision"); return NULL; } if (in_pympfrcache) { self = pympfrcache[--in_pympfrcache]; /* Py_INCREF does not set the debugging pointers, so need to use _Py_NewReference instead. */ _Py_NewReference((PyObject*)self); mpfr_set_prec(self->f, bits); } else { if (!(self = PyObject_New(PympfrObject, &Pympfr_Type))) return NULL; mpfr_init2(self->f, bits); } self->hash_cache = -1; self->rc = 0; self->round_mode = context->ctx.mpfr_round; return (PyObject*)self; } static void Pympfr_dealloc(PympfrObject *self) { size_t msize; /* Calculate the number of limbs in the mantissa. */ msize = (self->f->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb; if (in_pympfrcache < global.cache_size && msize <= (size_t)global.cache_obsize) { pympfrcache[in_pympfrcache++] = self; } else { mpfr_clear(self->f); PyObject_Del(self); } } #endif #ifdef WITHMPC static void set_pympccache(void) { if (in_pympccache > global.cache_size) { int i; for (i = global.cache_size; i < in_pympccache; ++i) { mpc_clear(pympccache[i]->c); PyObject_Del(pympccache[i]); } in_pympccache = global.cache_size; } pympccache = GMPY_REALLOC(pympccache, sizeof(PympcObject)*global.cache_size); } static PyObject * Pympc_new(mpfr_prec_t rprec, mpfr_prec_t iprec) { PympcObject *self; if (!rprec) rprec = GET_REAL_PREC(context); if (!iprec) iprec = GET_IMAG_PREC(context); if (rprec < MPFR_PREC_MIN || rprec > MPFR_PREC_MAX || iprec < MPFR_PREC_MIN || iprec > MPFR_PREC_MAX) { VALUE_ERROR("invalid value for precision"); return NULL; } if (in_pympccache) { self = pympccache[--in_pympccache]; /* Py_INCREF does not set the debugging pointers, so need to use _Py_NewReference instead. */ _Py_NewReference((PyObject*)self); if (rprec == iprec) { mpc_set_prec(self->c, rprec); } else { mpc_clear(self->c); mpc_init3(self->c, rprec, iprec); } } else { if (!(self = PyObject_New(PympcObject, &Pympc_Type))) return NULL; mpc_init3(self->c, rprec, iprec); } self->hash_cache = -1; self->rc = 0; self->round_mode = GET_MPC_ROUND(context); return (PyObject*)self; } static void Pympc_dealloc(PympcObject *self) { size_t msize; /* Calculate the number of limbs in the mantissa. */ msize = (mpc_realref(self->c)->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb; msize += (mpc_imagref(self->c)->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb; if (in_pympccache < global.cache_size && msize <= (size_t)global.cache_obsize) { pympccache[in_pympccache++] = self; } else { mpc_clear(self->c); PyObject_Del(self); } } #endif gmpy2-2.0.7/src/gmpy_binary.h0000666000000000000000000000572412542614506014555 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_binary.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_BINARY_H #define GMPY_BINARY_H #ifdef __cplusplus extern "C" { #endif /* Conversion routines between GMPY2 objects and a compact, portable * binary representation. The binary format of GMPY2 is not compatible * with GMPY 1.x. Methods to read the old format are provided. */ static PyObject * Pympz_From_Old_Binary(PyObject *self, PyObject *other); static PyObject * Pympq_From_Old_Binary(PyObject *self, PyObject *other); static PyObject * Pympany_From_Binary(PyObject *self, PyObject *other); static PyObject * Pympz_To_Binary(PympzObject *self); static PyObject * Pyxmpz_To_Binary(PyxmpzObject *self); static PyObject * Pympq_To_Binary(PympqObject *self); #ifdef WITHMPFR static PyObject * Pympfr_From_Old_Binary(PyObject *self, PyObject *other); static PyObject * Pympfr_To_Binary(PympfrObject *self); #endif #ifdef WITHMPC static PyObject * Pympc_To_Binary(PympcObject *self); #endif #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_binary.c0000666000000000000000000011622312542614506014545 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_binary.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Conversion routines between GMPY2 objects and a compact, portable * binary representation. The binary format of GMPY2 is not compatible * with GMPY 1.x. Methods to read the old format are provided. */ /* Provide functions to access the old binary formats. */ PyDoc_STRVAR(doc_g_mpz_from_old_binary, "mpz_from_old_binary(string) -> mpz\n\n" "Return an 'mpz' from a GMPY 1.x binary format."); static PyObject * Pympz_From_Old_Binary(PyObject *self, PyObject *other) { unsigned char *cp; Py_ssize_t len; int negative = 0; PympzObject *result; if (!(PyBytes_Check(other))) { TYPE_ERROR("mpz_from_old_binary() requires bytes argument"); return NULL; } if (!(result = (PympzObject*)Pympz_new())) return NULL; len = PyBytes_Size(other); cp = (unsigned char*)PyBytes_AsString(other); if (cp[len-1] == 0xFF) { negative = 1; --len; } mpz_import(result->z, len, -1, sizeof(char), 0, 0, cp); if (negative) mpz_neg(result->z, result->z); return (PyObject*)result; } PyDoc_STRVAR(doc_g_mpq_from_old_binary, "mpq_from_old_binary(string) -> mpq\n\n" "Return an 'mpq' from a GMPY 1.x binary format."); static PyObject * Pympq_From_Old_Binary(PyObject *self, PyObject *other) { unsigned char *cp; Py_ssize_t len; int topper, negative, numlen; mpz_t numerator, denominator; PympqObject *result; if (!(PyBytes_Check(other))) { TYPE_ERROR("mpq_from_old_binary() requires bytes argument"); return NULL; } if (!(result = (PympqObject*)Pympq_new())) return NULL; len = PyBytes_Size(other); cp = (unsigned char*)PyBytes_AsString(other); if (len < 6) { VALUE_ERROR("invalid mpq binary (too short)"); Py_DECREF((PyObject*)result); return NULL; } topper = cp[3] & 0x7f; negative = cp[3] & 0x80; numlen = cp[0] + 256 * (cp[1] + 256 * (cp[2] + 256 * topper)); if (len < (4 + numlen + 1)) { VALUE_ERROR("invalid mpq binary (num len)"); Py_DECREF((PyObject*)result); return NULL; } mpz_inoc(numerator); mpz_inoc(denominator); mpz_import(numerator, numlen, -1, sizeof(char), 0, 0, cp+4); mpz_import(denominator, len-4-numlen, -1, sizeof(char), 0, 0, cp+4+numlen); if (negative) mpz_neg(numerator, numerator); mpq_set_num(result->q, numerator); mpq_set_den(result->q, denominator); mpq_canonicalize(result->q); mpz_cloc(numerator); mpz_cloc(denominator); return (PyObject*)result; } #ifdef WITHMPFR PyDoc_STRVAR(doc_g_mpfr_from_old_binary, "mpfr_from_old_binary(string) -> mpfr\n\n" "Return an 'mpfr' from a GMPY 1.x binary mpf format."); static PyObject * Pympfr_From_Old_Binary(PyObject *self, PyObject *other) { unsigned char *cp; Py_ssize_t len; PympfrObject *result; mpfr_t digit; mpfr_prec_t prec; int i, codebyte, resusign, exposign, resuzero, precilen; unsigned int expomag = 0; if (!(PyBytes_Check(other))) { TYPE_ERROR("mpfr_from_old_binary() requires bytes argument"); return NULL; } len = PyBytes_Size(other); cp = (unsigned char*)PyBytes_AsString(other); if (len == 1) { prec = 0; } else { prec = (mpfr_prec_t)(8 * (len - 5)); if ((len>=5) && (cp[0]&8)) { prec = 0; for (i=4; i>0; --i) { prec = (prec << 8) | cp[i]; } } } /* * binary format for MP floats: first, a code-byte, then, a LSB * 4-byte unsigned int (exponent magnitude), then the "mantissa" * (actually, "significand", but "mantissa" is the usual term...) * in MSB form. * * The codebyte encodes both the signs, exponent and result, or * also the zeroness of the result (in which case, nothing more). */ codebyte = cp[0]; resusign = codebyte & 1; exposign = codebyte & 2; resuzero = codebyte & 4; precilen = (codebyte & 8)?4:0; /* mpfr zero has a very compact (1-byte) binary encoding!-) */ if (resuzero) { if (!(result = (PympfrObject*)Pympfr_new(prec))) return NULL; result->rc = mpfr_set_ui(result->f, 0, context->ctx.mpfr_round); return (PyObject*)result; } /* all other numbers are 6+ bytes: codebyte, 4-byte exp, 1+ * bytes for the mantissa; check this string is 6+ bytes */ if (len < 6 + precilen) { VALUE_ERROR("invalid mpf binary encoding (too short)"); return NULL; } if (!(result = (PympfrObject*)Pympfr_new(prec))) return NULL; /* reconstruct exponent */ for (i = 4 + precilen; i > precilen; --i) { expomag = (expomag<<8) | cp[i]; } /* reconstruct 'mantissa' (significand) */ mpfr_set_si(result->f, 0, context->ctx.mpfr_round); mpfr_init2(digit, prec); for (i = 5 + precilen; ictx.mpfr_round); mpfr_div_2ui(digit, digit, (unsigned long)((i-4-precilen) * 8), context->ctx.mpfr_round); mpfr_add(result->f, result->f, digit, context->ctx.mpfr_round); } mpfr_clear(digit); /* apply exponent, with its appropriate sign */ if (exposign) mpfr_div_2ui(result->f, result->f, 8*expomag, context->ctx.mpfr_round); else mpfr_mul_2ui(result->f, result->f, 8*expomag, context->ctx.mpfr_round); /* apply significand-sign (sign of the overall number) */ if (resusign) mpfr_neg(result->f, result->f, context->ctx.mpfr_round); return (PyObject*)result; } #endif /* Format of the binary representation of an mpz/xmpz. * * byte[0]: 1 => mpz * 2 => xmpz * 3 => mpq (see Pympq_To_Binary) * 4 => mpfr (see Pympfr_To_Binary) * 5 => mpc (see Pympc_To_Binary) * byte[1:0-1]: 0 => value is 0 * 1 => value is > 0 * 2 => value is < 0 * 3 => unassigned * byte[2]+: value */ static PyObject * Pympz_To_Binary(PympzObject *self) { size_t size = 2; int sgn; char *buffer; PyObject *result; sgn = mpz_sgn(self->z); if (sgn == 0) { TEMP_ALLOC(buffer, size); buffer[0] = 0x01; buffer[1] = 0x00; goto done; } size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2; TEMP_ALLOC(buffer, size); buffer[0] = 0x01; if (sgn > 0) buffer[1] = 0x01; else buffer[1] = 0x02; mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z); done: result = PyBytes_FromStringAndSize(buffer, size); TEMP_FREE(buffer, size); return result; } static PyObject * Pyxmpz_To_Binary(PyxmpzObject *self) { size_t size = 2; int sgn; char *buffer; PyObject *result; sgn = mpz_sgn(self->z); if (sgn == 0) { TEMP_ALLOC(buffer, size); buffer[0] = 0x02; buffer[1] = 0x00; goto done; } size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2; TEMP_ALLOC(buffer, size); buffer[0] = 0x02; if (sgn > 0) buffer[1] = 0x01; else buffer[1] = 0x02; mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z); done: result = PyBytes_FromStringAndSize(buffer, size); TEMP_FREE(buffer, size); return result; } /* Format of the binary representation of an mpq. * * byte[0]: 1 => mpz (see Pympz_To_Binary) * 2 => xmpz (see Pyxmpz_To_Binary) * 3 => mpq * 4 => mpfr (see Pympfr_To_Binary) * 5 => mpc (see Pympc_To_Binary) * byte[1:0-1]: 0 => value is 0 * 1 => value is > 0 * 2 => value is < 0 * 3 => unassigned * byte[1:2-2]: 0 => 32-bit length (n=4) * 1 => 64-bit length (n=8) * byte[2+]: numerator length, using either 4 or 8 bytes * byte[2+n]+: numerator, followed by denominator */ static PyObject * Pympq_To_Binary(PympqObject *self) { size_t sizenum, sizeden, sizesize = 4, size = 2, sizetemp, i; size_t count = 0; int sgn; char *buffer, large = 0x00; PyObject *result = 0; sgn = mpq_sgn(self->q); if (sgn == 0) { TEMP_ALLOC(buffer, size); buffer[0] = 0x03; buffer[1] = 0x00; goto done; } sizenum = (mpz_sizeinbase(mpq_numref(self->q), 2) + 7) / 8; sizeden = (mpz_sizeinbase(mpq_denref(self->q), 2) + 7) / 8; size = sizenum + sizeden + 2; /* Check if sizenum larger than 32 bits. */ if ((sizenum >> 16) >> 16) { large = 0x04; sizesize = 8; } size += sizesize; TEMP_ALLOC(buffer, size); buffer[0] = 0x03; if (sgn > 0) buffer[1] = 0x01 | large; else buffer[1] = 0x02 | large; /* Copy sizenum to the buffer. */ sizetemp = sizenum; for (i=0; i>= 8; } mpz_export(buffer+sizesize+2, &count, -1, sizeof(char), 0, 0, mpq_numref(self->q)); if (count != sizenum) { SYSTEM_ERROR("internal error in Pympq_To_Binary"); TEMP_FREE(buffer, size); return NULL; } count = 0; mpz_export(buffer+sizenum+sizesize+2, &count, -1, sizeof(char), 0, 0, mpq_denref(self->q)); if (count != sizeden) { SYSTEM_ERROR("internal error in Pympq_To_Binary"); TEMP_FREE(buffer, size); return NULL; } done: result = PyBytes_FromStringAndSize(buffer, size); TEMP_FREE(buffer, size); return result; } #ifdef WITHMPFR /* Format of the binary representation of an mpfr. * * byte[0]: 1 => mpz (see Pympz_To_Binary) * 2 => xmpz (see Pyxmpz_To_Binary) * 3 => mpq (see Pympq_To_Binary) * 4 => mpfr * 5 => mpc (see Pympc_To_Binary) * byte[1:0]: 0 => value is "special" * 1 => value is an actual number * byte[1:1]: 0 => signbit is clear * 1 => signbit is set * byte[1:2-2]: 0 => 32-bit lengths (n=4) * 1 => 64-bit lengths (n=8) * byte[1:3-4]: 0 => 0 (see signbit) * 1 => value is NaN * 2 => value is Inf (see signbit) * 3 => unassigned * byte[1:5]: 0 => exponent is positive * 1 => exponent is negative * byte[1:6]: 0 => 4 byte limbs * 1 => 8 byte limbs * byte[2]: 0 => rc = 0 * 1 => rc > 0 * 2 => rc < 0 * byte[3]: mpfr.round_mode * byte[4]+: precision, saved in 4 or 8 bytes * byte[4+n]+: exponent, saved in 4 or 8 bytes * byte[4+2n]+: mantissa */ static PyObject * Pympfr_To_Binary(PympfrObject *self) { size_t sizemant = 0, sizesize = 4, size = 4, sizetemp, i; mp_limb_t templimb; mpfr_prec_t precision; mpfr_exp_t exponent = 0; int sgn; char *buffer, *cp, large = 0x00, expsgn = 0x00; PyObject *result = 0; /* Check if the precision, exponent and mantissa length can fit in * 32 bits. */ sgn = mpfr_signbit(self->f); precision = mpfr_get_prec(self->f); /* Exponent and mantiss are only valid for regular numbers * (not 0, Nan, Inf, -Inf). */ if (mpfr_regular_p(self->f)) { exponent = self->f->_mpfr_exp; if (exponent < 0) { exponent = -exponent; expsgn = 0x20; } /* Calculate the size of mantissa in limbs */ sizemant = (self->f->_mpfr_prec + mp_bits_per_limb - 1)/mp_bits_per_limb; } if (((exponent >> 16) >> 16) || ((precision >> 16) >> 16) || ((sizemant >> 16) >> 16)) { sizesize = 8; large = 0x04; } if (!mpfr_regular_p(self->f)) { /* Only need to save the precision. */ size += sizesize; TEMP_ALLOC(buffer, size); buffer[0] = 0x04; /* Set to all 0 since we are special. */ buffer[1] = 0x00; /* Set the sign bit. */ if (sgn) buffer[1] |= 0x02; /* 4 or 8 byte values. */ buffer[1] |= large; /* Check if NaN. */ if (mpfr_nan_p(self->f)) buffer[1] |= 0x08; /* Check if Infinity. */ if (mpfr_inf_p(self->f)) buffer[1] |= 0x10; /* Save the result code */ if (self->rc == 0) buffer[2] = 0x00; else if (self->rc > 0) buffer[2] = 0x01; else buffer[2] = 0x02; /* Save the rounding mode active when the mpfr was created. */ buffer[3] = (char)(self->round_mode); /* Save the precision */ sizetemp = precision; for (i=0; i>= 8; } goto done; } /* Now process all actual numbers. */ size += (2 * sizesize) + (sizemant * (mp_bits_per_limb >> 3)); TEMP_ALLOC(buffer, size); buffer[0] = 0x04; /* Set bit 0 to 1 since we are an actual number. */ buffer[1] = 0x01; /* Save the sign bit. */ if (sgn) buffer[1] |= 0x02; /* Save the size of the values. */ buffer[1] |= large; /* Save the exponent sign. */ buffer[1] |= expsgn; /* Save the limb size. */ if ((mp_bits_per_limb >> 3) == 8) buffer[1] |= 0x40; else if ((mp_bits_per_limb >> 3) != 4) { SYSTEM_ERROR("cannot support current limb size"); TEMP_FREE(buffer, size); return NULL; } /* Save the result code. */ if (self->rc == 0) buffer[2] = 0x00; else if (self->rc > 0) buffer[2] = 0x01; else buffer[2] = 0x02; /* Save the original rounding mode. */ buffer[3] = (char)(self->round_mode); /* Save the precision */ cp = buffer + 4; sizetemp = precision; for (i=0; i>= 8; } /* Save the exponenet */ cp += sizesize; sizetemp = exponent; for (i=0; i>= 8; } /* Save the actual mantissa */ cp += sizesize; for (i=0; if->_mpfr_d[i]; #if GMP_LIMB_BITS == 64 cp[0] = (char)(templimb & 0xff); templimb >>= 8; cp[1] = (char)(templimb & 0xff); templimb >>= 8; cp[2] = (char)(templimb & 0xff); templimb >>= 8; cp[3] = (char)(templimb & 0xff); templimb >>= 8; cp[4] = (char)(templimb & 0xff); templimb >>= 8; cp[5] = (char)(templimb & 0xff); templimb >>= 8; cp[6] = (char)(templimb & 0xff); templimb >>= 8; cp[7] = (char)(templimb & 0xff); cp += 8; #endif #if GMP_LIMB_BITS == 32 cp[0] = (char)(templimb & 0xff); templimb >>= 8; cp[1] = (char)(templimb & 0xff); templimb >>= 8; cp[2] = (char)(templimb & 0xff); templimb >>= 8; cp[3] = (char)(templimb & 0xff); cp += 4; #endif } done: result = PyBytes_FromStringAndSize(buffer, size); TEMP_FREE(buffer, size); return result; } #endif #ifdef WITHMPC /* Format of the binary representation of an mpc. * * The format consists of the concatenation of mpfrs (real and imaginary) * converted to binary format. The 0x04 leading byte of each binary string * is replaced by 0x05. */ static PyObject * Pympc_To_Binary(PympcObject *self) { PympfrObject *real = 0, *imag = 0; PyObject *result = 0, *temp = 0; mpfr_prec_t rprec = 0, cprec = 0; mpc_get_prec2(&rprec, &cprec, self->c); real = (PympfrObject*)Pympfr_new(rprec); imag = (PympfrObject*)Pympfr_new(cprec); if (!real || !imag) { Py_XDECREF((PyObject*)real); Py_XDECREF((PyObject*)imag); return NULL; } mpfr_set(real->f, mpc_realref(self->c), MPFR_RNDN); mpfr_set(imag->f, mpc_imagref(self->c), MPFR_RNDN); real->rc = self->rc; real->round_mode = self->round_mode; result = Pympfr_To_Binary(real); temp = Pympfr_To_Binary(imag); Py_DECREF((PyObject*)real); Py_DECREF((PyObject*)imag); if (!result || !temp) { Py_XDECREF((PyObject*)result); Py_XDECREF((PyObject*)temp); return NULL; } PyBytes_AS_STRING(result)[0] = 0x05; PyBytes_AS_STRING(temp)[0] = 0x05; PyBytes_ConcatAndDel(&result, temp); return result; } #endif PyDoc_STRVAR(doc_from_binary, "from_binary(bytes) -> gmpy2 object\n" "Return a Python object from a byte sequence created by\n" "gmpy2.to_binary()."); static PyObject * Pympany_From_Binary(PyObject *self, PyObject *other) { unsigned char *buffer, *cp; Py_ssize_t len; if (!(PyBytes_Check(other))) { TYPE_ERROR("from_binary() requires bytes argument"); return NULL; } len = PyBytes_Size(other); if (len < 2) { VALUE_ERROR("byte sequence too short for from_binary()"); return NULL; } buffer = (unsigned char*)PyBytes_AsString(other); cp = buffer; switch (cp[0]) { case 0x01: { PympzObject *result; if (!(result = (PympzObject*)Pympz_new())) return NULL; if (cp[1] == 0x00) { mpz_set_ui(result->z, 0); return (PyObject*)result; } mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2); if (cp[1] == 0x02) mpz_neg(result->z, result->z); return (PyObject*)result; break; } case 0x02: { PyxmpzObject *result; if (!(result = (PyxmpzObject*)Pyxmpz_new())) return NULL; if (cp[1] == 0x00) { mpz_set_ui(result->z, 0); return (PyObject*)result; } mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2); if (cp[1] == 0x02) mpz_neg(result->z, result->z); return (PyObject*)result; break; } case 0x03: { PympqObject *result; Py_ssize_t numlen = 0, sizesize = 4, i; mpz_t num, den; if (!(result = (PympqObject*)Pympq_new())) return NULL; if (cp[1] == 0x00) { mpq_set_ui(result->q, 0, 1); return (PyObject*)result; } if (cp[1] & 0x04) sizesize = 8; if (len < 2 + sizesize) { VALUE_ERROR("byte sequence too short for from_binary()"); return NULL; } for (i=sizesize; i>0; --i) { numlen = (numlen << 8) + cp[i+1]; } if (len < 2 + sizesize + numlen + 1) { VALUE_ERROR("byte sequence too short for from_binary()"); return NULL; } mpz_inoc(num); mpz_inoc(den); mpz_import(num, numlen, -1, sizeof(char), 0, 0, cp+sizesize+2); mpz_import(den, len-numlen-sizesize-2, -1, sizeof(char), 0, 0, cp+sizesize+numlen+2); mpq_set_num(result->q, num); mpq_set_den(result->q, den); mpq_canonicalize(result->q); mpz_cloc(num); mpz_cloc(den); if (cp[1] == 0x02) mpq_neg(result->q, result->q); return (PyObject*)result; break; } case 0x04: { #ifndef WITHMPFR VALUE_ERROR("creating 'mpfr' object not supported"); return NULL; } #else PympfrObject *result; Py_ssize_t sizemant = 0, sizesize = 4, i, newmant; mpfr_prec_t precision = 0; mpfr_exp_t exponent = 0; mp_limb_t templimb; int sgn = 1, expsgn = 1, limbsize = 4; int newlimbsize = (mp_bits_per_limb >> 3); if (len < 4) { VALUE_ERROR("byte sequence too short for from_binary()"); return NULL; } /* Get size of values. */ if (cp[1] & 0x04) sizesize = 8; /* Get the original precision. */ for (i=sizesize; i>0; --i) { precision = (precision << 8) + cp[i+3]; } /* Get the original sign bit. */ if (cp[1] & 0x02) sgn = -1; /* Get the original exponent sign. */ if (cp[1] & 0x20) expsgn = -1; /* Get the limb size of the originating system. */ if (cp[1] & 0x40) limbsize = 8; if (!(result = (PympfrObject*)Pympfr_new(precision))) return NULL; /* Restore the original result code and rounding mode. */ /* Get the original result code. */ if (cp[2] == 0) result->rc = 0; else if (cp[2] == 1) result->rc = 1; else result->rc = -1; /* Get the original rounding mode. */ result->round_mode = cp[3]; if (!(cp[1] & 0x01)) { /* Process special numbers. */ if ((cp[1] & 0x18) == 0x00) mpfr_set_zero(result->f, sgn); else if ((cp[1] & 0x18) == 0x08) mpfr_set_nan(result->f); else mpfr_set_inf(result->f, sgn); return (PyObject*)result; } /* Process actual numbers. */ /* Calculate the number of limbs on the original system. */ if (limbsize == 8) sizemant = ((precision + 63) / 64); else sizemant = ((precision + 31) / 32); /* Calculate the number of limbs on the current system. */ newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb; /* Get the original exponent. */ cp = buffer + 4 + sizesize - 1; for (i=sizesize; i>0; --i) { exponent = (exponent << 8) + cp[i]; } if (len < 2 + sizesize) { VALUE_ERROR("byte sequence too short for from_binary()"); return NULL; } /* Check if the mantissa occupies the same number of bytes * on both the source and target system. */ if (limbsize * sizemant == newmant * newlimbsize) { mpfr_set_ui(result->f, 1, MPFR_RNDN); cp = buffer + 4 + (2 * sizesize); for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } result->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(result->f, result->f, MPFR_RNDN); return (PyObject*)result; } else if (limbsize * sizemant > newmant * newlimbsize) { /* Since the amount of saved data is greater than the amount of * data needed on the new system, we skip the first 32 bits * since they must be 0. */ /* Verify we are on a 32-bit system and the source was 64-bit. */ if ((limbsize == 8) && (newlimbsize == 4)) { VALUE_ERROR("byte sequence invalid for from_binary()"); return NULL; } mpfr_set_ui(result->f, 1, MPFR_RNDN); cp = buffer + 4 + (2 * sizesize) + 4; for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } result->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(result->f, result->f, MPFR_RNDN); return (PyObject*)result; } else { /* Since the amount of saved data is less than the amount of * data needed on the new system, we must "add" 32 0-bits at * the low end. */ /* Verify we are on a 64-bit system and the source was 32-bit. */ if ((limbsize == 4) && (newlimbsize == 8)) { VALUE_ERROR("byte sequence invalid for from_binary()"); return NULL; } mpfr_set_ui(result->f, 1, MPFR_RNDN); cp = buffer + 4 + (2 * sizesize); templimb = cp[3]; templimb = (templimb << 8) + cp[2]; templimb = (templimb << 8) + cp[1]; templimb = (templimb << 8) + cp[0]; result->f->_mpfr_d[i] = ((templimb << 16) << 16); cp += 4; for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } result->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(result->f, result->f, MPFR_RNDN); return (PyObject*)result; } } #endif case 0x05: { #ifndef WITHMPC VALUE_ERROR("creating 'mpc' object not supported"); return NULL; } #else PympcObject *result; PympfrObject *real = 0, *imag = 0; size_t sizemant = 0, sizesize = 4, i, newmant; mpfr_prec_t precision = 0; mpfr_exp_t exponent = 0; mp_limb_t templimb; int sgn = 1, expsgn = 1, limbsize = 4; int newlimbsize = (mp_bits_per_limb >> 3); unsigned char *tempbuf; if (len < 4) { VALUE_ERROR("byte sequence too short for from_binary()"); return NULL; } /* read the real part first */ if (cp[1] & 0x04) sizesize = 8; for (i=sizesize; i>0; --i) { precision = (precision << 8) + cp[i+3]; } if (cp[1] & 0x02) sgn = -1; if (cp[1] & 0x20) expsgn = -1; if (cp[1] & 0x40) limbsize = 8; if (!(real = (PympfrObject*)Pympfr_new(precision))) return NULL; if (cp[2] == 0) real->rc = 0; else if (cp[2] == 1) real->rc = 1; else real->rc = -1; real->round_mode = cp[3]; if (!(cp[1] & 0x01)) { if ((cp[1] & 0x18) == 0x00) mpfr_set_zero(real->f, sgn); else if ((cp[1] & 0x18) == 0x08) mpfr_set_nan(real->f); else mpfr_set_inf(real->f, sgn); cp += 4 + sizesize; goto readimag; } if (limbsize == 8) sizemant = ((precision + 63) / 64); else sizemant = ((precision + 31) / 32); newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb; cp = buffer + 4 + sizesize - 1; for (i=sizesize; i>0; --i) { exponent = (exponent << 8) + cp[i]; } if (limbsize * sizemant == newmant * newlimbsize) { mpfr_set_ui(real->f, 1, MPFR_RNDN); cp = buffer + 4 + (2 * sizesize); for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } real->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(real->f, real->f, MPFR_RNDN); } else if (limbsize * sizemant > newmant * newlimbsize) { if ((limbsize == 8) && (newlimbsize == 4)) { VALUE_ERROR("byte sequence invalid for from_binary()"); Py_DECREF((PyObject*)real); return NULL; } mpfr_set_ui(real->f, 1, MPFR_RNDN); cp = buffer + 4 + (2 * sizesize) + 4; for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } real->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(real->f, real->f, MPFR_RNDN); } else { if ((limbsize == 4) && (newlimbsize == 8)) { VALUE_ERROR("byte sequence invalid for from_binary()"); Py_DECREF((PyObject*)real); return NULL; } mpfr_set_ui(real->f, 1, MPFR_RNDN); cp = buffer + 4 + (2 * sizesize); templimb = cp[3]; templimb = (templimb << 8) + cp[2]; templimb = (templimb << 8) + cp[1]; templimb = (templimb << 8) + cp[0]; real->f->_mpfr_d[i] = ((templimb << 16) << 16); cp += 4; for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } real->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(real->f, real->f, MPFR_RNDN); } readimag: /* Set all the variables back to default. */ tempbuf = cp; sizemant = 0; sizesize = 4; precision = 0; exponent = 0; sgn = 1; expsgn = 1; limbsize = 4; /* Done reading the real part. The next byte should be 0x05. */ if (!(cp[0] == 0x05)) { VALUE_ERROR("byte sequence invalid for from_binary()"); Py_DECREF((PyObject*)real); return NULL; } if (cp[1] & 0x04) sizesize = 8; for (i=sizesize; i>0; --i) { precision = (precision << 8) + cp[i+3]; } if (cp[1] & 0x02) sgn = -1; if (cp[1] & 0x20) expsgn = -1; if (cp[1] & 0x40) limbsize = 8; if (!(imag = (PympfrObject*)Pympfr_new(precision))) return NULL; if (cp[2] == 0) imag->rc = 0; else if (cp[2] == 1) imag->rc = 1; else imag->rc = -1; imag->round_mode = cp[3]; if (!(cp[1] & 0x01)) { if ((cp[1] & 0x18) == 0x00) mpfr_set_zero(imag->f, sgn); else if ((cp[1] & 0x18) == 0x08) mpfr_set_nan(imag->f); else mpfr_set_inf(imag->f, sgn); goto alldone; } if (limbsize == 8) sizemant = ((precision + 63) / 64); else sizemant = ((precision + 31) / 32); newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb; cp = tempbuf + 4 + sizesize - 1; for (i=sizesize; i>0; --i) { exponent = (exponent << 8) + cp[i]; } if (limbsize * sizemant == newmant * newlimbsize) { mpfr_set_ui(imag->f, 1, MPFR_RNDN); cp = tempbuf + 4 + (2 * sizesize); for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } imag->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(imag->f, imag->f, MPFR_RNDN); } else if (limbsize * sizemant > newmant * newlimbsize) { if ((limbsize == 8) && (newlimbsize == 4)) { VALUE_ERROR("byte sequence invalid for from_binary()"); Py_DECREF((PyObject*)real); Py_DECREF((PyObject*)imag); return NULL; } mpfr_set_ui(imag->f, 1, MPFR_RNDN); cp = tempbuf + 4 + (2 * sizesize) + 4; for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } imag->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(imag->f, imag->f, MPFR_RNDN); } else { if ((limbsize == 4) && (newlimbsize == 8)) { VALUE_ERROR("byte sequence invalid for from_binary()"); Py_DECREF((PyObject*)real); Py_DECREF((PyObject*)imag); return NULL; } mpfr_set_ui(imag->f, 1, MPFR_RNDN); cp = tempbuf + 4 + (2 * sizesize); templimb = cp[3]; templimb = (templimb << 8) + cp[2]; templimb = (templimb << 8) + cp[1]; templimb = (templimb << 8) + cp[0]; imag->f->_mpfr_d[i] = ((templimb << 16) << 16); cp += 4; for (i=0; if->_mpfr_d[i] = templimb; cp += newlimbsize; } imag->f->_mpfr_exp = expsgn * exponent; if (sgn == -1) mpfr_neg(imag->f, imag->f, MPFR_RNDN); } alldone: if (!(result = (PympcObject*)Pympc_new(0,0))) { Py_DECREF((PyObject*)real); Py_DECREF((PyObject*)imag); return NULL; } mpfr_swap(mpc_realref(result->c), real->f); mpfr_swap(mpc_imagref(result->c), imag->f); Py_DECREF((PyObject*)real); Py_DECREF((PyObject*)imag); return (PyObject*)result; } #endif default: { TYPE_ERROR("from_binary() argument type not supported"); return NULL; } } } gmpy2-2.0.7/src/gmpy_basic.h0000666000000000000000000000525612542614506014352 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_context.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef GMPY_BASIC_H #define GMPY_BASIC_H #ifdef __cplusplus extern "C" { #endif /* Forward declarations begin here. */ static PyObject * Pybasic_add(PyObject *a, PyObject *b); static PyObject * Pybasic_sub(PyObject *a, PyObject *b); static PyObject * Pybasic_mul(PyObject *a, PyObject *b); static PyObject * Pybasic_floordiv(PyObject *a, PyObject *b); static PyObject * Pybasic_truediv(PyObject *a, PyObject *b); #ifdef PY2 static PyObject * Pybasic_div2(PyObject *a, PyObject *b); #endif static PyObject * Pybasic_rem(PyObject *a, PyObject *b); static PyObject * Pybasic_divmod(PyObject *a, PyObject *b); #ifdef __cplusplus } #endif #endif gmpy2-2.0.7/src/gmpy_basic.c0000666000000000000000000020506412542614506014344 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_basic.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Generic arithmetic methods for gmpy types. * The routines are highly optimized for performance. */ #include /* Generic addition * * Support addition for gmpy types with automatic conversion of Python types. * * The following conversion logic is used: * 1) 'mpz' combined with an integer type returns an 'mpz' * 2) 'mpz' combined with a rational type returns an 'mpq' * 3) 'mpz' combined with a floating-point type returns an 'mpf' * 4) 'mpq' combined with an integer or rational type returns an 'mpq' * 5) 'mpq' combines with a floating-point type returns an 'mpf' * 6) Any type combines with 'mpc' returns an 'mpc. * * The most common inputs are processed as efficiently as possible. */ /* To optimize the performance of mpfr op mpfr and mpc op mpc, dedicated * functions are provided for the mpfr and mpc types. The optimal path assumes * both arguments are of the same type. If not, the general-purpose Pybasic * function is called. * * These functions are located in either gmpy_mpfr.c or gmpy_mpc.c. Ther are * call Pympfr_op_fast or Pympc_op_fast. */ static PyObject * Pybasic_add(PyObject *a, PyObject *b) { mpz_t tempz; #ifdef WITHMPFR PympzObject *rz = 0, *paz = 0, *pbz = 0; #else PympzObject *rz = 0; #endif PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *rf = 0, *paf = 0, *pbf = 0; #else double tempdouble; #endif #ifdef WITHMPC PympcObject *rc = 0, *pac = 0, *pbc = 0; #endif mpir_si temp_si; int overflow; if (CHECK_MPZANY(a)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_add(rz->z, Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if (temp_si >= 0) { mpz_add_ui(rz->z, Pympz_AS_MPZ(a), temp_si); } else { mpz_sub_ui(rz->z, Pympz_AS_MPZ(a), -temp_si); } return (PyObject*)rz; } if (CHECK_MPZANY(b)) { mpz_add(rz->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } if (CHECK_MPZANY(b)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(a)) { temp_si = PyLong_AsSIAndOverflow(a, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, a); mpz_add(rz->z, Pympz_AS_MPZ(b), tempz); mpz_cloc(tempz); } else if (temp_si >0) { mpz_add_ui(rz->z, Pympz_AS_MPZ(b), temp_si); } else { mpz_sub_ui(rz->z, Pympz_AS_MPZ(b), -temp_si); } return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } #ifdef WITHMPFR /* Pympfr_add_fast already handles the case when both a and b are valid * mpfr instances. */ if (Pympfr_CheckAndExp(a)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (isInteger(b)) { if (!(pbz = Pympz_From_Number(b))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_add_z(rf->f, Pympfr_AS_MPFR(a), pbz->z, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbz); MPFR_CLEANUP_RF(addition); } if (isRational(b) || isDecimal(b)) { if (!(pbq = Pympq_From_Number(b))) { SYSTEM_ERROR("Can not convert Rational or Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_add_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(addition); } if (PyFloat_Check(b)) { mpfr_clear_flags(); rf->rc = mpfr_add_d(rf->f, Pympfr_AS_MPFR(a), PyFloat_AS_DOUBLE(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(addition); } Py_DECREF((PyObject*)rf); } if (Pympfr_CheckAndExp(b)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (isInteger(a)) { if (!(paz = Pympz_From_Number(a))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_add_z(rf->f, Pympfr_AS_MPFR(b), paz->z, context->ctx.mpfr_round); Py_DECREF((PyObject*)paz); MPFR_CLEANUP_RF(addition); } if (isRational(a) || isDecimal(a)) { if (!(paq = Pympq_From_Number(a))) { SYSTEM_ERROR("Can not convert Rational or Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_add_q(rf->f, Pympfr_AS_MPFR(b), paq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)paq); MPFR_CLEANUP_RF(addition); } if (PyFloat_Check(a)) { mpfr_clear_flags(); rf->rc = mpfr_add_d(rf->f, Pympfr_AS_MPFR(b), PyFloat_AS_DOUBLE(a), context->ctx.mpfr_round); MPFR_CLEANUP_RF(addition); } Py_DECREF((PyObject*)rf); } #endif if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpq_add(rq->q, paq->q, pbq->q); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return (PyObject*)rq; } #ifdef WITHMPFR if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (!(rf = (PympfrObject*)Pympfr_new(0))) { Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_add(rf->f, paf->f, pbf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); MPFR_CLEANUP_RF(addition); } #else /* Support mpz+float and float+mpz. */ if (CHECK_MPZANY(a) && PyFloat_Check(b)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(a)); tempdouble = tempdouble + PyFloat_AsDouble(b); return PyFloat_FromDouble(tempdouble); } if (CHECK_MPZANY(b) && PyFloat_Check(a)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(b)); tempdouble = PyFloat_AsDouble(a) + tempdouble; return PyFloat_FromDouble(tempdouble); } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { pac = Pympc_From_Complex(a, 0, 0); pbc = Pympc_From_Complex(b, 0, 0); if (!pac || !pbc) { SYSTEM_ERROR("Can not convert Complex to 'mpc'"); Py_XDECREF((PyObject*)pac); Py_XDECREF((PyObject*)pbc); return NULL; } if (!(rc = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); return NULL; } rc->rc = mpc_add(rc->c, pac->c, pbc->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); MPC_CLEANUP(rc, "addition"); } #endif Py_RETURN_NOTIMPLEMENTED; } /* Generic Subtraction * * Follows the same conversion rules as Pympany_add. */ static PyObject * Pybasic_sub(PyObject *a, PyObject *b) { mpz_t tempz; PympzObject *rz = 0, *paz = 0, *pbz = 0; PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *rf = 0, *paf = 0, *pbf = 0; #else double tempdouble; #endif #ifdef WITHMPC PympcObject *rc = 0, *pac = 0, *pbc = 0; #endif mpir_si temp_si; int overflow; if (CHECK_MPZANY(a)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_sub(rz->z, Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if (temp_si >= 0) { mpz_sub_ui(rz->z, Pympz_AS_MPZ(a), temp_si); } else { mpz_add_ui(rz->z, Pympz_AS_MPZ(a), -temp_si); } return (PyObject*)rz; } if (Pympz_Check(b)) { mpz_sub(rz->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } if (CHECK_MPZANY(b)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(a)) { temp_si = PyLong_AsSIAndOverflow(a, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, a); mpz_sub(rz->z, tempz, Pympz_AS_MPZ(b)); mpz_cloc(tempz); } else if (temp_si >= 0) { mpz_ui_sub(rz->z, temp_si, Pympz_AS_MPZ(b)); } else { mpz_add_ui(rz->z, Pympz_AS_MPZ(b), -temp_si); mpz_neg(rz->z, rz->z); } return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } #ifdef WITHMPFR /* Pympfr_sub_fast already handles the case when both a and b are valid * mpfr instances. */ if (Pympfr_CheckAndExp(a)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (isInteger(b)) { if (!(pbz = Pympz_From_Number(b))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_sub_z(rf->f, Pympfr_AS_MPFR(a), pbz->z, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbz); MPFR_CLEANUP_RF(subtraction); } if (isRational(b)) { if (!(pbq = Pympq_From_Number(b))) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_sub_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(subtraction); } if (isDecimal(b)) { if (!(pbq = Pympq_From_Decimal(b))) { SYSTEM_ERROR("Can not convert Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_sub_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(subtraction); } if (PyFloat_Check(b)) { mpfr_clear_flags(); rf->rc = mpfr_sub_d(rf->f, Pympfr_AS_MPFR(a), PyFloat_AS_DOUBLE(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(subtraction); } Py_DECREF((PyObject*)rf); } if (Pympfr_CheckAndExp(b)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (isInteger(a)) { if (!(paz = Pympz_From_Number(a))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_sub_z(rf->f, Pympfr_AS_MPFR(b), paz->z, context->ctx.mpfr_round); mpfr_neg(rf->f, rf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paz); MPFR_CLEANUP_RF(subtraction); } if (isRational(a)) { if (!(paq = Pympq_From_Number(a))) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_sub_q(rf->f, Pympfr_AS_MPFR(b), paq->q, context->ctx.mpfr_round); mpfr_neg(rf->f, rf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paq); MPFR_CLEANUP_RF(subtraction); } if (isDecimal(a)) { if (!(paq = Pympq_From_Decimal(a))) { SYSTEM_ERROR("Can not convert Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_sub_q(rf->f, Pympfr_AS_MPFR(b), paq->q, context->ctx.mpfr_round); mpfr_neg(rf->f, rf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paq); MPFR_CLEANUP_RF(subtraction); } if (PyFloat_Check(a)) { mpfr_clear_flags(); rf->rc = mpfr_sub_d(rf->f, Pympfr_AS_MPFR(b), PyFloat_AS_DOUBLE(a), context->ctx.mpfr_round); mpfr_neg(rf->f, rf->f, context->ctx.mpfr_round); MPFR_CLEANUP_RF(subtraction); } Py_DECREF((PyObject*)rf); } #endif if (isInteger(a) && isInteger(b)) { paz = Pympz_From_Number(a); pbz = Pympz_From_Number(b); if (!paz || !pbz) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_XDECREF((PyObject*)paz); Py_XDECREF((PyObject*)pbz); return NULL; } if (!(rz = (PympzObject*)Pympz_new())) { Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } mpz_sub(rz->z, paz->z, pbz->z); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return (PyObject*)rz; } if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpq_sub(rq->q, paq->q, pbq->q); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return (PyObject*)rq; } #ifdef WITHMPFR if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (!(rf = (PympfrObject*)Pympfr_new(0))) { Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_sub(rf->f, paf->f, pbf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); MPFR_CLEANUP_RF(subtraction); } #else /* Support mpz-float and float-mpz. */ if (CHECK_MPZANY(a) && PyFloat_Check(b)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(a)); tempdouble = tempdouble-PyFloat_AsDouble(b); return PyFloat_FromDouble(tempdouble); } if (CHECK_MPZANY(b) && PyFloat_Check(a)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(b)); tempdouble = PyFloat_AsDouble(a)-tempdouble; return PyFloat_FromDouble(tempdouble); } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { pac = Pympc_From_Complex(a, 0, 0); pbc = Pympc_From_Complex(b, 0, 0); if (!pac || !pbc) { SYSTEM_ERROR("Can not convert Complex to 'mpc'"); Py_XDECREF((PyObject*)pac); Py_XDECREF((PyObject*)pbc); return NULL; } if (!(rc = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); return NULL; } rc->rc = mpc_sub(rc->c, pac->c, pbc->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); MPC_CLEANUP(rc, "subtraction"); } #endif Py_RETURN_NOTIMPLEMENTED; } /* Generic Multiplication * * Follows the same conversion rules as Pympany_add. */ static PyObject * Pybasic_mul(PyObject *a, PyObject *b) { mpz_t tempz; PympzObject *rz = 0, *paz = 0, *pbz = 0; PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *rf = 0, *paf = 0, *pbf = 0; #else double tempdouble; #endif #ifdef WITHMPC PympcObject *rc = 0, *pac = 0, *pbc = 0; #endif mpir_si temp_si; int overflow; if (CHECK_MPZANY(a)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_mul(rz->z, Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else { mpz_mul_si(rz->z, Pympz_AS_MPZ(a), temp_si); } return (PyObject*)rz; } if (Pympz_Check(b)) { mpz_mul(rz->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } if (CHECK_MPZANY(b)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(a)) { temp_si = PyLong_AsSIAndOverflow(a, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, a); mpz_mul(rz->z, Pympz_AS_MPZ(b), tempz); mpz_cloc(tempz); } else { mpz_mul_si(rz->z, Pympz_AS_MPZ(b), temp_si); } return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } #ifdef WITHMPFR if (Pympfr_CheckAndExp(a)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (Pympfr_CheckAndExp(b)) { mpfr_clear_flags(); rf->rc = mpfr_mul(rf->f, Pympfr_AS_MPFR(a), Pympfr_AS_MPFR(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(multiplication); } if (isInteger(b)) { if (!(pbz = Pympz_From_Number(b))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_mul_z(rf->f, Pympfr_AS_MPFR(a), pbz->z, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbz); MPFR_CLEANUP_RF(multiplication); } if (isRational(b)) { if (!(pbq = Pympq_From_Number(b))) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_mul_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(multiplication); } if (isDecimal(b)) { if (!(pbq = Pympq_From_Decimal(b))) { SYSTEM_ERROR("Can not convert Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_mul_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(multiplication); } if (PyFloat_Check(b)) { mpfr_clear_flags(); rf->rc = mpfr_mul_d(rf->f, Pympfr_AS_MPFR(a), PyFloat_AS_DOUBLE(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(multiplication); } Py_DECREF((PyObject*)rf); } if (Pympfr_CheckAndExp(b)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (isInteger(a)) { if (!(paz = Pympz_From_Number(a))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_mul_z(rf->f, Pympfr_AS_MPFR(b), paz->z, context->ctx.mpfr_round); Py_DECREF((PyObject*)paz); MPFR_CLEANUP_RF(multiplication); } if (isRational(a)) { if (!(paq = Pympq_From_Number(a))) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_mul_q(rf->f, Pympfr_AS_MPFR(b), paq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)paq); MPFR_CLEANUP_RF(multiplication); } if (isDecimal(a)) { if (!(paq = Pympq_From_Decimal(a))) { SYSTEM_ERROR("Can not convert Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_mul_q(rf->f, Pympfr_AS_MPFR(b), paq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)paq); MPFR_CLEANUP_RF(multiplication); } if (PyFloat_Check(a)) { mpfr_clear_flags(); rf->rc = mpfr_mul_d(rf->f, Pympfr_AS_MPFR(b), PyFloat_AS_DOUBLE(a), context->ctx.mpfr_round); MPFR_CLEANUP_RF(multiplication); } Py_DECREF((PyObject*)rf); } #endif if (isInteger(a) && isInteger(b)) { paz = Pympz_From_Number(a); pbz = Pympz_From_Number(b); if (!paz || !pbz) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_XDECREF((PyObject*)paz); Py_XDECREF((PyObject*)pbz); return NULL; } if (!(rz = (PympzObject*)Pympz_new())) { Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } mpz_mul(rz->z, paz->z, pbz->z); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return (PyObject*)rz; } if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpq_mul(rq->q, paq->q, pbq->q); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return (PyObject*)rq; } #ifdef WITHMPFR if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (!(rf = (PympfrObject*)Pympfr_new(0))) { Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_mul(rf->f, paf->f, pbf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); MPFR_CLEANUP_RF(multiplication); } #else /* Support mpz*float and float*mpz. */ if (CHECK_MPZANY(a) && PyFloat_Check(b)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(a)); if (Py_IS_INFINITY(tempdouble)) { OVERFLOW_ERROR("'mpz' too large to convert to float"); return NULL; } tempdouble = tempdouble*PyFloat_AsDouble(b); return PyFloat_FromDouble(tempdouble); } if (CHECK_MPZANY(b) && PyFloat_Check(a)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(b)); if (Py_IS_INFINITY(tempdouble)) { OVERFLOW_ERROR("'mpz' too large to convert to float"); return NULL; } tempdouble = PyFloat_AsDouble(a)*tempdouble; return PyFloat_FromDouble(tempdouble); } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { pac = Pympc_From_Complex(a, 0, 0); pbc = Pympc_From_Complex(b, 0, 0); if (!pac || !pbc) { SYSTEM_ERROR("Can not convert Complex to 'mpc'"); Py_XDECREF((PyObject*)pac); Py_XDECREF((PyObject*)pbc); return NULL; } if (!(rc = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); return NULL; } rc->rc = mpc_mul(rc->c, pac->c, pbc->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); MPC_CLEANUP(rc, "multiplication"); } #endif Py_RETURN_NOTIMPLEMENTED; } /* Pympany_floordiv follows the // semantics from Python 3.x. The result is * an mpz when the arguments are mpz or mpq, but the result is an mpfr when * the arguments are mpfr. */ static PyObject * Pybasic_floordiv(PyObject *a, PyObject *b) { mpz_t tempz; PympzObject *rz = 0, *paz = 0, *pbz = 0; PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *rf = 0, *paf = 0, *pbf = 0; #endif mpir_si temp_si; int overflow; if (CHECK_MPZANY(a)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_q(rz->z, Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if (temp_si == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); return NULL; } else if (temp_si > 0) { mpz_fdiv_q_ui(rz->z, Pympz_AS_MPZ(a), temp_si); } else { mpz_cdiv_q_ui(rz->z, Pympz_AS_MPZ(a), -temp_si); mpz_neg(rz->z, rz->z); } return (PyObject*)rz; } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pympz_AS_MPZ(b)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); return NULL; } mpz_fdiv_q(rz->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pympz_AS_MPZ(b)) == 0) { ZERO_ERROR("division or modulo by zero"); return NULL; } if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(a)) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, a); mpz_fdiv_q(rz->z, tempz, Pympz_AS_MPZ(b)); mpz_cloc(tempz); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } #ifdef WITHMPFR if (Pympfr_CheckAndExp(a)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (Pympfr_CheckAndExp(b)) { mpfr_clear_flags(); rf->rc = mpfr_div(rf->f, Pympfr_AS_MPFR(a), Pympfr_AS_MPFR(b), MPFR_RNDD); rf->rc = mpfr_floor(rf->f, rf->f); MPFR_CLEANUP_RF(division); } if (isInteger(b)) { if (!(pbz = Pympz_From_Number(b))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_z(rf->f, Pympfr_AS_MPFR(a), pbz->z, MPFR_RNDD); rf->rc = mpfr_floor(rf->f, rf->f); Py_DECREF((PyObject*)pbz); MPFR_CLEANUP_RF(division); } if (isRational(b)) { if (!(pbq = Pympq_From_Number(b))) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, MPFR_RNDD); rf->rc = mpfr_floor(rf->f, rf->f); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(division); } if (isDecimal(b)) { if (!(pbq = Pympq_From_Decimal(b))) { SYSTEM_ERROR("Can not convert Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, MPFR_RNDD); rf->rc = mpfr_floor(rf->f, rf->f); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(division); } if (PyFloat_Check(b)) { mpfr_clear_flags(); rf->rc = mpfr_div_d(rf->f, Pympfr_AS_MPFR(a), PyFloat_AS_DOUBLE(b), MPFR_RNDD); rf->rc = mpfr_floor(rf->f, rf->f); MPFR_CLEANUP_RF(division); } Py_DECREF((PyObject*)rf); } if (Pympfr_CheckAndExp(b)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; /* Need an mpfr_z_div() to provide optimal support for isInteger(), and * need an mpfr_q_div() to provide optimal support for isRational() and * isDecimal(). */ if (PyFloat_Check(a)) { mpfr_clear_flags(); rf->rc = mpfr_d_div(rf->f, PyFloat_AS_DOUBLE(a), Pympfr_AS_MPFR(b), MPFR_RNDD); rf->rc = mpfr_floor(rf->f, rf->f); MPFR_CLEANUP_RF(division); } Py_DECREF((PyObject*)rf); } #endif if (isInteger(a) && isInteger(b)) { paz = Pympz_From_Number(a); pbz = Pympz_From_Number(b); if (!paz || !pbz) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_XDECREF((PyObject*)paz); Py_XDECREF((PyObject*)pbz); return NULL; } if (mpz_sgn(pbz->z)==0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } if (!(rz = (PympzObject*)Pympz_new())) { Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } mpz_fdiv_q(rz->z, paz->z, pbz->z); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return (PyObject*)rz; } if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (mpq_sgn(pbq->q)==0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } if (!(rq = (PympqObject*)Pympq_new()) || !(rz = (PympzObject*)Pympz_new())) { Py_XDECREF((PyObject*)rq); Py_XDECREF((PyObject*)rz); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpq_div(rq->q, paq->q, pbq->q); mpz_fdiv_q(rz->z, mpq_numref(rq->q), mpq_denref(rq->q)); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); Py_DECREF((PyObject*)rq); return (PyObject*)rz; } #ifdef WITHMPFR if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (!(rf = (PympfrObject*)Pympfr_new(0))) { Py_XDECREF((PyObject*)rf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div(rf->f, paf->f, pbf->f, MPFR_RNDD); rf->rc = mpfr_floor(rf->f, rf->f); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); MPFR_CLEANUP_RF(division); } #else /* Handle mixed mpz and PyFloat floor division. */ if (CHECK_MPZANY(a) && PyFloat_Check(b)) { PyObject *temp = NULL, *result = NULL; if ((temp = Pympz_To_PyLong((PympzObject*)a))) { result = PyNumber_FloorDivide(temp, b); Py_DECREF(temp); } return result; } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { TYPE_ERROR("can't take floor of complex number."); return NULL; } #endif Py_RETURN_NOTIMPLEMENTED; } /* Pympany_truediv follows the / semantics from Python 3.x. The result types * are: * mpz / mpz -> mpfr * mpq / mpq -> mpq * mpfr / mpfr -> mpfr * * The behavior of mpq now mimics the behavior of fractions.Fraction. */ static PyObject * Pybasic_truediv(PyObject *a, PyObject *b) { PympzObject *paz = 0, *pbz = 0; PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *rf = 0, *paf = 0, *pbf = 0; #else double tempdouble; #endif #ifdef WITHMPC PympcObject *rc = 0, *pac = 0, *pbc = 0; #endif mpq_t tempq; #ifdef WITHMPFR if (Pympfr_CheckAndExp(a)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (Pympfr_CheckAndExp(b)) { mpfr_clear_flags(); rf->rc = mpfr_div(rf->f, Pympfr_AS_MPFR(a), Pympfr_AS_MPFR(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(division); } if (isInteger(b)) { if (!(pbz = Pympz_From_Number(b))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_z(rf->f, Pympfr_AS_MPFR(a), pbz->z, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbz); MPFR_CLEANUP_RF(division); } if (isRational(b)) { if (!(pbq = Pympq_From_Number(b))) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(division); } if (isDecimal(b)) { if (!(pbq = Pympq_From_Decimal(b))) { SYSTEM_ERROR("Can not convert Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(division); } if (PyFloat_Check(b)) { mpfr_clear_flags(); rf->rc = mpfr_div_d(rf->f, Pympfr_AS_MPFR(a), PyFloat_AS_DOUBLE(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(division); } Py_DECREF((PyObject*)rf); } if (Pympfr_CheckAndExp(b)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; /* Need an mpfr_z_div() to provide optimal support for isInteger(), and * need an mpfr_q_div() to provide optimal support for isRational() and * isDecimal(). */ if (PyFloat_Check(a)) { mpfr_clear_flags(); rf->rc = mpfr_d_div(rf->f, PyFloat_AS_DOUBLE(a), Pympfr_AS_MPFR(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(division); } Py_DECREF((PyObject*)rf); } #endif if (isInteger(a) && isInteger(b)) { paz = Pympz_From_Number(a); pbz = Pympz_From_Number(b); if (!paz || !pbz) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_XDECREF((PyObject*)paz); Py_XDECREF((PyObject*)pbz); return NULL; } if (mpz_sgn(pbz->z) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } #ifdef WITHMPFR if (!(rf = (PympfrObject*)Pympfr_new(0))) { Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } #endif mpq_init(tempq); mpq_set_num(tempq, paz->z); mpq_set_den(tempq, pbz->z); mpq_canonicalize(tempq); #ifdef WITHMPFR mpfr_clear_flags(); rf->rc = mpfr_set_q(rf->f, tempq, context->ctx.mpfr_round); #else tempdouble = mpq_get_d(tempq); #endif mpq_clear(tempq); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); #ifdef WITHMPFR MPFR_CLEANUP_RF(division); #else return PyFloat_FromDouble(tempdouble); #endif } if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (mpq_sgn(pbq->q)==0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpq_div(rq->q, paq->q, pbq->q); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return (PyObject*) rq; } #ifdef WITHMPFR if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (!(rf = (PympfrObject*)Pympfr_new(0))) { Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div(rf->f, paf->f, pbf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); MPFR_CLEANUP_RF(division); } #else /* Support mpz/float and float/mpz. */ if (CHECK_MPZANY(a) && PyFloat_Check(b)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(a)); if (Py_IS_INFINITY(tempdouble)) { OVERFLOW_ERROR("'mpz' too large to convert to float"); return NULL; } tempdouble = tempdouble/PyFloat_AsDouble(b); return PyFloat_FromDouble(tempdouble); } if (CHECK_MPZANY(b) && PyFloat_Check(a)) { tempdouble = mpz_get_d(Pympz_AS_MPZ(b)); if (Py_IS_INFINITY(tempdouble)) { OVERFLOW_ERROR("'mpz' too large to convert to float"); return NULL; } tempdouble = PyFloat_AsDouble(a)/tempdouble; return PyFloat_FromDouble(tempdouble); } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { pac = Pympc_From_Complex(a, 0, 0); pbc = Pympc_From_Complex(b, 0, 0); if (!pac || !pbc) { SYSTEM_ERROR("Can not convert Complex to 'mpc'"); Py_XDECREF((PyObject*)pac); Py_XDECREF((PyObject*)pbc); return NULL; } if (MPC_IS_ZERO_P(pbc)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("'mpc' division by zero"); Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); return NULL; } } if (!(rc = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); return NULL; } rc->rc = mpc_div(rc->c, pac->c, pbc->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); MPC_CLEANUP(rc, "division"); } #endif Py_RETURN_NOTIMPLEMENTED; } #ifdef PY2 /* Pympany_div2 follows the conversions rules for Python 2.x. The behavior is * a mix of floordiv and truediv. The type conversion behavior is: * mpz / mpz -> mpz * mpq / mpq -> mpq * mpfr / mpfr -> mpfr * * A division operator with these properties is not available with Python 3.x. */ static PyObject * Pybasic_div2(PyObject *a, PyObject *b) { mpz_t tempz; PympzObject *rz = 0, *paz = 0, *pbz = 0; PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *rf = 0, *paf = 0, *pbf = 0; #endif #ifdef WITHMPC PympcObject *rc = 0, *pac = 0, *pbc = 0; #endif mpir_si temp_si; int overflow; /* Use floordiv for integer types. */ if (CHECK_MPZANY(a)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_q(rz->z, Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if (temp_si == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); return NULL; } else if (temp_si > 0) { mpz_fdiv_q_ui(rz->z, Pympz_AS_MPZ(a), temp_si); } else { mpz_cdiv_q_ui(rz->z, Pympz_AS_MPZ(a), -temp_si); mpz_neg(rz->z, rz->z); } return (PyObject*)rz; } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pympz_AS_MPZ(b)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); return NULL; } mpz_fdiv_q(rz->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } if (isInteger(a) && isInteger(b)) { paz = Pympz_From_Number(a); pbz = Pympz_From_Number(b); if (!paz || !pbz) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_XDECREF((PyObject*)paz); Py_XDECREF((PyObject*)pbz); return NULL; } if (mpz_sgn(pbz->z)==0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } if (!(rz = (PympzObject*)Pympz_new())) { Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return NULL; } mpz_fdiv_q(rz->z, paz->z, pbz->z); Py_DECREF((PyObject*)paz); Py_DECREF((PyObject*)pbz); return (PyObject*)rz; } if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (mpq_sgn(pbq->q)==0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpq_div(rq->q, paq->q, pbq->q); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return (PyObject*) rq; } /* Use truediv for floating-point types. */ #ifdef WITHMPFR if (Pympfr_CheckAndExp(a)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; if (Pympfr_CheckAndExp(b)) { mpfr_clear_flags(); rf->rc = mpfr_div(rf->f, Pympfr_AS_MPFR(a), Pympfr_AS_MPFR(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(division); } if (isInteger(b)) { if (!(pbz = Pympz_From_Number(b))) { SYSTEM_ERROR("Can not convert Integer to 'mpz'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_z(rf->f, Pympfr_AS_MPFR(a), pbz->z, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbz); MPFR_CLEANUP_RF(division); } if (isRational(b)) { if (!(pbq = Pympq_From_Number(b))) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(division); } if (isDecimal(b)) { if (!(pbq = Pympq_From_Decimal(b))) { SYSTEM_ERROR("Can not convert Decimal to 'mpq'"); Py_DECREF((PyObject*)rf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div_q(rf->f, Pympfr_AS_MPFR(a), pbq->q, context->ctx.mpfr_round); Py_DECREF((PyObject*)pbq); MPFR_CLEANUP_RF(division); } if (PyFloat_Check(b)) { mpfr_clear_flags(); rf->rc = mpfr_div_d(rf->f, Pympfr_AS_MPFR(a), PyFloat_AS_DOUBLE(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(division); } Py_DECREF((PyObject*)rf); } if (Pympfr_CheckAndExp(b)) { if (!(rf = (PympfrObject*)Pympfr_new(0))) return NULL; /* Need an mpfr_z_div() to provide optimal support for isInteger(), and * need an mpfr_q_div() to provide optimal support for isRational() and * isDecimal(). */ if (PyFloat_Check(a)) { mpfr_clear_flags(); rf->rc = mpfr_d_div(rf->f, PyFloat_AS_DOUBLE(a), Pympfr_AS_MPFR(b), context->ctx.mpfr_round); MPFR_CLEANUP_RF(division); } Py_DECREF((PyObject*)rf); } if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (!(rf = (PympfrObject*)Pympfr_new(0))) { Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); rf->rc = mpfr_div(rf->f, paf->f, pbf->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); MPFR_CLEANUP_RF(division); } #else /* Handle mixed mpz and PyFloat true division. */ if (CHECK_MPZANY(a) && PyFloat_Check(b)) { PyObject *temp = NULL, *result = NULL; if ((temp = Pympz_To_PyLong((PympzObject*)a))) { result = PyNumber_TrueDivide(temp, b); Py_DECREF(temp); } return result; } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { pac = Pympc_From_Complex(a, 0, 0); pbc = Pympc_From_Complex(b, 0, 0); if (!pac || !pbc) { SYSTEM_ERROR("Can not convert Complex to 'mpc'"); Py_XDECREF((PyObject*)pac); Py_XDECREF((PyObject*)pbc); return NULL; } if (MPC_IS_ZERO_P(pbc)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("'mpc' division by zero"); Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); return NULL; } } if (!(rc = (PympcObject*)Pympc_new(0, 0))) { Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); return NULL; } rc->rc = mpc_div(rc->c, pac->c, pbc->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)pac); Py_DECREF((PyObject*)pbc); MPC_CLEANUP(rc, "division"); } #endif Py_RETURN_NOTIMPLEMENTED; } #endif /* Pympany_rem follows the % semantics from Python 3.x. The result types * are: * mpz % mpz -> mpz * mpq % mpq -> mpq * mpfr % mpfr -> mpfr * * The behavior of mpq now mimics the behavior of fractions.Fraction. */ static PyObject * Pybasic_rem(PyObject *a, PyObject *b) { mpz_t tempz; PympzObject *rz = 0; PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *qf = 0, *rf = 0, *paf = 0, *pbf = 0; #endif mpir_si temp_si; int overflow; if (CHECK_MPZANY(a)) { if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_r(rz->z, Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if (temp_si > 0) { mpz_fdiv_r_ui(rz->z, Pympz_AS_MPZ(a), temp_si); } else if (temp_si == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); return NULL; } else { mpz_cdiv_r_ui(rz->z, Pympz_AS_MPZ(a), -temp_si); } return (PyObject*)rz; } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pympz_AS_MPZ(b)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); return NULL; } mpz_fdiv_r(rz->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pympz_AS_MPZ(b)) == 0) { ZERO_ERROR("division or modulo by zero"); return NULL; } if (!(rz = (PympzObject*)Pympz_new())) return NULL; if (PyIntOrLong_Check(a)) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, a); mpz_fdiv_r(rz->z, tempz, Pympz_AS_MPZ(b)); mpz_cloc(tempz); return (PyObject*)rz; } Py_DECREF((PyObject*)rz); } if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to 'mpq'"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (mpq_sgn(pbq->q)==0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_XDECREF((PyObject*)rq); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpz_inoc(tempz); mpq_div(rq->q, paq->q, pbq->q); mpz_fdiv_q(tempz, mpq_numref(rq->q), mpq_denref(rq->q)); /* Need to calculate paq - rz * pbq */ mpq_set_z(rq->q, tempz); mpq_mul(rq->q, rq->q, pbq->q); mpq_sub(rq->q, paq->q, rq->q); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); mpz_cloc(tempz); return (PyObject*)rq; } #ifdef WITHMPFR if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (mpfr_zero_p(pbf->f)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("'mpfr' division by zero in modulo"); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } } if (!(rf = (PympfrObject*)Pympfr_new(0)) || !(qf = (PympfrObject*)Pympfr_new(0))) { Py_XDECREF((PyObject*)rf); Py_XDECREF((PyObject*)qf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); if (mpfr_nan_p(paf->f) || mpfr_nan_p(pbf->f) || mpfr_inf_p(paf->f)) { context->ctx.invalid = 1; if (context->ctx.trap_invalid) { GMPY_INVALID("'mpfr' invalid operation in modulo"); Py_DECREF((PyObject*)rf); Py_DECREF((PyObject*)qf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } else { mpfr_set_nan(rf->f); } } else if (mpfr_inf_p(pbf->f)) { context->ctx.invalid = 1; if (context->ctx.trap_invalid) { GMPY_INVALID("'mpfr' invalid operation in modulo"); Py_DECREF((PyObject*)rf); Py_DECREF((PyObject*)qf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } if (mpfr_signbit(pbf->f)) { mpfr_set_inf(rf->f, -1); } else { rf->rc = mpfr_set(rf->f, paf->f, context->ctx.mpfr_round); } } else { mpfr_div(qf->f, paf->f, pbf->f, MPFR_RNDD); mpfr_floor(qf->f, qf->f); rf->rc = mpfr_fms(rf->f, qf->f, pbf->f, paf->f, context->ctx.mpfr_round); mpfr_neg(rf->f, rf->f, context->ctx.mpfr_round); } Py_XDECREF((PyObject*)qf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); MPFR_CLEANUP_RF(rem); } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { TYPE_ERROR("can't mod complex numbers"); return NULL; } #endif Py_RETURN_NOTIMPLEMENTED; } /* Pympany_divmod follows the semantics from Python 3.x. The result types * are: * divmod(mpz, mpz) -> (mpz, mpz) * divmod(mpq, mpq) -> (mpz, mpq) * divmod(mpfr, mpfr) -> (mpfr, mpfr) * * The behavior of mpq now mimics the behavior of fractions.Fraction. */ static PyObject * Pybasic_divmod(PyObject *a, PyObject *b) { PyObject *r = 0; mpz_t tempz; PympzObject *qz = 0, *rz = 0; PympqObject *rq = 0, *paq = 0, *pbq = 0; #ifdef WITHMPFR PympfrObject *qf = 0, *rf = 0, *paf = 0, *pbf = 0; #endif mpir_si temp_si; int overflow; if (CHECK_MPZANY(a)) { if (!( r= PyTuple_New(2)) || !(rz = (PympzObject*)Pympz_new()) || !(qz = (PympzObject*)Pympz_new())) { Py_XDECREF((PyObject*)rz); Py_XDECREF((PyObject*)qz); Py_XDECREF(r); return NULL; } if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_qr(qz->z, rz->z, Pympz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if (temp_si > 0) { mpz_fdiv_qr_ui(qz->z, rz->z, Pympz_AS_MPZ(a), temp_si); } else if (temp_si == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); Py_DECREF((PyObject*)qz); Py_DECREF(r); return NULL; } else { mpz_cdiv_qr_ui(qz->z, rz->z, Pympz_AS_MPZ(a), -temp_si); mpz_neg(qz->z, qz->z); } PyTuple_SET_ITEM(r, 0, (PyObject*)qz); PyTuple_SET_ITEM(r, 1, (PyObject*)rz); return r; } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pympz_AS_MPZ(b)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rz); Py_DECREF((PyObject*)qz); Py_DECREF(r); return NULL; } mpz_fdiv_qr(qz->z, rz->z, Pympz_AS_MPZ(a), Pympz_AS_MPZ(b)); PyTuple_SET_ITEM(r, 0, (PyObject*)qz); PyTuple_SET_ITEM(r, 1, (PyObject*)rz); return r; } Py_DECREF((PyObject*)rz); Py_DECREF((PyObject*)qz); Py_DECREF(r); } if (CHECK_MPZANY(b) && PyIntOrLong_Check(a)) { if (mpz_sgn(Pympz_AS_MPZ(b)) == 0) { ZERO_ERROR("division or modulo by zero"); return NULL; } if (!(r = PyTuple_New(2)) || !(rz = (PympzObject*)Pympz_new()) || !(qz = (PympzObject*)Pympz_new())) { Py_XDECREF((PyObject*)rz); Py_XDECREF((PyObject*)qz); Py_XDECREF(r); return NULL; } mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, a); mpz_fdiv_qr(qz->z, rz->z, tempz, Pympz_AS_MPZ(b)); mpz_cloc(tempz); PyTuple_SET_ITEM(r, 0, (PyObject*)qz); PyTuple_SET_ITEM(r, 1, (PyObject*)rz); return r; } if (isRational(a) && isRational(b)) { paq = Pympq_From_Number(a); pbq = Pympq_From_Number(b); if (!paq || !pbq) { SYSTEM_ERROR("Can not convert Rational to mpq"); Py_XDECREF((PyObject*)paq); Py_XDECREF((PyObject*)pbq); return NULL; } if (mpq_sgn(pbq->q)==0) { ZERO_ERROR("'mpq' division or modulo by zero"); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } if (!(r = PyTuple_New(2)) || !(rq = (PympqObject*)Pympq_new()) || !(qz = (PympzObject*)Pympz_new())) { Py_XDECREF((PyObject*)r); Py_XDECREF((PyObject*)rq); Py_XDECREF((PyObject*)qz); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); return NULL; } mpq_div(rq->q, paq->q, pbq->q); mpz_fdiv_q(qz->z, mpq_numref(rq->q), mpq_denref(rq->q)); /* Need to calculate paq - rz * pbq */ mpq_set_z(rq->q, qz->z); mpq_mul(rq->q, rq->q, pbq->q); mpq_sub(rq->q, paq->q, rq->q); Py_DECREF((PyObject*)paq); Py_DECREF((PyObject*)pbq); PyTuple_SET_ITEM(r, 0, (PyObject*)qz); PyTuple_SET_ITEM(r, 1, (PyObject*)rq); return r; } #ifdef WITHMPFR if (isReal(a) && isReal(b)) { paf = Pympfr_From_Real(a, 0); pbf = Pympfr_From_Real(b, 0); if (!paf || !pbf) { SYSTEM_ERROR("Can not convert Real to 'mpfr'"); Py_XDECREF((PyObject*)paf); Py_XDECREF((PyObject*)pbf); return NULL; } if (mpfr_zero_p(pbf->f)) { context->ctx.divzero = 1; if (context->ctx.trap_divzero) { GMPY_DIVZERO("'mpfr' division by zero in divmod"); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } } if (!(r = PyTuple_New(2)) || !(qf = (PympfrObject*)Pympfr_new(0)) || !(rf = (PympfrObject*)Pympfr_new(0))) { Py_XDECREF(r); Py_XDECREF((PyObject*)qf); Py_XDECREF((PyObject*)rf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } mpfr_clear_flags(); if (mpfr_nan_p(paf->f) || mpfr_nan_p(pbf->f) || mpfr_inf_p(paf->f)) { context->ctx.invalid = 1; if (context->ctx.trap_invalid) { GMPY_INVALID("'mpfr' invalid operation in divmod"); Py_DECREF(r); Py_DECREF((PyObject*)qf); Py_DECREF((PyObject*)rf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } else { mpfr_set_nan(qf->f); mpfr_set_nan(rf->f); } } else if (mpfr_inf_p(pbf->f)) { context->ctx.invalid = 1; if (context->ctx.trap_invalid) { GMPY_INVALID("'mpfr' invalid operation in divmod"); Py_DECREF(r); Py_DECREF((PyObject*)qf); Py_DECREF((PyObject*)rf); Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); return NULL; } else { if (mpfr_zero_p(paf->f)) { mpfr_set_zero(qf->f, mpfr_sgn(pbf->f)); mpfr_set_zero(rf->f, mpfr_sgn(pbf->f)); } else if ((mpfr_signbit(paf->f)) != (mpfr_signbit(pbf->f))) { mpfr_set_si(qf->f, -1, context->ctx.mpfr_round); mpfr_set_inf(rf->f, mpfr_sgn(pbf->f)); } else { mpfr_set_si(qf->f, 0, context->ctx.mpfr_round); rf->rc = mpfr_set(rf->f, paf->f, context->ctx.mpfr_round); } } } else { mpfr_div(qf->f, paf->f, pbf->f, MPFR_RNDD); mpfr_floor(qf->f, qf->f); rf->rc = mpfr_fms(rf->f, qf->f, pbf->f, paf->f, context->ctx.mpfr_round); mpfr_neg(rf->f, rf->f, context->ctx.mpfr_round); } Py_DECREF((PyObject*)paf); Py_DECREF((PyObject*)pbf); SUBNORMALIZE(rf); SUBNORMALIZE(qf); MERGE_FLAGS; if (mpfr_underflow_p() && context->ctx.trap_underflow) { GMPY_UNDERFLOW("'mpfr' underflow in divmod"); Py_DECREF((PyObject*)rf); Py_DECREF((PyObject*)qf); Py_DECREF(r); return NULL; } if (mpfr_overflow_p() && context->ctx.trap_overflow) { GMPY_OVERFLOW("'mpfr' overflow in divmod"); Py_DECREF((PyObject*)rf); Py_DECREF((PyObject*)qf); Py_DECREF(r); return NULL; } if (mpfr_inexflag_p() && context->ctx.trap_inexact) { GMPY_INEXACT("'mpfr' inexact result in divmod"); Py_DECREF((PyObject*)rf); Py_DECREF((PyObject*)qf); Py_DECREF(r); return NULL; } PyTuple_SET_ITEM(r, 0, (PyObject*)qf); PyTuple_SET_ITEM(r, 1, (PyObject*)rf); return r; } #endif #ifdef WITHMPC if (isComplex(a) && isComplex(b)) { TYPE_ERROR("can't take floor or mod of complex number."); return NULL; } #endif Py_RETURN_NOTIMPLEMENTED; } gmpy2-2.0.7/src/gmpy_args.h0000666000000000000000000005551012564432250014221 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy_args.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Various macros for parsing arguments. */ #ifndef GMPY_ARG_H #define GMPY_ARG_H #ifdef __cplusplus extern "C" { #endif /* * Create two 'mpz' and a 2-tuple. */ #define CREATE_TWO_MPZ_TUPLE(q, r, t) \ q = (PympzObject*)Pympz_new(); \ r = (PympzObject*)Pympz_new(); \ t = PyTuple_New(2); \ if (!q || !r || !t) { \ Py_XDECREF(t); \ Py_XDECREF((PyObject*)q); \ Py_XDECREF((PyObject*)r); \ return NULL; \ } /* * Parses one, and only one, argument into "self" and converts it to an * mpz. Is faster, but not as generic, as using PyArg_ParseTuple. It * supports either gmpy.fname(z) or z.fname(). "self" must be decref'ed. * "msg" should be an error message that includes the function name and * describes the required arguments. Replaces SELF_MPZ_NO_ARG. * * Also considers an 'xmpz' to be equivalent to an 'mpz'. */ #define PARSE_ONE_MPZ(msg) \ if (self && CHECK_MPZANY(self)) { \ if (PyTuple_GET_SIZE(args) != 0) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ Py_INCREF(self); \ } else { \ if (PyTuple_GET_SIZE(args) != 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if(CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* * Parses one, and only one, argument into "self" and converts it to an * mpfr. Is faster, but not as generic, as using PyArg_ParseTuple. It * supports either gmpy.fname(z) or z.fname(). "self" must be decref'ed. * "msg" should be an error message that includes the function name and * describes the required arguments. It assumes the functions is declared * as either METH_O or METH_NOARGS. It is faster than PARSE_ONE_MPFR and * passing a tuple as args. */ #define PARSE_ONE_MPFR_OTHER(msg) \ if (self && Pympfr_Check(self)) { \ if (Pympfr_CheckAndExp(self)) { \ Py_INCREF(self); \ } \ else if (!(self = (PyObject*)Pympfr_From_Real(self, 0))) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ else if (other && Pympfr_CheckAndExp(other)) { \ self = other; \ Py_INCREF((PyObject*)self); \ } \ else if (!(self = (PyObject*)Pympfr_From_Real(other, 0))) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } /* * Parses one argument into "self" and an optional second argument into * "var". The second argument is converted into a C long. If there is not a * second argument, "var" is unchanged. Is faster, but not as generic, as * using PyArg_ParseTuple with "|l". It supports either gmpy.fname(z,l) or * z.fname(l). "self" must be decref'ed. "var" must be a pointer to a long. * "msg" should be an error message that includes the function name and * describes the required arguments. Replaces some uses of SELF_MPZ_ONE_ARG. * * Also considers an 'xmpz' to be equivalent to an 'mpz'. */ #define PARSE_ONE_MPZ_OPT_CLONG(var, msg) \ if (self && CHECK_MPZANY(self)) { \ if (PyTuple_GET_SIZE(args) == 1) { \ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ else if (PyTuple_GET_SIZE(args) > 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) == 2) { \ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ else if (PyTuple_GET_SIZE(args) == 1) { \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ else { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* Parses one argument into "self" and an optional second argument into * "var". The second argument is converted into an mpir_si. If there is not a * second argument, "var" is unchanged. It supports either gmpy.fname(z,l) or * z.fname(l). "self" must be decref'ed. "var" must be a pointer to an mpir_si. * "msg" should be an error message that includes the function name and * describes the required arguments. Replaces some uses of SELF_MPZ_ONE_ARG. * * Also considers an 'xmpz' to be equivalent to an 'mpz'. */ #define PARSE_ONE_MPZ_OPT_SI(var, msg) \ if (self && CHECK_MPZANY(self)) { \ if (PyTuple_GET_SIZE(args) == 1) { \ *var = SI_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ else if (PyTuple_GET_SIZE(args) > 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) == 2) { \ *var = SI_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ else if (PyTuple_GET_SIZE(args) == 1) { \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ else { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* * Parses one argument into "self" and an optional second argument into "var". * The second argument is converted into a Py_ssize_t. If there is not a * second argument, "var" is unchanged. Is faster, but not as generic, as * using PyArg_ParseTuple with "|l". It supports either gmpy.fname(z,l) or * z.fname(l). "self" must be decref'ed. "var" must be a pointer to a * Py_ssize_t. "msg" should be an error message that includes the function * name and describes the required arguments. Replaces some uses of * SELF_MPZ_ONE_ARG. * * Also considers an 'xmpz' to be equivalent to an 'mpz'. */ #define PARSE_ONE_MPZ_OPT_SSIZE_T(var, msg) \ if (self && CHECK_MPZANY(self)) { \ if (PyTuple_GET_SIZE(args) == 1) { \ *var = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if(*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ else if (PyTuple_GET_SIZE(args) > 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) == 2) { \ *var = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ else if (PyTuple_GET_SIZE(args) == 1) { \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ else { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* * Parses one argument into "self" and an optional second argument into * "var". The second argument is converted into a C long. If there is not a * second argument, "var" is unchanged. Is faster, but not as generic, as * using PyArg_ParseTuple with "|l". It supports either gmpy.fname(z,l) or * z.fname(l). "self" must be decref'ed. "var" must be a pointer to a long. * "msg" should be an error message that includes the function name and * describes the required arguments. Replaces some uses of SELF_MPF_ONE_ARG. */ #define PARSE_ONE_MPFR_OPT_CLONG(var, msg) \ if (self && Pympfr_CheckAndExp(self)) { \ if (PyTuple_GET_SIZE(args) == 1) { \ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ else if (PyTuple_GET_SIZE(args) > 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) == 2) { \ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if (Pympfr_CheckAndExp(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympfr_From_Real(PyTuple_GET_ITEM(args, 0), 0); \ } \ } \ else if (PyTuple_GET_SIZE(args) == 1) { \ self = PyTuple_GET_ITEM(args, 0); \ if(Pympfr_CheckAndExp(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympfr_From_Real(self, 0); \ } \ } \ else { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* * Parses one argument into "self" and a required second argument into * "var". The second argument is converted into a C long. Is faster, but not * as generic, as using PyArg_ParseTuple with "l". It supports either * gmpy.fname(z,l) or z.fname(l). "self" must be decref'ed. "var" must be a * pointer to a long. "msg" should be an error message that includes the * function name and describes the required arguments. Replaces some uses of * SELF_MPZ_ONE_ARG. * * Also considers an 'xmpz' to be equivalent to an 'mpz'. */ #define PARSE_ONE_MPZ_REQ_CLONG(var, msg) \ if (self && CHECK_MPZANY(self)) { \ if (PyTuple_GET_SIZE(args) != 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ else { \ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) != 2) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ else {\ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* Parses one argument into "self" and a required second argument into * "var". The second argument is converted into an mpir_si. It supports either * gmpy.fname(z,l) or z.fname(l). "self" must be decref'ed. "var" must be a * pointer to an mpir_si. "msg" should be an error message that includes the * function name and describes the required arguments. Replaces some uses of * SELF_MPZ_ONE_ARG. * * Also considers an 'xmpz' to be equivalent to an 'mpz'. */ #define PARSE_ONE_MPZ_REQ_SI(var, msg) \ if (self && CHECK_MPZANY(self)) { \ if (PyTuple_GET_SIZE(args) != 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ else { \ *var = SI_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) != 2) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ else { \ *var = SI_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if (CHECK_MPZANY(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ } \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* * Parses one argument into "self" and a required second argument into * "var". The second argument is converted into a C long. Is faster, but not * as generic, as using PyArg_ParseTuple with "l". It supports either * gmpy.fname(z,l) or z.fname(l). "self" must be decref'ed. "var" must be a * pointer to a long. "msg" should be an error message that includes the * function name and describes the required arguments. */ #define PARSE_ONE_MPFR_REQ_CLONG(var, msg) \ if (self && Pympfr_CheckAndExp(self)) { \ if (PyTuple_GET_SIZE(args) != 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ else {\ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) != 2) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ else { \ *var = clong_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (*var == -1 && PyErr_Occurred()) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = PyTuple_GET_ITEM(args, 0); \ if (Pympfr_CheckAndExp(self)) { \ Py_INCREF((PyObject*)self); \ } \ else { \ self = (PyObject*)Pympfr_From_Real(PyTuple_GET_ITEM(args, 0), 0); \ } \ } \ if (!self) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ } /* * Parses two, and only two, arguments into "self" and "var" and converts * them both to mpz. Is faster, but not as generic, as using PyArg_ParseTuple. * It supports either gmpy.fname(z,z) or z.fname(z). "self" & "var" must be * decref'ed after use. "msg" should be an error message that includes the * function name and describes the required arguments. Replaces * SELF_MPZ_ONE_ARG_CONVERTED(var). * * Also considers an 'xmpz' to be equivalent to an 'mpz'. */ #define PARSE_TWO_MPZ(var, msg) \ if (self && CHECK_MPZANY(self)) { \ if (PyTuple_GET_SIZE(args) != 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ var = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ if (!var) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) != 2) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); \ var = (PyObject*)Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); \ if (!self || !var) { \ PyErr_SetString(PyExc_TypeError, msg); \ Py_XDECREF((PyObject*)self); \ Py_XDECREF((PyObject*)var); \ return NULL; \ } \ } #define PARSE_TWO_MPQ(var, msg) \ if (self && Pympq_Check(self)) { \ if (PyTuple_GET_SIZE(args) != 1) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ var = (PyObject*)Pympq_From_Rational(PyTuple_GET_ITEM(args, 0)); \ if (!var) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ Py_INCREF(self); \ } \ else { \ if (PyTuple_GET_SIZE(args) != 2) { \ PyErr_SetString(PyExc_TypeError, msg); \ return NULL; \ } \ self = (PyObject*)Pympq_From_Rational(PyTuple_GET_ITEM(args, 0)); \ var = (PyObject*)Pympq_From_Rational(PyTuple_GET_ITEM(args, 1)); \ if (!self || !var) { \ PyErr_SetString(PyExc_TypeError, msg); \ Py_XDECREF((PyObject*)self); \ Py_XDECREF((PyObject*)var); \ return NULL; \ } \ } /* * Parses two, and only two, arguments into "self" and "var" and converts * them both to mpfR. Is faster, but not as generic, as using PyArg_ParseTuple. * It supports either gmpy.fname(f,f) or f.fname(f). "self" & "var" must be * decref'ed after use. "msg" should be an error message that includes the * function name and describes the required arguments. Replaces * SELF_MPF_ONE_ARG_CONVERTED(var). */ #define PARSE_TWO_MPFR_ARGS(var, msg) \ if (self && Pympfr_Check(self)) { \ if (PyTuple_GET_SIZE(args) != 1) { \ TYPE_ERROR(msg); \ return NULL; \ } \ self = (PyObject*)Pympfr_From_Real(self, 0); \ var = (PyObject*)Pympfr_From_Real(PyTuple_GET_ITEM(args, 0), 0); \ } \ else { \ if (PyTuple_GET_SIZE(args) != 2) { \ TYPE_ERROR(msg); \ return NULL; \ } \ self = (PyObject*)Pympfr_From_Real(PyTuple_GET_ITEM(args, 0), 0); \ var = (PyObject*)Pympfr_From_Real(PyTuple_GET_ITEM(args, 1), 0); \ } \ if (!self || !var) { \ TYPE_ERROR(msg); \ Py_XDECREF((PyObject*)var); \ Py_XDECREF((PyObject*)self); \ return NULL; \ } /* Define three different versions of the SELF_NO_ARG macro. Under Python 2.x, self is NULL when a function is called via gmpy.fname(..). But under Python 3.x, self is a module. */ #define SELF_MPQ_NO_ARG \ if (self && Pympq_Check(self)) { \ if(!PyArg_ParseTuple(args, "")) \ return NULL; \ Py_INCREF(self); \ } \ else { \ if(!PyArg_ParseTuple(args, "O&", Pympq_convert_arg, &self)) \ return NULL; \ } #define SELF_MPQ_ONE_ARG(fm, var) \ if (self && Pympq_Check(self)) { \ if (!PyArg_ParseTuple(args, fm, var)) \ return NULL; \ Py_INCREF(self); \ } \ else { \ if (!PyArg_ParseTuple(args, "O&" fm, Pympq_convert_arg, &self, var)) \ return NULL; \ } #ifdef __cplusplus } #endif #endif /* !defined(Py_GMPYMODULE_H */ gmpy2-2.0.7/src/gmpy2.c0000666000000000000000000013434612564432250013267 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy2.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * originally written for GMP-2.0 (by AMK...?) * Rewritten by Niels Möller, May 1996 * * Version for GMP-4, Python 2.X, with support for MSVC++6, * addition of mpf's, &c: Alex Martelli (now aleaxit@gmail.com, Nov 2000). * cleanups & reorgs leading to 1.0: Alex Martelli (until Aug 2003) * further cleanups and bugfixes leading to 1.01, Alex Martelli (Nov 2005) * minor bugfixes+new decimal (&c) support to 1.02, Alex Martelli (Feb 2006) * various bugfixes for 64-bit platforms, 1.03, aleaxit and casevh (Jun 2008) * rich comparisons, 1.04, aleaxit and casevh (Jan 2009) * support for Python 3.x, 1.10, casevh (Oct 2009) * * Some hacks by Gustavo Niemeyer . * * 0.1, pre-alpha; date: 2000-11-06 first placed on sourceforge * * 0.2, still pre-alpha: 2000-11-15: bugfixes re formatting (tx, Peanu!) * no tags on oct() and hex() of mpz's * insert 'tagoff' in options (gmpy.mpz() vs mpz() in repr) (for Peanu!) * speedups for _nonzero & _cmp (tx, Peanu!) * slight speedup (7/8%?) for excess reallocs 4<->8 bytes (Peanu's help!) * added copy/fcopy; bin; fib; remove * * 0.3, still pre-alpha, but...: * performance tweaks via mpz-caching & fixed-constants * added get/set functions for zcache, zco min/max * added get-only function for versions (of gmp, and of gmpy) * removed all 'traces' of mutability (to be re-done... much later!) * cleaned up all of the mpz_cmp_ui(X,0) to mpz_sgn(X) * cleaned up Py_BuildValue usage (N vs O, explicit-() for tuples) * added numdigits, lowbits, root, next_prime, invert, popcount, * hamdist, scan0, scan1 * renamed bin to bincoef * * 0.4: * split gmpy.c/gmpy.h introducing C-API interface (Pearu's suggestion) * cleanup some casts using Pearu's new macros * further cache-tweaks at Pearu's suggestion (macros introduced) * added sign (Pearu's request), getbit, setbit * added docstrings * renamed copy functions to start with _ ('internal, private') * added .comb as a synonym of .bincoef * * 0.5: * added jacobi, legendre, kronecker * added random-number generation, seed set/save, shuffling * added mpq (at last!-) * * 0.6: (lots of good ideas from Pearu once more!-): * fixed silly bugs in kronecker and mpq_abs * gmpy-level workaround for scan0/scan1 bugs (?) in GMP 3.1.1 * added qdiv; anynum->mpq substituted for all such conversions * (also anynum->mpz and anynum->mpf by analogy, with care!) * added global.fcoform for optional use of intermediate string in * float2mpf (used for any float->mpf conversion) * added set_fcoform function for global.fcoform access * general cleanup of sources; added alloca for MSVC++; * many sundry minor bugfixes & uniformization; * a little useful refactoring (more would be good...) * added caching of mpq objects * power for mpq * Stern-Brocot algorithm for mpf->mpq (also exposed as f2q) * also used for float->mpq * with stricter tracking of mpf's requested-precision * added getrprec method to mpf, getrprec module-function * exposed ceil, floor and trunc methods/functions for mpf's * changed a couple exceptions from Value to ZeroDivision * added 'qual' and 'floa' options to gmpy.rand * * 0.7: (good feedback from Keith Briggs, some advice from Tim Peters * and Fred Lundh -- thanks all!): * fixed bug of '"%d" where "%ld" was meant' in many places * and other sundry minor warnings given by gcc * fixed hash (delegating to Python) so mp[nqz](x) will * produce the same value as hash(x) for any Python number x * workaround for GMP 3.1.1 bug, mpz_root wrongly returning * 'exact' for non-exact root if dest==source, which stopped * needed value-error for inexact mpq**mpq operations * determined correct 'actual precision' of floats * explicitly stored precision with binary-form mpf's * extended explicit-bits request to all ->mpf operations * (good in itself, plus, preparing for future MPFR) * removed the limitation of no binary-form for <0 mpz * introduced macros to parse args, for conciseness * * 0.8: (again, requests & suggestions by great Pearu!) * raise test coverage 72.5% -> 90.0% * introduced callbacks (not documented/tested for now; * Pearu will test/support/document in PySymbolic) * some errors went undiagnosed, caused crash: now fixed * workaround for GMP bug(?s?) in mpz_fits_... (?) * added exposure of mpf_ sqrt and pow_ui * * 0.9: (ditto) * change ValueError to OverflowError for 'too-large' errors * fix bug in mpq_pow (negative base, exp. with odd denominator) * (fix now corrected -- _even_ denominator is the error!) * fixed gcc warnings reported by K. Briggs * * 0.9b: * support GMP 4 (but added no GMP4-only functionality yet) * * 0.9c: * updated tests to 0.9, better coverage * * 1.0: * minor cleanups, ensure support for Python 2.3 * fixed misdiagnosis of some argument counts in macro * SELF_ONE_ARG_CONVERTED (tx to Paul Rubin!) * * 1.01: * cleanups, ensure support for Python 2.4.1 on MacOSX 10.4/XCode 2.1 * as well as Python 2.2 and 2.3 (on MacOSX and Linux) * fixed memory leak on divm (thanks to mensanator@aol.com) * fixed bug on mpq('123') [[str2mpq on string w/o a slash]] * added floordiv and truediv operators, and tests for them * NOT tested on GMP 3 (have none left around...), ONLY on GMP 4.* * * 1.02: * fix warning in comparison of mpq's * added support of mpq('12.34') [[string w/o a slash, but with a dot]] * fixes for 64-bit build (thanks to a patch by dmcooke) * added experimental support for decimal.Decimal (and user-coded types) * via wider use of special conversion methods (if present) and their * sly insertion on-the-fly into the decimal.Decimal class (!) * two bugfixes, thanks to Simon Burton * Brought back into C89 compliance (thanks to Chip Turner), had * drifted to C99 (declarations in the middle of the code). * Python 2.5 support (Py_ssize_t, __index__) thanks to Chip Turner * Pushed coverage to 93.3% (missing only "sanity check" level error * tests [mostly for out-of-memory conditions], output to stderr * conditioned by global.debug, & a couple of very obscure cases) * * 1.03: * Fixed the bug that caused crashes on gmpy.mpf(float('inf')) and * other such conversions, implicit and explicit * Fixed a bug in get_zconst's prototype affecting 64-bit machines, * thanks to Gary Bunting * Fixed a bug in hashing on 64-bit systems. hash(long) now equals * hash(mpz) for large values. (casevh) * Changed int() to return a long value instead of OverFlowError. * Complies with PEP 237. (casevh) * Added support in setup.py for darwinports/macports build of GMP * on MacOSX. (aleaxit) * * 1.04: * Avoid GMP/mingw32 bug when converting very small floats to mpz. * (casevh) * Significant performance improvement for long->mpz and mpz->long. * (casevh) * Added "rich comparisons" to mpz, mpq and mpf types (aleaxit) * Added additional tests (casevh, aleaxit) * Fixed bug when converting very large mpz to str (casevh) * Faster conversion from mpz->binary and binary->mpz (casevh) * Added support for pickling (casevh) * Added divexact (casevh) * Fixed mpf comparisons by rounding mpf results when GMP returns * a longer result. Added fround() (casevh) * Added bit_length (Thanks Mario Pernici) * Added helper functions for mpmath (casevh) * Faster conversion from mpq->binary and binary->mpq (casevh) * Recognize MPIR, mpir_version() (casevh) * * 1.10: * Remove dependancy on pymemcompat.h (casevh) * Remove callback (casevh) * Added support for -DMPIR to include MPIR instead of GMP (casevh) * Major code revisions to add support for Python 3.x (casevh) * Fixed bug in binary() and qbinary() (casevh) * Fixed bug in rich comparisons (casevh) * Added % and divmod support to mpq and mpf (casevh) * Changed memory allocation functions to use PyMem (casevh) * Removed small number interning (casevh) * Added tdivmod, cdivmod, and fdivmod (casevh) * Added more helper functions for mpmath (casevh) * Faster mpz<>PyLong conversion (casevh) * Faster hash(mpz) (casevh) * * 1.11: * Recognize True/False (bug in 1.10) (casevh) * Optimize argument handling (casevh) * Added caching for mpz (casevh) * ************************************************************************ * * 2.0.0 alpha and b1: * Added caching for mpq (casevh) * Added rootrem, fib2, lucas, lucas2 (casevh) * Removed mpf.setprec(), use mpf.round() (casevh) * Fix test compatibility with Python 3.1.2 and 3.2 (casevh) * Support changed hash function in Python 3.2 (casevh) * Added is_even, is_odd (casevh) * Rename to gmpy2 to allow backwards incompatible changes (casevh) * Remove old random number functions, to be replaced later (casevh) * Add caching of the calculated hash value (casevh) * Add xmpz (mutable mpz) type (casevh) * Fix mpq formatting issue (casevh) * Add read/write bit access using slices to xmpz (casevh) * Add read-only bit access using slices to mpz (casevh) * Add pack()/unpack() methods (casevh) * Remove tagoff option (casevh) * Add support for MPFR (casevh) * Debug messages only available if compiled with -DDEBUG (casevh) * Removed fcoform float conversion modifier (casevh) * Add support for MPC (casevh) * Renamed 'mpf' to 'mpfr' to reflect use of MPFR (casevh) * Added context manager (casevh) * Allow building with just GMP/MPIR if MPFR not available (casevh) * Allow building with GMP/MPIR and MPFR if MPC not available (casevh) * Removed most instance methods in favor of gmpy2.method (casevh) * Added __ceil__, __floor__, and __trunc__ methods (casevh) * Removed gmpy2.pow to avoid conflicts (casevh) * Removed gmpy2._copy and added xmpz.copy (casevh) * Added support for __format__ (casevh) * Completed support for MPC (casevh) * Added as_integer_ratio, as_mantissa_exp, as_simple_fraction (casevh) * Update rich_compare (casevh) * Require MPFR 3.1.0+ to get divby0 support (casevh) * Added fsum(), degrees(), radians() (casevh) * Renamed context() -> local_context(), new_context() -> context() (casevh) * Added get_context() (casevh) * Added random number generation support (casevh) * Changed license to LGPL 3+ (casevh) * Added lucasu, lucasu_mod, lucasv, and lucasv_mod (casevh) * (Based on code contributed by David Cleaver.) * Added probable-prime tests (casevh) * (Based on code contributed by David Cleaver.) * Added to_binary()/from_binary (casevh) * Renamed numdigits() to num_digits() (casevh) * Added keyword precision to constants (casevh) * Added addmul() and submul() (casevh) * Added __round__(), round2(), round_away() for mpfr (casevh) * round() is no longer a module level function (casevh) * pow() is no longer a module level function (casevh) * Renamed module functions min()/max() to min2()/max2() (casevh) * No longer conflicts with builtin min() and max() * Removed set_debug() and related functionality (casevh) * Released as 2.0.0b1 * * 2.0.0b2 * Allow xmpz slice assignment to increase length of xmpz instance by * specifying a value for stop (casevh) * Fixed ref-count bug in several is_xxx_prp tests (casevh) * Added iter_bits, iter_clear, iter_set methods to xmpz (casevh) * Added powmod() for easy access to three argument pow() (casevh) * Removed addmul() and submul() since they are slower than (casevh) * just using Python code * Bug fix in gcd_ext when both arguments are not mpz (casevh) * Added ieee() to create contexts for 32, 64, or 128 bit floats (casevh) * Bug fix in context() not setting emax/emin correctly if they (casevh) * had been changed earlier * Contexts can be directly used in with statement without (casevh) * requiring set_context()/local_context() sequence * local_context() now accepts an optional context (casevh) * * 2.0.0b3 * mp_version(), mpc_version(), and mpfr_version() shouldn't (casevh) * return Unicode on Python 2.x * Fix warnings when shifting 32-bit integer by 32 bits (casevh) * Faster conversion of Fraction to gmpy2 types (casevh) * Fix conversion with Decimal, especially on Python 3.3 (casevh) * Consistently return OverflowError when converting "inf" (casevh) * Fix mpz.__format__() with # code (casevh) * Add is_infinite(), deprecate is_inf() (casevh) * Add is_finite(), deprecate is_number() (casevh) * Fixed issues with mpc() and various is_XXX() functions (casevh) * Fixed error handling with mpc(); mpc(1,"nan") is properly (casevh) * handled * Added caching for mpc objects; faster when real and (casevh) * imaginary precisions are equal * Add optimal path for mpfr/mpc + - * / when both operands (casevh) * have the same type * Fix mpfr + float segmentation fault (casevh) * * 2.0.0b4 * Add __ceil__, __floor__, __trunc__, __round__ to mpz & mpq (casevh) * Add __complex__ to mpc (casevh) * round(mpfr) now correctly returns an mpz (casevh) * Add mpz.denominator and mpz.numerator (casevh) * mpz() returns mpz(0); also xmpz, mpq, mpfr, and mpc (casevh) * Fix bug when comparing mpz to mpq (with mpz on left) (casevh) * Add __sizeof__ (casevh) * * 2.0.0 * Fix segfault in _mpmath_normalize if rnd not specified (casevh) * Improved setup.py (casevh) * Fix issues encountered when compiled without MPFR support (casevh) * Conversion of too large an mpz to float now raises OverflowError (casevh) * Renamed module functions min2()/max2() to minnum()/maxnum() (casevh) * Added copy() method to contexts (casevh) * get_context() no longer supports keyword arguments (casevh) * * 2.0.1 * Updated setup.py (casevh) * Added missing mpfr_clear_flags() to Pympfr_*_fast (casevh) * Fixed exception not raised for Invalid Operation (casevh) * invert() now raises exception if inverse does not exist (casevh) * Fixed is_bpsw_prp() and is_strong_pbsw_prp() (casevh) * Fixed is_extra_strong_lucas_prp() (casevh) * * 2.0.2 * Rebuild Windows binary installers due to MPIR 2.6.0 bug in next_prime(). * Another fix for is_extra_strong_lucas_prp(). * * 2.0.3 * Fix lucas2 (casevh) * Fix atanh (casevh) * * 2.0.4b1 * Fix bit_scan0 for negative values (casevh) * Changes to setup.py to allow static linking (casevh) * Fix performance regression with mpmath and Python 3 (casevh) * * 2.0.4 * Fix bug in divm() that can mutate input (casevh) * * 2.0.5 * Fix crashing bug in repr(mpc) for precision >325 bits (casevh) * Fix bug in qdiv() when denominator is a Python long larger than a * C long (casevh) * * 2.0.6 * Fix setup.py to not override --prefix (casevh) * * 2.0.7 * Fix math.floor(gmpy2.mpfr('inf')) to not segfault (casevh) * ************************************************************************ * * Discussion on sizes of C integer types. * * GMP, MPIR, MPFR, and MPC use typedef to create integer objects with * different sizes. It can become confusing to map the different types * onto the standard C types used by Python's C API. Below are external * types and how the map to C types. The assumptions are verified when * the module is initialized. * * mp_limb_t: This is usually an 'unsigned long' but is an 'unsigned * long long' on MPIR/64-bit Windows. * * mp_bitcnt_t: This is usually an 'unsigned long' but is an 'unsigned * long long' on MPIR/64-bit Windows. 'size_t' is probably the best * match since that is the return type of mpz_sizeinbase(). * * mp_size_t: This is a 'long'. * * mp_exp_t: This is defined by GMP to be a 'long'. * * mpfr_rnd_t: This is an 'int' ??? * * mpfr_prec_t: This can be 'short', 'int', or 'long'. GMPY assumes it * will be a 'long'. * * mpfr_sign_t: This is an 'int'. * * mpfr_exp_t: This is currently the same as mp_exp_t but will change * to a signed 64-bit integer in the future. * * mpc_rnd_t: This is an 'int'. * * mpc_prec_t: See mpfr_exp_t. * ************************************************************************ */ #define PY_SSIZE_T_CLEAN #include "Python.h" /* * we do have a dependence on Python's internals, specifically: * how Python "long int"s are internally represented. */ #include "longintrepr.h" #include #include #include #include #include /* Include functions missing from the Python 2.6 C-API that are include * in later versions of Python. */ #if ((PY_VERSION_HEX < 0x02070000) || ((PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION < 2))) #include "py3intcompat.c" #endif #include "gmpy.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Global data declarations begin here. * * NOTE: Because of these global declarations, GMPY2 is not thread-safe! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* The following global strings are used by gmpy_misc.c. */ char gmpy_version[] = "2.0.7"; char _gmpy_cvs[] = "$Id: gmpy2.c 1043 2015-08-18 04:22:42Z casevh $"; char gmpy_license[] = "\ The GMPY2 source code is licensed under LGPL 3 or later. The supported \ versions of the GMP/MPIR, MPFR, and MPC libraries are also licensed under \ LGPL 3 or later."; /* The following global structures are used by gmpy_cache.c. */ static struct gmpy_global { int cache_size; /* size of cache, for all caches */ int cache_obsize; /* maximum size of the objects that are cached */ } global = { 100, /* cache_size */ 128, /* cache_obsize */ }; static mpz_t* zcache; static int in_zcache; static PympzObject **pympzcache; static int in_pympzcache; static PyxmpzObject **pyxmpzcache; static int in_pyxmpzcache; static PympqObject **pympqcache; static int in_pympqcache; #ifdef WITHMPFR static PympfrObject **pympfrcache; static int in_pympfrcache; /* Support for context manager. */ static GMPyContextObject *context = NULL; /* Define gmpy2 specific errors for mpfr and mpc data types. No change will * be made the exceptions raised by mpz, xmpz, and mpq. */ static PyObject *GMPyExc_GmpyError = NULL; static PyObject *GMPyExc_DivZero = NULL; static PyObject *GMPyExc_Inexact = NULL; static PyObject *GMPyExc_Invalid = NULL; static PyObject *GMPyExc_Overflow = NULL; static PyObject *GMPyExc_Underflow = NULL; static PyObject *GMPyExc_Erange = NULL; static PyObject *GMPyExc_ExpBound = NULL; #endif #ifdef WITHMPC static PympcObject **pympccache; static int in_pympccache; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * End of global data declarations. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* The code for object creation, deletion, and caching is in gmpy_cache.c. */ #include "gmpy_cache.c" /* Miscellaneous helper functions and simple methods are in gmpy_misc.c. */ #include "gmpy_misc.c" /* Include fast mpz to/from PyLong conversion from sage. */ #include "mpz_pylong.c" /* Support for conversion to/from binary representation. */ #include "gmpy_binary.c" /* Support for conversions to/from numeric types. */ #include "gmpy_convert.c" /* Support primitive arithmetic operations. */ #include "gmpy_basic.c" /* Include the module-level methods that call the type-specific methods. */ #include "gmpy_mpany.c" /* Support for random numbers. */ #include "gmpy_random.c" /* Support for Lucas sequences. */ #include "gmpy_mpz_lucas.c" /* Support for probable-prime tests. */ #include "gmpy_mpz_prp.c" /* Include helper functions for mpmath. */ #include "gmpy_mpmath.c" #include "gmpy_mpz_inplace.c" #include "gmpy_xmpz_inplace.c" #include "gmpy_mpz_divmod2exp.c" #include "gmpy_mpz_divmod.c" #include "gmpy_mpz.c" #include "gmpy_xmpz.c" #include "gmpy_mpq.c" #ifdef WITHMPFR #include "gmpy_context.c" #include "gmpy_mpfr.c" #endif #ifdef WITHMPC #include "gmpy_mpc.c" #endif static PyMethodDef Pygmpy_methods [] = { { "_cvsid", Pygmpy_get_cvsid, METH_NOARGS, doc_cvsid }, { "_printf", Pympany_printf, METH_VARARGS, doc_printf }, { "add", Pympany_add, METH_VARARGS, doc_mpany_add }, { "bit_clear", Pygmpy_bit_clear, METH_VARARGS, doc_bit_clearg }, { "bit_flip", Pygmpy_bit_flip, METH_VARARGS, doc_bit_flipg }, { "bit_length", Pympz_bit_length, METH_O, doc_bit_lengthg }, { "bit_mask", Pympz_bit_mask, METH_O, doc_bit_maskg }, { "bit_scan0", Pympz_bit_scan0, METH_VARARGS, doc_bit_scan0g }, { "bit_scan1", Pympz_bit_scan1, METH_VARARGS, doc_bit_scan1g }, { "bit_set", Pygmpy_bit_set, METH_VARARGS, doc_bit_setg }, { "bit_test", Pygmpy_bit_test, METH_VARARGS, doc_bit_testg }, { "bincoef", Pympz_bincoef, METH_VARARGS, doc_bincoefg }, { "comb", Pympz_bincoef, METH_VARARGS, doc_combg }, { "c_div", Pygmpy_c_div, METH_VARARGS, doc_gmpy_c_div }, { "c_div_2exp", Pygmpy_c_div_2exp, METH_VARARGS, doc_gmpy_c_div_2exp }, { "c_divmod", Pygmpy_c_divmod, METH_VARARGS, doc_gmpy_c_divmod }, { "c_divmod_2exp", Pygmpy_c_divmod_2exp, METH_VARARGS, doc_gmpy_c_divmod_2exp }, { "c_mod", Pygmpy_c_mod, METH_VARARGS, doc_gmpy_c_mod }, { "c_mod_2exp", Pygmpy_c_mod_2exp, METH_VARARGS, doc_gmpy_c_mod_2exp }, { "denom", Pympq_denom, METH_VARARGS, doc_denomg }, { "digits", Pympany_digits, METH_VARARGS, doc_g_mpany_digits }, { "div", Pympany_div, METH_VARARGS, doc_mpany_div }, { "divexact", Pygmpy_divexact, METH_VARARGS, doc_divexactg }, { "divm", Pygmpy_divm, METH_VARARGS, doc_divm }, { "fac", Pygmpy_fac, METH_O, doc_fac }, { "fib", Pygmpy_fib, METH_O, doc_fib }, { "fib2", Pygmpy_fib2, METH_O, doc_fib2 }, { "from_binary", Pympany_From_Binary, METH_O, doc_from_binary }, { "f_div", Pygmpy_f_div, METH_VARARGS, doc_gmpy_f_div }, { "f_div_2exp", Pygmpy_f_div_2exp, METH_VARARGS, doc_gmpy_f_div_2exp }, { "f_divmod", Pygmpy_f_divmod, METH_VARARGS, doc_gmpy_f_divmod }, { "f_divmod_2exp", Pygmpy_f_divmod_2exp, METH_VARARGS, doc_gmpy_f_divmod_2exp }, { "f_mod", Pygmpy_f_mod, METH_VARARGS, doc_gmpy_f_mod }, { "f_mod_2exp", Pygmpy_f_mod_2exp, METH_VARARGS, doc_gmpy_f_mod_2exp }, { "gcd", Pygmpy_gcd, METH_VARARGS, doc_gcd }, { "gcdext", Pygmpy_gcdext, METH_VARARGS, doc_gcdext }, { "get_cache", Pygmpy_get_cache, METH_NOARGS, doc_get_cache }, { "hamdist", Pympz_hamdist, METH_VARARGS, doc_hamdistg }, { "invert", Pygmpy_invert, METH_VARARGS, doc_invertg }, { "isqrt", Pympz_isqrt, METH_O, doc_mpz_isqrt }, { "isqrt_rem", Pympz_isqrt_rem, METH_VARARGS, doc_mpz_isqrt_rem }, { "is_bpsw_prp", GMPY_mpz_is_bpsw_prp, METH_VARARGS, doc_mpz_is_bpsw_prp }, { "is_even", Pympz_is_even, METH_O, doc_is_eveng }, { "is_euler_prp", GMPY_mpz_is_euler_prp, METH_VARARGS, doc_mpz_is_euler_prp }, { "is_extra_strong_lucas_prp", GMPY_mpz_is_extrastronglucas_prp, METH_VARARGS, doc_mpz_is_extrastronglucas_prp }, { "is_fermat_prp", GMPY_mpz_is_fermat_prp, METH_VARARGS, doc_mpz_is_fermat_prp }, { "is_fibonacci_prp", GMPY_mpz_is_fibonacci_prp, METH_VARARGS, doc_mpz_is_fibonacci_prp }, { "is_lucas_prp", GMPY_mpz_is_lucas_prp, METH_VARARGS, doc_mpz_is_lucas_prp }, { "is_odd", Pympz_is_odd, METH_O, doc_is_oddg }, { "is_power", Pympz_is_power, METH_O, doc_is_powerg }, { "is_prime", Pympz_is_prime, METH_VARARGS, doc_is_primeg }, { "is_selfridge_prp", GMPY_mpz_is_selfridge_prp, METH_VARARGS, doc_mpz_is_selfridge_prp }, { "is_square", Pympz_is_square, METH_O, doc_is_squareg }, { "is_strong_prp", GMPY_mpz_is_strong_prp, METH_VARARGS, doc_mpz_is_strong_prp }, { "is_strong_bpsw_prp", GMPY_mpz_is_strongbpsw_prp, METH_VARARGS, doc_mpz_is_strongbpsw_prp }, { "is_strong_lucas_prp", GMPY_mpz_is_stronglucas_prp, METH_VARARGS, doc_mpz_is_stronglucas_prp }, { "is_strong_selfridge_prp", GMPY_mpz_is_strongselfridge_prp, METH_VARARGS, doc_mpz_is_strongselfridge_prp }, { "jacobi", Pympz_jacobi, METH_VARARGS, doc_jacobig }, { "kronecker", Pympz_kronecker, METH_VARARGS, doc_kroneckerg }, { "lcm", Pygmpy_lcm, METH_VARARGS, doc_lcm }, { "legendre", Pympz_legendre, METH_VARARGS, doc_legendreg }, { "license", Pygmpy_get_license, METH_NOARGS, doc_license }, { "lucas", Pygmpy_lucas, METH_O, doc_lucas }, { "lucasu", GMPY_mpz_lucasu, METH_VARARGS, doc_mpz_lucasu }, { "lucasu_mod", GMPY_mpz_lucasu_mod, METH_VARARGS, doc_mpz_lucasu_mod }, { "lucasv", GMPY_mpz_lucasv, METH_VARARGS, doc_mpz_lucasv }, { "lucasv_mod", GMPY_mpz_lucasv_mod, METH_VARARGS, doc_mpz_lucasv_mod }, { "lucas2", Pygmpy_lucas2, METH_O, doc_lucas2 }, { "mp_version", Pygmpy_get_mp_version, METH_NOARGS, doc_mp_version }, { "mp_limbsize", Pygmpy_get_mp_limbsize, METH_NOARGS, doc_mp_limbsize }, { "mpc_version", Pygmpy_get_mpc_version, METH_NOARGS, doc_mpc_version }, { "mpfr_version", Pygmpy_get_mpfr_version, METH_NOARGS, doc_mpfr_version }, { "mpq", (PyCFunction)Pygmpy_mpq, METH_VARARGS | METH_KEYWORDS, doc_mpq }, { "mpq_from_old_binary", Pympq_From_Old_Binary, METH_O, doc_g_mpq_from_old_binary }, { "mpz", (PyCFunction)Pygmpy_mpz, METH_VARARGS | METH_KEYWORDS, doc_mpz }, { "mpz_from_old_binary", Pympz_From_Old_Binary, METH_O, doc_g_mpz_from_old_binary }, { "mpz_random", GMPY_mpz_random, METH_VARARGS, doc_mpz_random }, { "mpz_rrandomb", GMPY_mpz_rrandomb, METH_VARARGS, doc_mpz_rrandomb }, { "mpz_urandomb", GMPY_mpz_urandomb, METH_VARARGS, doc_mpz_urandomb }, { "mul", Pympany_mul, METH_VARARGS, doc_mpany_mul }, { "next_prime", Pympz_next_prime, METH_O, doc_next_primeg }, { "numer", Pympq_numer, METH_VARARGS, doc_numerg }, { "num_digits", Pympz_num_digits, METH_VARARGS, doc_num_digitsg }, { "pack", Pygmpy_pack, METH_VARARGS, doc_gmpy_pack }, { "popcount", Pympz_popcount, METH_O, doc_popcountg }, { "powmod", Pympz_powmod, METH_VARARGS, doc_gmpy_powmod }, { "qdiv", Pympq_qdiv, METH_VARARGS, doc_qdivg }, { "remove", Pympz_remove, METH_VARARGS, doc_removeg }, { "iroot", Pympz_iroot, METH_VARARGS, doc_mpz_iroot }, { "iroot_rem", Pympz_iroot_rem, METH_VARARGS, doc_mpz_iroot_rem }, { "random_state", GMPY_random_state, METH_VARARGS, doc_random_state }, { "set_cache", Pygmpy_set_cache, METH_VARARGS, doc_set_cache }, { "sign", Pympany_sign, METH_O, doc_g_mpany_sign }, { "square", Pympany_square, METH_O, doc_mpany_square }, { "sub", Pympany_sub, METH_VARARGS, doc_mpany_sub }, { "to_binary", Pympany_to_binary, METH_O, doc_to_binary }, { "t_div", Pygmpy_t_div, METH_VARARGS, doc_gmpy_t_div }, { "t_div_2exp", Pygmpy_t_div_2exp, METH_VARARGS, doc_gmpy_t_div_2exp }, { "t_divmod", Pygmpy_t_divmod, METH_VARARGS, doc_gmpy_t_divmod }, { "t_divmod_2exp", Pygmpy_t_divmod_2exp, METH_VARARGS, doc_gmpy_t_divmod_2exp }, { "t_mod", Pygmpy_t_mod, METH_VARARGS, doc_gmpy_t_mod }, { "t_mod_2exp", Pygmpy_t_mod_2exp, METH_VARARGS, doc_gmpy_t_mod_2exp }, { "unpack", Pygmpy_unpack, METH_VARARGS, doc_gmpy_unpack }, { "version", Pygmpy_get_version, METH_NOARGS, doc_version }, { "xbit_mask", Pyxmpz_xbit_mask, METH_O, doc_xbit_maskg }, { "xmpz", (PyCFunction)Pygmpy_xmpz, METH_VARARGS | METH_KEYWORDS, doc_xmpz }, { "_mpmath_normalize", Pympz_mpmath_normalize, METH_VARARGS, doc_mpmath_normalizeg }, { "_mpmath_create", Pympz_mpmath_create, METH_VARARGS, doc_mpmath_createg }, #ifdef WITHMPFR { "acos", Pympany_acos, METH_O, doc_mpany_acos }, { "acosh", Pympany_acosh, METH_O, doc_mpany_acosh }, { "ai", Pympfr_ai, METH_O, doc_g_mpfr_ai }, { "agm", Pympfr_agm, METH_VARARGS, doc_g_mpfr_agm }, { "asin", Pympany_asin, METH_O, doc_mpany_asin }, { "asinh", Pympany_asinh, METH_O, doc_mpany_asinh }, { "atan", Pympany_atan, METH_O, doc_mpany_atan }, { "atanh", Pympany_atanh, METH_O, doc_mpany_atanh }, { "atan2", Pympfr_atan2, METH_VARARGS, doc_g_mpfr_atan2 }, { "cbrt", Pympfr_cbrt, METH_O, doc_g_mpfr_cbrt }, { "ceil", Pympfr_ceil, METH_O, doc_g_mpfr_ceil}, { "check_range", Pympfr_check_range, METH_O, doc_g_mpfr_check_range }, { "const_catalan", (PyCFunction)Pympfr_const_catalan, METH_VARARGS | METH_KEYWORDS, doc_mpfr_const_catalan }, { "const_euler", (PyCFunction)Pympfr_const_euler, METH_VARARGS | METH_KEYWORDS, doc_mpfr_const_euler }, { "const_log2", (PyCFunction)Pympfr_const_log2, METH_VARARGS | METH_KEYWORDS, doc_mpfr_const_log2 }, { "const_pi", (PyCFunction)Pympfr_const_pi, METH_VARARGS | METH_KEYWORDS, doc_mpfr_const_pi }, { "context", (PyCFunction)GMPyContext_context, METH_VARARGS | METH_KEYWORDS, doc_context }, { "copy_sign", Pympfr_copy_sign, METH_VARARGS, doc_g_mpfr_copy_sign }, { "cos", Pympany_cos, METH_O, doc_mpany_cos }, { "cosh", Pympany_cosh, METH_O, doc_mpany_cosh }, { "cot", Pympfr_cot, METH_O, doc_g_mpfr_cot }, { "coth", Pympfr_coth, METH_O, doc_g_mpfr_coth }, { "csc", Pympfr_csc, METH_O, doc_g_mpfr_csc }, { "csch", Pympfr_csch, METH_O, doc_g_mpfr_csch }, { "degrees", Pympfr_degrees, METH_O, doc_g_mpfr_degrees }, { "digamma", Pympfr_digamma, METH_O, doc_g_mpfr_digamma }, { "div_2exp", Pympany_div_2exp, METH_VARARGS, doc_mpany_div_2exp }, { "eint", Pympfr_eint, METH_O, doc_g_mpfr_eint }, { "erf", Pympfr_erf, METH_O, doc_g_mpfr_erf }, { "erfc", Pympfr_erfc, METH_O, doc_g_mpfr_erfc }, { "exp", Pympany_exp, METH_O, doc_mpany_exp }, { "expm1", Pympfr_expm1, METH_O, doc_g_mpfr_expm1 }, { "exp10", Pympfr_exp10, METH_O, doc_g_mpfr_exp10 }, { "exp2", Pympfr_exp2, METH_O, doc_g_mpfr_exp2 }, { "f2q", Pympfr_f2q, METH_VARARGS, doc_g_mpfr_f2q }, { "factorial", Pympfr_factorial, METH_O, doc_g_mpfr_factorial }, { "floor", Pympfr_floor, METH_O, doc_g_mpfr_floor}, { "fma", Pympany_fma, METH_VARARGS, doc_mpany_fma }, { "fms", Pympany_fms, METH_VARARGS, doc_mpany_fms }, { "fmod", Pympfr_fmod, METH_VARARGS, doc_g_mpfr_fmod }, { "frac", Pympfr_frac, METH_O, doc_g_mpfr_frac }, { "frexp", Pympfr_frexp, METH_O, doc_g_mpfr_frexp }, { "fsum", Pympfr_fsum, METH_O, doc_g_mpfr_fsum }, { "gamma", Pympfr_gamma, METH_O, doc_g_mpfr_gamma }, { "get_context", GMPyContext_get_context, METH_NOARGS, doc_get_context }, { "get_emax_max", Pympfr_get_emax_max, METH_NOARGS, doc_g_mpfr_get_emax_max }, { "get_emin_min", Pympfr_get_emin_min, METH_NOARGS, doc_g_mpfr_get_emin_min }, { "get_exp", Pympfr_get_exp, METH_O, doc_g_mpfr_get_exp }, { "get_max_precision", Pympfr_get_max_precision, METH_NOARGS, doc_g_mpfr_get_max_precision }, { "hypot", Pympfr_hypot, METH_VARARGS, doc_g_mpfr_hypot }, { "ieee", GMPyContext_ieee, METH_O, doc_context_ieee }, { "inf", Pympfr_set_inf, METH_VARARGS, doc_g_mpfr_set_inf }, { "is_finite", Pympany_is_finite, METH_O, doc_mpany_is_finite }, { "is_inf", Pympany_is_inf, METH_O, doc_mpany_is_inf }, { "is_infinite", Pympany_is_infinite, METH_O, doc_mpany_is_infinite }, { "is_integer", Pympfr_is_integer, METH_O, doc_g_mpfr_is_integer }, { "is_lessgreater", Pympfr_is_lessgreater, METH_VARARGS, doc_g_mpfr_is_lessgreater }, { "is_nan", Pympany_is_nan, METH_O, doc_mpany_is_nan }, { "is_number", Pympfr_is_number, METH_O, doc_g_mpfr_is_number }, { "is_regular", Pympfr_is_regular, METH_O, doc_g_mpfr_is_regular }, { "is_signed", Pympfr_is_signed, METH_O, doc_g_mpfr_is_signed }, { "is_unordered", Pympfr_is_unordered, METH_VARARGS, doc_g_mpfr_is_unordered }, { "is_zero", Pympany_is_zero, METH_O, doc_mpany_is_zero }, { "jn", Pympfr_jn, METH_VARARGS, doc_g_mpfr_jn }, { "j0", Pympfr_j0, METH_O, doc_g_mpfr_j0 }, { "j1", Pympfr_j1, METH_O, doc_g_mpfr_j1 }, { "lgamma", Pympfr_lgamma, METH_O, doc_g_mpfr_lgamma }, { "li2", Pympfr_li2, METH_O, doc_g_mpfr_li2 }, { "lngamma", Pympfr_lngamma, METH_O, doc_g_mpfr_lngamma }, { "local_context", (PyCFunction)GMPyContext_local_context, METH_VARARGS | METH_KEYWORDS, doc_local_context }, { "log", Pympany_log, METH_O, doc_mpany_log }, { "log1p", Pympfr_log1p, METH_O, doc_g_mpfr_log1p }, { "log10", Pympany_log10, METH_O, doc_mpany_log10 }, { "log2", Pympfr_log2, METH_O, doc_g_mpfr_log2 }, { "maxnum", Pympfr_max2, METH_VARARGS, doc_g_mpfr_maxnum }, { "max2", Pympfr_max2, METH_VARARGS, doc_g_mpfr_max2 }, { "minnum", Pympfr_min2, METH_VARARGS, doc_g_mpfr_minnum }, { "min2", Pympfr_min2, METH_VARARGS, doc_g_mpfr_min2 }, { "modf", Pympfr_modf, METH_O, doc_g_mpfr_modf }, { "mpfr", (PyCFunction)Pygmpy_mpfr, METH_VARARGS | METH_KEYWORDS, doc_mpfr }, { "mpfr_from_old_binary", Pympfr_From_Old_Binary, METH_O, doc_g_mpfr_from_old_binary }, { "mpfr_random", GMPY_mpfr_random, METH_VARARGS, doc_mpfr_random }, { "mpfr_grandom", GMPY_mpfr_grandom, METH_VARARGS, doc_mpfr_grandom }, { "mul_2exp", Pympany_mul_2exp, METH_VARARGS, doc_mpany_mul_2exp }, { "nan", Pympfr_set_nan, METH_NOARGS, doc_g_mpfr_set_nan }, { "next_above", Pympfr_nextabove, METH_O, doc_g_mpfr_nextabove }, { "next_below", Pympfr_nextbelow, METH_O, doc_g_mpfr_nextbelow }, { "next_toward", Pympfr_nexttoward, METH_VARARGS, doc_g_mpfr_nexttoward }, { "radians", Pympfr_radians, METH_O, doc_g_mpfr_radians }, { "rec_sqrt", Pympfr_rec_sqrt, METH_O, doc_g_mpfr_rec_sqrt }, { "reldiff", Pympfr_reldiff, METH_VARARGS, doc_g_mpfr_reldiff }, { "remainder", Pympfr_remainder, METH_VARARGS, doc_g_mpfr_remainder }, { "remquo", Pympfr_remquo, METH_VARARGS, doc_g_mpfr_remquo }, { "rint", Pympfr_rint, METH_O, doc_g_mpfr_rint }, { "rint_ceil", Pympfr_rint_ceil, METH_O, doc_g_mpfr_rint_ceil }, { "rint_floor", Pympfr_rint_floor, METH_O, doc_g_mpfr_rint_floor }, { "rint_round", Pympfr_rint_round, METH_O, doc_g_mpfr_rint_round }, { "rint_trunc", Pympfr_rint_trunc, METH_O, doc_g_mpfr_rint_trunc }, { "root", Pympfr_root, METH_VARARGS, doc_mpfr_root }, { "round_away", Pympfr_round_away, METH_O, doc_g_mpfr_round_away }, { "round2", Pympfr_round2, METH_VARARGS, doc_g_mpfr_round2 }, { "sec", Pympfr_sec, METH_O, doc_g_mpfr_sec }, { "sech", Pympfr_sech, METH_O, doc_g_mpfr_sech }, { "set_context", GMPyContext_set_context, METH_O, doc_set_context }, { "set_exp", Pympfr_set_exp, METH_VARARGS, doc_g_mpfr_set_exp }, { "set_sign", Pympfr_set_sign, METH_VARARGS, doc_g_mpfr_set_sign }, { "sin", Pympany_sin, METH_O, doc_mpany_sin }, { "sinh", Pympany_sinh, METH_O, doc_mpany_sinh }, { "sinh_cosh", Pympfr_sinh_cosh, METH_O, doc_g_mpfr_sinh_cosh }, { "sin_cos", Pympany_sin_cos, METH_O, doc_mpany_sin_cos }, { "sqrt", Pympany_sqrt, METH_O, doc_mpany_sqrt }, { "tan", Pympany_tan, METH_O, doc_mpany_tan }, { "tanh", Pympany_tanh, METH_O, doc_mpany_tanh }, { "trunc", Pympfr_trunc, METH_O, doc_g_mpfr_trunc}, { "yn", Pympfr_yn, METH_VARARGS, doc_g_mpfr_yn }, { "y0", Pympfr_y0, METH_O, doc_g_mpfr_y0 }, { "y1", Pympfr_y1, METH_O, doc_g_mpfr_y1 }, { "zero", Pympfr_set_zero, METH_VARARGS, doc_g_mpfr_set_zero }, { "zeta", Pympfr_zeta, METH_O, doc_g_mpfr_zeta }, #endif #ifdef WITHMPC { "mpc", (PyCFunction)Pygmpy_mpc, METH_VARARGS | METH_KEYWORDS, doc_g_mpc }, { "mpc_random", GMPY_mpc_random, METH_VARARGS, doc_mpc_random }, { "norm", Pympc_norm, METH_O, doc_mpc_norm }, { "polar", Pympc_polar, METH_O, doc_mpc_polar }, { "phase", Pympc_phase, METH_O, doc_mpc_phase }, { "proj", Pympc_proj, METH_O, doc_mpc_proj }, { "rect", Pympc_rect, METH_VARARGS, doc_mpc_rect }, #endif { NULL, NULL, 1} }; /* The custom memory allocation routines either use PyMem_* or the standard * libraries. See gmpy.h for defines. */ static void * gmpy_allocate(size_t size) { void *res; if (!(res = GMPY_MALLOC(size))) Py_FatalError("Insufficient memory"); return res; } static void * gmpy_reallocate(void *ptr, size_t old_size, size_t new_size) { void *res; if (!(res = GMPY_REALLOC(ptr, new_size))) Py_FatalError("Insufficient memory"); return res; } static void gmpy_free( void *ptr, size_t size) { GMPY_FREE(ptr); } static void _PyInitGMP(void) { #ifdef WITHMPFR PyObject *temp = NULL; #endif mp_set_memory_functions(gmpy_allocate, gmpy_reallocate, gmpy_free); set_zcache(); set_pympzcache(); set_pympqcache(); set_pyxmpzcache(); #ifdef WITHMPFR set_pympfrcache(); context = (GMPyContextObject*)GMPyContext_new(); GMPyExc_GmpyError = PyErr_NewException("gmpy2.gmpyError", PyExc_ArithmeticError, NULL); GMPyExc_Erange = PyErr_NewException("gmpy2.RangeError", GMPyExc_GmpyError, NULL); GMPyExc_Inexact = PyErr_NewException("gmpy2.InexactResultError", GMPyExc_GmpyError, NULL); GMPyExc_Overflow = PyErr_NewException("gmpy2.OverflowResultError", GMPyExc_Inexact, NULL); GMPyExc_Underflow = PyErr_NewException("gmpy2.UnderflowResultError", GMPyExc_Inexact, NULL); GMPyExc_ExpBound = PyErr_NewException("gmpy2.ExponentOutOfBoundsError", GMPyExc_GmpyError, NULL); temp = PyTuple_Pack(2, GMPyExc_GmpyError, PyExc_ValueError); GMPyExc_Invalid = PyErr_NewException("gmpy2.InvalidOperationError", temp, NULL); Py_XDECREF(temp); temp = PyTuple_Pack(2, GMPyExc_GmpyError, PyExc_ZeroDivisionError); GMPyExc_DivZero = PyErr_NewException("gmpy2.DivisionByZeroError", temp, NULL); Py_XDECREF(temp); #endif #ifdef WITHMPC set_pympccache(); #endif } static char _gmpy_docs[] = "gmpy2 2.0.7 - General Multiple-precision arithmetic for Python\n" "\n" "gmpy2 supports several multiple-precision libraries. Integer and\n" "rational arithmetic is provided by either the GMP or MPIR libraries.\n" "Real floating-point arithmetic is provided by the MPFR library.\n" "Complex floating-point arithmetic is provided by the MPC library.\n" "\n" "The integer type 'mpz' has comparable functionality to Python's\n" "builtin integers, but is faster for operations on large numbers.\n" "A wide variety of additional functions are provided:\n" " - bit manipulations\n" " - GCD, Extended GCD, LCM\n" " - Fibonacci and Lucas sequences\n" " - primality testing\n" " - powers and integer Nth roots\n" "\n" "The rational type 'mpq' is equivalent to Python's fractions\n" "module, but is faster.\n" "\n" "The real type 'mpfr' and complex type 'mpc' provide multiple-\n" "precision real and complex numbers with user-definable precision,\n" "rounding, and exponent range. All the advanced functions from the\n" "MPFR and MPC libraries are available.\n\ "; /* Notes on Python 3.x support: Full support for PEP-3121 has not been * implemented. No per-module state has been defined. */ #ifdef PY3 #define INITERROR return NULL static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "gmpy2", _gmpy_docs, -1, /*sizeof(struct module_state) */ Pygmpy_methods, NULL, NULL, /* gmpy_traverse */ NULL, /* gmpy_clear */ NULL }; PyMODINIT_FUNC PyInit_gmpy2(void) #else #define INITERROR return PyMODINIT_FUNC initgmpy2(void) #endif { PyObject* gmpy_module = NULL; PyObject* copy_reg_module = NULL; /* Validate the sizes of the various typedef'ed integer types. */ if (sizeof(mp_limb_t) != sizeof(mpir_si)) { SYSTEM_ERROR("Size of mp_limb_t and mpir_si not compatible"); INITERROR; } if (sizeof(mp_bitcnt_t) != sizeof(size_t)) { SYSTEM_ERROR("Size of mp_bitcnt_t and size_t not compatible"); INITERROR; } if (sizeof(mp_size_t) != sizeof(size_t)) { SYSTEM_ERROR("Size of mp_size_t and size_t not compatible"); INITERROR; } #ifdef WITHMPFR if (sizeof(mpfr_prec_t) != sizeof(long)) { SYSTEM_ERROR("Size of mpfr_prec_t and long not compatible"); INITERROR; } if (sizeof(mpfr_exp_t) != sizeof(long)) { SYSTEM_ERROR("Size of mpfr_exp_t and long not compatible"); INITERROR; } #endif if (PyType_Ready(&Pympz_Type) < 0) INITERROR; if (PyType_Ready(&Pympq_Type) < 0) INITERROR; if (PyType_Ready(&Pyxmpz_Type) < 0) INITERROR; if (PyType_Ready(&GMPYIter_Type) < 0) INITERROR; #ifdef WITHMPFR if (PyType_Ready(&Pympfr_Type) < 0) INITERROR; if (PyType_Ready(&GMPyContext_Type) < 0) INITERROR; if (PyType_Ready(&GMPyContextManager_Type) < 0) INITERROR; #endif #ifdef WITHMPC if (PyType_Ready(&Pympc_Type) < 0) INITERROR; #endif _PyInitGMP(); #ifdef PY3 gmpy_module = PyModule_Create(&moduledef); #else gmpy_module = Py_InitModule3("gmpy2", Pygmpy_methods, _gmpy_docs); #endif if (gmpy_module == NULL) INITERROR; #ifdef WITHMPFR /* Add the constants for defining rounding modes. */ PyModule_AddIntConstant(gmpy_module, "RoundToNearest", MPFR_RNDN); PyModule_AddIntConstant(gmpy_module, "RoundToZero", MPFR_RNDZ); PyModule_AddIntConstant(gmpy_module, "RoundUp", MPFR_RNDU); PyModule_AddIntConstant(gmpy_module, "RoundDown", MPFR_RNDD); PyModule_AddIntConstant(gmpy_module, "RoundAwayZero", MPFR_RNDA); PyModule_AddIntConstant(gmpy_module, "Default", GMPY_DEFAULT); Py_INCREF(GMPyExc_DivZero); PyModule_AddObject(gmpy_module, "DivisionByZeroError", GMPyExc_DivZero); Py_INCREF(GMPyExc_Inexact); PyModule_AddObject(gmpy_module, "InexactResultError", GMPyExc_Inexact); Py_INCREF(GMPyExc_Invalid); PyModule_AddObject(gmpy_module, "InvalidOperationError", GMPyExc_Invalid); Py_INCREF(GMPyExc_Overflow); PyModule_AddObject(gmpy_module, "OverflowResultError", GMPyExc_Overflow); Py_INCREF(GMPyExc_Underflow); PyModule_AddObject(gmpy_module, "UnderflowResultError", GMPyExc_Underflow); Py_INCREF(GMPyExc_Erange); PyModule_AddObject(gmpy_module, "RangeError", GMPyExc_Erange); Py_INCREF(GMPyExc_ExpBound); PyModule_AddObject(gmpy_module, "ExponentOutOfBoundsError", GMPyExc_ExpBound); #endif /* Add support for pickling. */ #ifdef PY3 copy_reg_module = PyImport_ImportModule("copyreg"); if (copy_reg_module) { char* enable_pickle = "def gmpy2_reducer(x): return (gmpy2.from_binary, (gmpy2.to_binary(x),))\n" "copyreg.pickle(type(gmpy2.mpz(0)), gmpy2_reducer)\n" "copyreg.pickle(type(gmpy2.xmpz(0)), gmpy2_reducer)\n" "copyreg.pickle(type(gmpy2.mpq(0)), gmpy2_reducer)\n" #ifdef WITHMPFR "copyreg.pickle(type(gmpy2.mpfr(0)), gmpy2_reducer)\n" #endif #ifdef WITHMPC "copyreg.pickle(type(gmpy2.mpc(0,0)), gmpy2_reducer)\n" #endif ; PyObject* namespace = PyDict_New(); PyObject* result = NULL; PyDict_SetItemString(namespace, "copyreg", copy_reg_module); PyDict_SetItemString(namespace, "gmpy2", gmpy_module); PyDict_SetItemString(namespace, "type", (PyObject*)&PyType_Type); result = PyRun_String(enable_pickle, Py_file_input, namespace, namespace); if (!result) PyErr_Clear(); Py_DECREF(namespace); Py_DECREF(copy_reg_module); Py_XDECREF(result); } else { PyErr_Clear(); } #else copy_reg_module = PyImport_ImportModule("copy_reg"); if (copy_reg_module) { char* enable_pickle = "def gmpy2_reducer(x): return (gmpy2.from_binary, (gmpy2.to_binary(x),))\n" "copy_reg.pickle(type(gmpy2.mpz(0)), gmpy2_reducer)\n" "copy_reg.pickle(type(gmpy2.xmpz(0)), gmpy2_reducer)\n" "copy_reg.pickle(type(gmpy2.mpq(0)), gmpy2_reducer)\n" #ifdef WITHMPFR "copy_reg.pickle(type(gmpy2.mpfr(0)), gmpy2_reducer)\n" #endif #ifdef WITHMPFR "copy_reg.pickle(type(gmpy2.mpc(0,0)), gmpy2_reducer)\n" #endif ; PyObject* namespace = PyDict_New(); PyObject* result = NULL; PyDict_SetItemString(namespace, "copy_reg", copy_reg_module); PyDict_SetItemString(namespace, "gmpy2", gmpy_module); PyDict_SetItemString(namespace, "type", (PyObject*)&PyType_Type); result = PyRun_String(enable_pickle, Py_file_input, namespace, namespace); if (!result) PyErr_Clear(); Py_DECREF(namespace); Py_DECREF(copy_reg_module); Py_XDECREF(result); } else { PyErr_Clear(); } #endif #ifdef PY3 return gmpy_module; #endif } gmpy2-2.0.7/src/gmpy.h0000666000000000000000000002274112542614506013207 0ustar rootroot/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * gmpy.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * * libraries. * * * * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * * 2008, 2009 Alex Martelli * * * * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, * * 2015 Case Van Horsen * * * * This file is part of GMPY2. * * * * GMPY2 is free software: you can redistribute it and/or modify it under * * the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation, either version 3 of the License, or (at your * * option) any later version. * * * * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * * License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with GMPY2; if not, see * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* gmpy C API extension header file. Part of Python's gmpy module since version 0.4 Created by Pearu Peterson , November 2000. Edited by A. Martelli , December 2000. Edited by Case Van Horsen , 2009, 2010, 2011. Version 1.02, February 2007. Version 1.03, June 2008 Version 1.04, June 2008 (no changes) Version 1.05, February 2009 (support MPIR) Version 1.20, January 2010 (remove obsolete MS hacks) casevh Version 2.00, April 2010 (change to gmpy2) casevh October 2010 (added Py_hash_t) casevh December 2010 (added mpfr, mpc) casevh January 2011 (add Pygmpy_context) casevh April 2011 (split into multiple files) casevh */ #ifndef Py_GMPYMODULE_H #define Py_GMPYMODULE_H #ifdef __cplusplus extern "C" { #endif /* Check for Python version requirements. */ #if PY_VERSION_HEX < 0x02060000 # error "GMPY2 requires Python 2.6 or later." #endif #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; typedef unsigned long Py_uhash_t; # define _PyHASH_IMAG 1000003 #endif /* Define various macros to deal with differences between Python 2 and 3. */ #if (PY_MAJOR_VERSION == 3) #define PY3 #define Py2or3String_FromString PyUnicode_FromString #define Py2or3String_FromFormat PyUnicode_FromFormat #define Py2or3String_Check PyUnicode_Check #define Py2or3String_Format PyUnicode_Format #define Py2or3String_AsString PyUnicode_AS_DATA #define PyStrOrUnicode_Check(op) (PyBytes_Check(op) || PyUnicode_Check(op)) #define PyIntOrLong_FromLong PyLong_FromLong #define PyIntOrLong_Check(op) PyLong_Check(op) #define PyIntOrLong_FromSize_t PyLong_FromSize_t #define PyIntOrLong_FromSsize_t PyLong_FromSsize_t #define PyIntOrLong_AsSsize_t PyLong_AsSsize_t #define PyIntOrLong_AsLong PyLong_AsLong #else #define PY2 #define Py2or3String_FromString PyString_FromString #define Py2or3String_FromFormat PyString_FromFormat #define Py2or3String_Check PyString_Check #define Py2or3String_Format PyString_Format #define Py2or3String_AsString PyString_AsString #define PyStrOrUnicode_Check(op) (PyString_Check(op) || PyUnicode_Check(op)) #define PyIntOrLong_FromLong PyInt_FromLong #define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op)) #define PyIntOrLong_FromSize_t PyInt_FromSize_t #define PyIntOrLong_FromSsize_t PyInt_FromSsize_t #define PyIntOrLong_AsSsize_t PyInt_AsSsize_t #define PyIntOrLong_AsLong PyInt_AsLong #endif /* Support MPIR, if requested. */ #ifdef MPIR # include "mpir.h" #else # include "gmp.h" #endif #if defined(MS_WIN32) && defined(_MSC_VER) /* so one won't need to link explicitly to gmp.lib...: */ # if defined(MPIR) # pragma comment(lib,"mpir.lib") # else # pragma comment(lib,"gmp.lib") # endif # define isnan _isnan # define isinf !_finite # define USE_ALLOCA 1 # define inline __inline #endif /* MPIR 2.6 introduce new data types - MPIR_UI and MPIR_SI - that correspond * to the "optimal" integer type for pass values to GMP/MPIR. On almost all * systems, these types correspond to "unsigned long" and "long". But on * 64-bit Windows, these types correspond to "unsigned long long" and * "long long". */ #ifndef BITS_PER_UI /* Assume we are NOT using MPIR > 2.5. */ #define BITS_PER_UI BITS_PER_ULONG typedef unsigned long mpir_ui; typedef long mpir_si; #define mpz_fits_si_p mpz_fits_slong_p #define mpz_fits_ui_p mpz_fits_ulong_p #endif #ifdef _WIN64 #define PyIntOrLong_FromSI PyLong_FromLongLong #define PyIntOrLong_AsSI PyLong_AsLongLong #else #define PyIntOrLong_FromSI PyIntOrLong_FromLong #define PyIntOrLong_AsSI PyIntOrLong_AsLong #endif #ifdef __GNUC__ # define USE_ALLOCA 1 #endif #ifndef alloca # ifdef __GNUC__ # define alloca __builtin_alloca # else # ifdef _MSC_VER # include # define alloca _alloca # else # if HAVE_ALLOCA_H # include # else char *alloca (); # endif # endif # endif #endif #define ALLOC_THRESHOLD 8192 #define TYPE_ERROR(msg) PyErr_SetString(PyExc_TypeError, msg) #define VALUE_ERROR(msg) PyErr_SetString(PyExc_ValueError, msg) #define ZERO_ERROR(msg) PyErr_SetString(PyExc_ZeroDivisionError, msg) #define SYSTEM_ERROR(msg) PyErr_SetString(PyExc_SystemError, msg) #define OVERFLOW_ERROR(msg) PyErr_SetString(PyExc_OverflowError, msg) #define GMPY_DEFAULT -1 /* To prevent excessive memory usage, we don't want to save very large * numbers in the cache. The default value specified in the options * structure is 128 words (512 bytes on 32-bit platforms, 1024 bytes on * 64-bit platforms). */ #define MAX_CACHE_LIMBS 16384 /* The maximum number of objects that can be saved in a cache is specified * here. The default value is 100.*/ #define MAX_CACHE 1000 /* Choose which memory manager is used: Python or C. * NOTE: The use of PyMem is not compatible with Sage, therefore it is * disabled by default. * Use -DUSE_PYMEM to enable. */ #ifdef USE_PYMEM # define GMPY_FREE(NAME) PyMem_FR(NAME) # define GMPY_MALLOC(NAME) PyMem_Malloc(NAME) # define GMPY_REALLOC(NAME, SIZE) PyMem_Realloc(NAME, SIZE) #else # define GMPY_FREE(NAME) free(NAME) # define GMPY_MALLOC(NAME) malloc(NAME) # define GMPY_REALLOC(NAME, SIZE) realloc(NAME, SIZE) #endif #ifdef USE_ALLOCA # define TEMP_ALLOC(B, S) \ if(S < ALLOC_THRESHOLD) { \ B = alloca(S); \ } else { \ if(!(B = GMPY_MALLOC(S))) { \ PyErr_NoMemory(); \ return NULL; \ } \ } # define TEMP_FREE(B, S) if(S >= ALLOC_THRESHOLD) GMPY_FREE(B) #else # define TEMP_ALLOC(B, S) \ if(!(B = GMPY_MALLOC(S))) { \ PyErr_NoMemory(); \ return NULL; \ } # define TEMP_FREE(B, S) GMPY_FREE(B) #endif /* Various defs to mask differences between Python versions. */ #define Py_RETURN_NOTIMPLEMENTED\ return Py_INCREF(Py_NotImplemented), Py_NotImplemented #ifndef Py_SIZE #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) #endif #ifndef Py_TYPE #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif /* The gmpy_args.h file includes macros that are used for argument * processing. */ #include "gmpy_args.h" #include "gmpy_mpz.h" #include "gmpy_xmpz.h" #include "gmpy_mpz_divmod.h" #include "gmpy_mpz_divmod2exp.h" #include "gmpy_mpz_inplace.h" #include "gmpy_xmpz_inplace.h" #include "gmpy_mpq.h" #ifdef WITHMPFR # include "mpfr.h" # include "gmpy_mpfr.h" # if MPFR_VERSION < 0x030100 # error gmpy2 requires MPFR 3.1.0 or later # endif # include "gmpy_context.h" #endif #ifdef WITHMPC # include "mpc.h" # include "gmpy_mpc.h" # if MPC_VERSION < 0x010000 # error gmpy2 requires MPC 1.0.0 or later # endif #endif #include "gmpy_convert.h" /* Support object caching, creation, and deletion. */ #include "gmpy_cache.h" /* Suport for miscellaneous functions (ie. version, license, etc.). */ #include "gmpy_misc.h" /* Support basic arithmetic operations on mpz, mpq, mpfr, and mpc types. */ #include "gmpy_basic.h" /* Support operations other than those in gmpy_basic. */ #include "gmpy_mpany.h" /* Support conversion to/from binary format. */ #include "gmpy_binary.h" /* Support random number generators. */ #include "gmpy_random.h" /* Support Lucas sequences. */ #include "gmpy_mpz_lucas.h" /* Support probable-prime tests. */ #include "gmpy_mpz_prp.h" #ifdef __cplusplus } #endif #endif /* !defined(Py_GMPYMODULE_H */ gmpy2-2.0.7/docs/0000755000000000000000000000000012567136721012216 5ustar rootrootgmpy2-2.0.7/docs/overview.rst0000666000000000000000000001224012204747352014615 0ustar rootrootOverview of gmpy2 ================= Tutorial -------- The *mpz* type is compatible with Python's built-in int/long type but is significanly 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 "", line 1, in 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 >>> Miscellaneous gmpy2 Functions ----------------------------- **from_binary(...)** from_binary(bytes) returns a gmpy2 object from a byte sequence created by to_binary(). **get_cache(...)** get_cache() returns the current cache size (number of objects) and the maximum size per object (number of limbs). 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. **license(...)** license() returns the gmpy2 license information. **mp_limbsize(...)** mp_limbsize() returns the number of bits per limb used by the GMP or MPIR libarary. **mp_version(...)** mp_version() returns the version of the GMP or MPIR library. **mpc_version(...)** mpc_version() returns the version of the MPC library. **mpfr_version(...)** mpfr_version() returns the version of the MPFR library. **random_state(...)** random_state([seed]) returns a new object containing state information for the random number generator. An optional integer argument can be specified as the seed value. Only the Mersenne Twister random number generator is supported. **set_cache(...)** set_cache(number, size) updates the maximum number of freed objects of each type that are cached and the maximum size (in limbs) of each object. The maximum number of objects of each type that can be cached is 1000. The maximum size of an object is 16384. The maximum size of an object is approximately 64K on 32-bit systems and 128K on 64-bit systems. .. note:: The caching options are global to gmpy2. Changes are not thread-safe. A change in one thread will impact all threads. **to_binary(...)** to_binary(x) returns a byte sequence from a gmpy2 object. All object types are supported. **version(...)** version() returns the version of gmpy2. gmpy2-2.0.7/docs/mpz.rst0000666000000000000000000003161112204747352013560 0ustar rootrootMultiple-precision Integers =========================== 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. Examples -------- :: >>> import gmpy2 >>> from gmpy2 import mpz >>> mpz('123') + 1 mpz(124) >>> 10 - mpz(1) mpz(9) >>> gmpy2.is_prime(17) True .. note:: The use of ``from gmpy2 import *`` is not recommended. The names in gmpy2 have been chosen to avoid conflict with Python's builtin names but gmpy2 does use names that may conflict with other modules or variable names. mpz Methods ----------- **bit_clear(...)** x.bit_clear(n) returns a copy of *x* with bit *n* set to 0. **bit_flip(...)** x.bit_flip(n) returns a copy of *x* with bit *n* inverted. **bit_length(...)** x.bit_length() returns the number of significant bits in the radix-2 representation of *x*. For compatibility with Python, mpz(0).bit_length() returns 0. **bit_scan0(...)** x.bit_scan0(n) returns the index of the first 0-bit of *x* with index >= *n*. If there are no more 0-bits in *x* at or above index *n* (which can only happen for *x* < 0, assuming an infinitely long 2's complement format), then None is returned. *n* must be >= 0. **bit_scan1(...)** x.bit_scan1(n) returns the index of the first 1-bit of *x* with index >= *n*. If there are no more 1-bits in *x* at or above index *n* (which can only happen for *x* >= 0, assuming an infinitely long 2's complement format), then None is returned. *n* must be >= 0. **bit_set(...)** x.bit_set(n) returns a copy of *x* with bit *n* set to 0. **bit_test(...)** x.bit_test(n) returns True if bit *n* of *x* is set, and False if it is not set. **denominator(...)** x.denominator() returns mpz(1). **digits(...)** x.digits([base=10]) returns a string representing *x* in radix *base*. **numerator(...)** x.numerator() returns a copy of x. **num_digits(...)** x.num_digits([base=10]) returns the length of the string representing the absolute value of *x* in radix *base*. The result is correct if base is a power of 2. For other other bases, the result is usually correct but may be 1 too large. *base* can range between 2 and 62, inclusive. mpz Functions ------------- **add(...)** add(x, y) returns *x* + *y*. The result type depends on the input types. **bincoef(...)** bincoef(x, n) returns the binomial coefficient. *n* must be >= 0. **bit_clear(...)** bit_clear(x, n) returns a copy of *x* with bit *n* set to 0. **bit_flip(...)** bit_flip(x, n) returns a copy of *x* with bit *n* inverted. **bit_length(...)** bit_length(x) returns the number of significant bits in the radix-2 representation of *x*. For compatibility with Python, mpz(0).bit_length() returns 0 while mpz(0).num_digits(2) returns 1. **bit_mask(...)** bit_mask(n) returns an *mpz* object exactly *n* bits in length with all bits set. **bit_scan0(...)** bit_scan0(x, n) returns the index of the first 0-bit of *x* with index >= *n*. If there are no more 0-bits in *x* at or above index *n* (which can only happen for *x* < 0, assuming an infinitely long 2's complement format), then None is returned. *n* must be >= 0. **bit_scan1(...)** bit_scan1(x, n) returns the index of the first 1-bit of *x* with index >= *n*. If there are no more 1-bits in *x* at or above index *n* (which can only happen for *x* >= 0, assuming an infinitely long 2's complement format), then None is returned. *n* must be >= 0. **bit_set(...)** bit_set(x, n) returns a copy of *x* with bit *n* set to 0. **bit_test(...)** bit_test(x, n) returns True if bit *n* of *x* is set, and False if it is not set. **c_div(...)** c_div(x, y) returns the quotient of *x* divided by *y*. The quotient is rounded towards +Inf (ceiling rounding). *x* and *y* must be integers. **c_div_2exp(...)** c_div_2exp(x, n) returns the quotient of *x* divided by 2**n. The quotient is rounded towards +Inf (ceiling rounding). *x* must be an integer and *n* must be > 0. **c_divmod(...)** c_divmod(x, y) returns the quotient and remainder of *x* divided by *y*. The quotient is rounded towards +Inf (ceiling rounding) and the remainder will have the opposite sign of *y*. *x* and *y* must be integers. **c_divmod_2exp(...)** c_divmod_2exp(x ,n) returns the quotient and remainder of *x* divided by 2**n. The quotient is rounded towards +Inf (ceiling rounding) and the remainder will be negative or zero. *x* must be an integer and *n* must be > 0. **c_mod(...)** c_mod(x, y) returns the remainder of *x* divided by *y*. The remainder will have the opposite sign of *y*. *x* and *y* must be integers. **c_mod_2exp(...)** c_mod_2exp(x, n) returns the remainder of *x* divided by 2**n. The remainder will be negative. *x* must be an integer and *n* must be > 0. **comb(...)** comb(x, n) returns the number of combinations of *x* things, taking *n* at a time. *n* must be >= 0. **digits(...)** digits(x[, base=10]) returns a string representing *x* in radix *base*. **div(...)** div(x, y) returns *x* / *y*. The result type depends on the input types. **divexact(...)** divexact(x, y) returns the quotient of *x* divided by *y*. Faster than standard division but requires the remainder is zero! **divm(...)** divm(a, b, m) returns *x* such that *b* * *x* == *a* modulo *m*. Raises a ZeroDivisionError exception if no such value *x* exists. **f_div(...)** f_div(x, y) returns the quotient of *x* divided by *y*. The quotient is rounded towards -Inf (floor rounding). *x* and *y* must be integers. **f_div_2exp(...)** f_div_2exp(x, n) returns the quotient of *x* divided by 2**n. The quotient is rounded towards -Inf (floor rounding). *x* must be an integer and *n* must be > 0. **f_divmod(...)** f_divmod(x, y) returns the quotient and remainder of *x* divided by *y*. The quotient is rounded towards -Inf (floor rounding) and the remainder will have the same sign as *y*. *x* and *y* must be integers. **f_divmod_2exp(...)** f_divmod_2exp(x, n) returns quotient and remainder after dividing *x* by 2**n. The quotient is rounded towards -Inf (floor rounding) and the remainder will be positive. *x* must be an integer and *n* must be > 0. **f_mod(...)** f_mod(x, y) returns the remainder of *x* divided by *y*. The remainder will have the same sign as *y*. *x* and *y* must be integers. **f_mod_2exp(...)** f_mod_2exp(x, n) returns remainder of *x* divided by 2**n. The remainder will be positive. *x* must be an integer and *n* must be > 0. **fac(...)** fac(n) returns the exact factorial of *n*. Use factorial() to get the floating-point approximation. **fib(...)** fib(n) returns the *n*-th Fibonacci number. **fib2(...)** fib2(n) returns a 2-tuple with the (*n*-1)-th and *n*-th Fibonacci numbers. **gcd(...)** gcd(a, b) returns the greatest common denominator of integers *a* and *b*. **gcdext(...)** gcdext(a, b) returns a 3-element tuple (*g*, *s*, *t*) such that *g* == gcd(*a*, *b*) and *g* == *a* * *s* + *b* * *t* **hamdist(...)** hamdist(x, y) returns the Hamming distance (number of bit-positions where the bits differ) between integers *x* and *y*. **invert(...)** invert(x, m) returns *y* such that *x* * *y* == 1 modulo *m*, or 0 if no such *y* exists. **iroot(...)** iroot(x,n) returns a 2-element tuple (*y*, *b*) such that *y* is the integer *n*-th root of *x* and *b* is True if the root is exact. *x* must be >= 0 and *n* must be > 0. **iroot_rem(...)** iroot_rem(x,n) returns a 2-element tuple (*y*, *r*) such that *y* is the integer *n*-th root of *x* and *x* = y**n + *r*. *x* must be >= 0 and *n* must be > 0. **is_even(...)** is_even(x) returns True if *x* is even, False otherwise. **is_odd(...)** is_odd(x) returns True if *x* is odd, False otherwise. **is_power(...)** is_power(x) returns True if *x* is a perfect power, False otherwise. **is_prime(...)** is_prime(x[, n=25]) returns True if *x* is **probably** prime. False is returned if *x* is definately composite. *x* is checked for small divisors and up to *n* Miller-Rabin tests are performed. The actual tests performed may vary based on version of GMP or MPIR used. **is_square(...)** is_square(x) returns True if *x* is a perfect square, False otherwise. **isqrt(...)** isqrt(x) returns the integer square root of an integer *x*. *x* must be >= 0. **isqrt_rem(...)** isqrt_rem(x) returns a 2-tuple (*s*, *t*) such that *s* = isqrt(*x*) and *t* = *x* - *s* * *s*. *x* must be >= 0. **jacobi(...)** jacobi(x, y) returns the Jacobi symbol (*x* | *y*). *y* must be odd and > 0. **kronecker(...)** kronecker(x, y) returns the Kronecker-Jacobi symbol (*x* | *y*). **lcm(...)** lcm(a, b) returns the lowest common multiple of integers *a* and *b*. **legendre(...)** legendre(x, y) returns the Legendre symbol (*x* | *y*). *y* is assumed to be an odd prime. **lucas(...)** lucas(n) returns the *n*-th Lucas number. **lucas2(...)** lucas2(n) returns a 2-tuple with the (*n*-1)-th and *n*-th Lucas numbers. **mpz(...)** mpz() returns a new *mpz* object set to 0. 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, thn 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. **mpz_random(...)** mpz_random(random_state, n) returns a uniformly distributed random integer between 0 and *n*-1. The parameter *random_state* must be created by random_state() first. **mpz_rrandomb(...)** mpz_rrandomb(random_state, b) returns a random integer between 0 and 2**b - 1 with long sequences of zeros and one in its binary representation. The parameter *random_state* must be created by random_state() first. **mpz_urandomb(...)** mpz_urandomb(random_state, b) returns a uniformly distributed random integer between 0 and 2**b - 1. The parameter *random_state* must be created by random_state() first. **mul(...)** mul(x, y) returns *x* \* *y*. The result type depends on the input types. **next_prime(...)** next_prime(x) returns the next **probable** prime number > *x*. **num_digits(...)** num_digits(x[, base=10]) returns the length of the string representing the absolute value of *x* in radix *base*. The result is correct if base is a power of 2. For other other bases, the result is usually correct but may be 1 too large. *base* can range between 2 and 62, inclusive. **popcount(...)** popcount(x) returns the number of bits with value 1 in *x*. If *x* < 0, the number of bits with value 1 is infinite so -1 is returned in that case. **powmod(...)** powmod(x, y, m) returns (*x* ** *y*) mod *m*. The exponenent *y* can be negative, and the correct result will be returned if the inverse of *x* mod *m* exists. Otherwise, a ValueError is raised. **remove(...)** remove(x, f) will remove the factor *f* from *x* as many times as possible and return a 2-tuple (*y*, *m*) where *y* = *x* // (*f* ** *m*). *f* does not divide *y*. *m* is the multiplicity of the factor *f* in *x*. *f* must be > 1. **sub(...)** sub(x, y) returns *x* - *y*. The result type depends on the input types. **t_div(...)** t_div(x, y) returns the quotient of *x* divided by *y*. The quotient is rounded towards zero (truncation). *x* and *y* must be integers. **t_div_2exp(...)** t_div_2exp(x, n) returns the quotient of *x* divided by 2**n. The quotient is rounded towards zero (truncation). *n* must be > 0. **t_divmod(...)** t_divmod(x, y) returns the quotient and remainder of *x* divided by *y*. The quotient is rounded towards zero (truncation) and the remainder will have the same sign as *x*. *x* and *y* must be integers. **t_divmod_2exp(...)** t_divmod_2exp(x, n) returns the quotient and remainder of *x* divided by 2**n. The quotient is rounded towards zero (truncation) and the remainder will have the same sign as *x*. *x* must be an integer and *n* must be > 0. **t_mod(...)** t_mod(x, y) returns the remainder of *x* divided by *y*. The remainder will have the same sign as *x*. *x* and *y* must be integers. **t_mod_2exp(...)** t_mod_2exp(x, n) returns the remainder of *x* divided by 2**n. The remainder will have the same sign as *x*. *x* must be an integer and *n* must be > 0. gmpy2-2.0.7/docs/mpq.rst0000666000000000000000000000417412204747352013553 0ustar rootrootMultiple-precision Rationals ============================ 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 Methods ----------- **digits(...)** x.digits([base=10]) returns a Python string representing *x* in the given base (2 to 62, default is 10). A leading '-' is present if *x* < 0, but no leading '+' is present if *x* >= 0. mpq Attributes -------------- **denominator** x.denomintor returns the denominator of *x*. **numerator** x.numerator returns the numerator of *x*. mpq Functions ------------- **add(...)** add(x, y) returns *x* + *y*. The result type depends on the input types. **div(...)** div(x, y) returns *x* / *y*. The result type depends on the input types. **f2q(...)** f2q(x[, err]) returns the best *mpq* approximating *x* to within relative error *err*. Default is the precision of *x*. If *x* is not an *mpfr*, it is converted to an *mpfr*. Uses Stern-Brocot tree to find the best approximation. An *mpz* is returned if the the denominator is 1. If *err* < 0, then the relative error sought is 2.0 ** *err*. **mpq(...)** mpq() returns an *mpq* object set to 0/1. 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. **mul(...)** mul(x, y) returns *x* \* *y*. The result type depends on the input types. **qdiv(...)** qdiv(x[, y=1]) returns *x/y* as *mpz* if possible, or as *mpq* if *x* is not exactly divisible by *y*. **sub(...)** sub(x, y) returns *x* - *y*. The result type depends on the input types. gmpy2-2.0.7/docs/mpfr.rst0000666000000000000000000006612412204747352013725 0ustar rootrootMultiple-precision Reals ======================== gmpy2 replaces the *mpf* type from gmpy 1.x with a new *mpfr* type 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 precison 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) >>> Contexts -------- .. warning:: Contexts and context managers are not thread-safe! Modifying the context in one thread will impact all other threads. 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) >>> 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) >>> Context Attributes ------------------ **precision** This attribute controls the precision of an *mpfr* result. The precision is specified in bits, not decimal digits. The maximum precision that can be specified is platform dependent and can be retrieved with **get_max_precision()**. .. note:: Specifying a value for precision that is too close to the maximum precision will cause the MPFR library to fail. **real_prec** This attribute controls the precision of the real part of an *mpc* result. If the value is ``Default``, then the value of the precision attribute is used. **imag_prec** This attribute controls the precision of the imaginary part of an *mpc* result. If the value is ``Default``, then the value of real_prec is used. **round** There are five rounding modes availble to *mpfr* types: ``RoundAwayZero`` The result is rounded away from 0.0. ``RoundDown`` The result is rounded towards -Infinity. ``RoundToNearest`` Round to the nearest value; ties are rounded to an even value. ``RoundToZero`` The result is rounded towards 0.0. ``RoundUp`` The result is rounded towards +Infinity. **real_round** This attribute controls the rounding mode for the real part of an *mpc* result. If the value is ``Default``, then the value of the round attribute is used. Note: ``RoundAwayZero`` is not a valid rounding mode for *mpc*. **imag_round** This attribute controls the rounding mode for the imaginary part of an *mpc* result. If the value is ``Default``, then the value of the real_round attribute is used. Note: ``RoundAwayZero`` is not a valid rounding mode for *mpc*. **emax** This attribute controls the maximum allowed exponent of an *mpfr* result. The maximum exponent is platform dependent and can be retrieved with **get_emax_max()**. **emin** This attribute controls the minimum allowed exponent of an *mpfr* result. The minimum exponent is platform dependent and can be retrieved with **get_emin_min()**. .. note:: It is possible to change the values of emin/emax such that previous *mpfr* values are no longer valid numbers but should either underflow to +/-0.0 or overflow to +/-Infinity. To raise an exception if this occurs, see **trap_expbound**. **subnormalize** The usual IEEE-754 floating point representation supports gradual underflow when the minimum exponent is reached. The MFPR library does not enable gradual underflow by default but it can be enabled to precisely mimic the results of IEEE-754 floating point operations. **trap_underflow** If set to ``False``, a result that is smaller than the smallest possible *mpfr* given the current exponent range will be replaced by +/-0.0. If set to ``True``, an ``UnderflowResultError`` exception is raised. **underflow** This flag is not user controllable. It is automatically set if a result underflowed to +/-0.0 and trap_underflow is ``False``. **trap_overflow** If set to ``False``, a result that is larger than the largest possible *mpfr* given the current exponent range will be replaced by +/-Infinity. If set to ``True``, an ``OverflowResultError`` exception is raised. **overflow** This flag is not user controllable. It is automatically set if a result overflowed to +/-Infinity and trap_overflow is ``False``. **trap_inexact** This attribute controls whether or not an ``InexactResultError`` exception is raised if an inexact result is returned. To check if the result is greater or less than the exact result, check the **rc** attribute of the *mpfr* result. **inexact** This flag is not user controllable. It is automatically set if an inexact result is returned. **trap_invalid** This attribute controls whether or not an ``InvalidOperationError`` exception is raised if a numerical result is not defined. A special NaN (Not-A-Number) value will be returned if an exception is not raised. The ``InvalidOperationError`` is a sub-class of Python's ``ValueError``. 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. **invalid** This flag is not user controllable. It is automatically set if an invalid (Not-A-Number) result is returned. **trap_erange** This attribute controls whether or not a ``RangeError`` exception is raised when certain operations are performed on NaN and/or Infinity values. Setting trap_erange to ``True`` can be used to raise an exception if comparisons are attempted with a NaN. :: >>> 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 "", line 1, in gmpy2.RangeError: comparison with NaN >>> **erange** This flag is not user controllable. It is automatically set if an erange error occurred. **trap_divzero** This attribute controls whether or not a ``DivisionByZeroError`` exception is raised if division by 0 occurs. The ``DivisionByZeroError`` is a sub-class of Python's ``ZeroDivisionError``. **divzero** This flag is not user controllable. It is automatically set if a division by zero occurred and NaN result was returned. **trap_expbound** This attribute controls whether or not an ``ExponentOutOfBoundsError`` exception is raised if exponents in an operand are outside the current emin/emax limits. **allow_complex** This attribute controls whether or not an *mpc* result can be returned if an *mpfr* result would normally not be possible. Context Methods --------------- **clear_flags()** Clear the underflow, overflow, inexact, invalid, erange, and divzero flags. **copy()** Return a copy of the context. Contexts and the with statement ------------------------------- 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 orginal 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: :: with gmpy2.ieee(64) as ctx: is equivalent to: :: gmpy2.set_context(gmpy2.ieee(64)) with gmpy2.local_context() as ctx: Contexts that implement the standard *single*, *double*, and *quadruple* precision floating point types can be created using **ieee()**. mpfr Methods ------------ **as_integer_ratio()** Returns a 2-tuple containing the numerator and denominator after converting the *mpfr* object into the exact rational equivalent. The return 2-tuple is equivalent to Python's as_integer_ratio() method of built-in float objects. **as_mantissa_exp()** Returns a 2-tuple containing the mantissa and exponent. **as_simple_fraction()** Returns an *mpq* containing the simpliest rational value that approximates the *mpfr* value with an error less than 1/(2**precision). **conjugate()** Returns the complex conjugate. For *mpfr* objects, returns a copy of the original object. **digits()** Returns a 3-tuple containing the mantissa, the exponent, and the number of bits of precision. The mantissa is represented as a string in the specified base with up to 'prec' digits. If 'prec' is 0, as many digits that are available are returned. No more digits than available given x's precision are returned. 'base' must be between 2 and 62, inclusive. **is_integer()** Returns True if the *mpfr* object is an integer. mpfr Attributes --------------- **imag** Returns the imaginary component. For *mpfr* objects, returns 0. **precision** Returns the precision of the *mpfr* object. **rc** The result code (also known as ternary value in the MPFR documentation) is 0 if the value of the *mpfr* object is exactly equal to the exact, infinite precision value. If the result code is 1, then the value of the *mpfr* object is greater than the exact value. If the result code is -1, then the value of the *mpfr* object is less than the exact, infinite precision value. **real** Returns the real component. For *mpfr* objects, returns a copy of the original object. mpfr Functions -------------- **acos(...)** acos(x) returns the arc-cosine of x. x is measured in radians. If context.allow_complex is True, then an *mpc* result will be returned for abs(x) > 1. **acosh(...)** acosh(x) returns the inverse hyperbolic cosine of x. **add(...)** add(x, y) returns x + y. The type of the result is based on the types of the arguments. **agm(...)** agm(x, y) returns the arithmetic-geometric mean of x and y. **ai(...)** ai(x) returns the Airy function of x. **asin(...)** asin(x) returns the arc-sine of x. x is measured in radians. If context.allow_complex is True, then an *mpc* result will be returned for abs(x) > 1. **asinh(...)** asinh(x) return the inverse hyperbolic sine of x. **atan(...)** atan(x) returns the arc-tangent of x. x is measured in radians. **atan2(...)** atan2(y, x) returns the arc-tangent of (y/x). **atanh(...)** atanh(x) returns the inverse hyperbolic tangent of x. If context.allow_complex is True, then an *mpc* result will be returned for abs(x) > 1. **cbrt(...)** cbrt(x) returns the cube root of x. **ceil(...)** ceil(x) returns the 'mpfr' that is the smallest integer >= x. **check_range(...)** check_range(x) return a new 'mpfr' with exponent that lies within the current range of emin and emax. **const_catalan(...)** const_catalan([precision=0]) returns the catalan constant using the specified precision. If no precision is specified, the default precision is used. **const_euler(...)** const_euler([precision=0]) returns the euler constant using the specified precision. If no precision is specified, the default precision is used. **const_log2(...)** const_log2([precision=0]) returns the log2 constant using the specified precision. If no precision is specified, the default precision is used. **const_pi(...)** const_pi([precision=0]) returns the constant pi using the specified precision. If no precision is specified, the default precision is used. **context(...)** context() returns a new context manager controlling MPFR and MPC arithmetic. **cos(...)** cos(x) seturns the cosine of x. x is measured in radians. **cosh(...)** cosh(x) returns the hyperbolic cosine of x. **cot(...)** cot(x) returns the cotangent of x. x is measured in radians. **coth(...)** coth(x) returns the hyperbolic cotangent of x. **csc(...)** csc(x) returns the cosecant of x. x is measured in radians. **csch(...)** csch(x) returns the hyperbolic cosecant of x. **degrees(...)** degrees(x) converts an angle measurement x from radians to degrees. **digamma(...)** digamma(x) returns the digamma of x. **div(...)** div(x, y) returns x / y. The type of the result is based on the types of the arguments. **div_2exp(...)** div_2exp(x, n) returns an 'mpfr' or 'mpc' divided by 2**n. **eint(...)** eint(x) returns the exponential integral of x. **erf(...)** erf(x) returns the error function of x. **erfc(...)** erfc(x) returns the complementary error function of x. **exp(...)** exp(x) returns e**x. **exp10(...)** exp10(x) returns 10**x. **exp2(...)** exp2(x) returns 2**x. **expm1(...)** expm1(x) returns e**x - 1. expm1() is more accurate than exp(x) - 1 when x is small. **f2q(...)** f2q(x[,err]) returns the simplest *mpq* approximating x to within relative error err. Default is the precision of x. Uses Stern-Brocot tree to find the simplist approximation. An *mpz* is returned if the the denominator is 1. If err<0, error sought is 2.0 ** err. **factorial(...)** factorial(n) returns the floating-point approximation to the factorial of n. See fac(n) to get the exact integer result. **floor(...)** floor(x) returns the 'mpfr' that is the smallest integer <= x. **fma(...)** fma(x, y, z) returns correctly rounded result of (x * y) + z. **fmod(...)** fmod(x, y) returns x - n*y where n is the integer quotient of x/y, rounded to 0. **fms(...)** fms(x, y, z) returns correctly rounded result of (x * y) - z. **frac(...)** frac(x) returns the fractional part of x. **frexp(...)** frexp(x) returns a tuple containing the exponent and mantissa of x. **fsum(...)** fsum(iterable) returns the accurate sum of the values in the iterable. **gamma(...)** gamma(x) returns the gamma of x. **get_exp(...)** get_exp(mpfr) returns the exponent of an *mpfr*. Returns 0 for NaN or Infinity and sets the erange flag and will raise an exception if trap_erange is set. **hypot(...)** hypot(y, x) returns square root of (x**2 + y**2). **ieee(...)** ieee(bitwidth) returns a context with settings for 32-bit (aka single), 64-bit (aka double), or 128-bit (aka quadruple) precision floating point types. **inf(...)** inf(n) returns an *mpfr* initialized to Infinity with the same sign as n. If n is not given, +Infinity is returned. **is_finite(...)** is_finite(x) returns True if x is an actual number (i.e. not NaN or Infinity). **is_inf(...)** is_inf(x) returns True if x is Infinity or -Infinity. .. note:: **is_inf()** is deprecated; please use **if_infinite()**. **is_infinite(...)** is_infinite(x) returns True if x Infinity or -Infinity. **is_nan(...)** is_nan(x) returns True if x is NaN (Not-A-Number). **is_number(...)** is_number(x) returns True if x is an actual number (i.e. not NaN or Infinity). .. note:: **is_number()** is deprecated; please use **is_finite()**. **is_regular(...)** is_regular(x) returns True if x is not zero, NaN, or Infinity. **is_signed(...)** is_signed(x) returns True if the sign bit of x is set. **is_unordered(...)** is_unordered(x,y) returns True if either x and/or y is NaN. **is_zero(...)** is_zero(x) returns True if x is zero. **j0(...)** j0(x) returns the Bessel function of the first kind of order 0 of x. **j1(...)** j1(x) returns the Bessel function of the first kind of order 1 of x. **jn(...)** jn(x,n) returns the Bessel function of the first kind of order n of x. **lgamma(...)** lgamma(x) returns a tuple containing the logarithm of the absolute value of gamma(x) and the sign of gamma(x) **li2(...)** li2(x) returns the real part of dilogarithm of x. **lngamma(...)** lngamma(x) returns the logarithm of gamma(x). **log(...)** log(x) returns the natural logarithm of x. **log10(...)** log10(x) returns the base-10 logarithm of x. **log1p(...)** log1p(x) returns the natural logarithm of (1+x). **log2(...)** log2(x) returns the base-2 logarithm of x. **max2(...)** max2(x, y) returns the maximum of x and y. The result may be rounded to match the current context. Use the builtin max() to get an exact copy of the largest object without any rounding. **min2(...)** min2(x, y) returns the minimum of x and y. The result may be rounded to match the current context. Use the builtin min() to get an exact copy of the smallest object without any rounding. **modf(...)** modf(x) returns a tuple containing the integer and fractional portions of x. **mpfr(...)** mpfr() returns and *mpfr* object set to 0.0. mpfr(n[, precison=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 precison 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. **mpfr_from_old_binary(...)** mpfr_from_old_binary(string) returns an *mpfr* from a GMPY 1.x binary mpf format. Please use to_binary()/from_binary() to convert GMPY2 objects to or from a binary format. **mpfr_grandom(...)** mpfr_grandom(random_state) returns two random numbers with gaussian distribution. The parameter *random_state* must be created by random_state() first. **mpfr_random(...)** mpfr_random(random_state) returns a uniformly distributed number between [0,1]. The parameter *random_state* must be created by random_state() first. **mul(...)** mul(x, y) returns x * y. The type of the result is based on the types of the arguments. **mul_2exp(...)** mul_2exp(x, n) returns 'mpfr' or 'mpc' multiplied by 2**n. **nan(...)** nan() returns an 'mpfr' initialized to NaN (Not-A-Number). **next_above(...)** next_above(x) returns the next 'mpfr' from x toward +Infinity. **next_below(...)** next_below(x) returns the next 'mpfr' from x toward -Infinity. **radians(...)** radians(x) converts an angle measurement x from degrees to radians. **rec_sqrt(...)** rec_sqrt(x) returns the reciprocal of the square root of x. **reldiff(...)** reldiff(x, y) returns the relative difference between x and y. Result is equal to abs(x-y)/x. **remainder(...)** remainder(x, y) returns x - n*y where n is the integer quotient of x/y, rounded to the nearest integer and ties rounded to even. **remquo(...)** remquo(x, y) returns a tuple containing the remainder(x,y) and the low bits of the quotient. **rint(...)** rint(x) returns x rounded to the nearest integer using the current rounding mode. **rint_ceil(...)** rint_ceil(x) returns x rounded to the nearest integer by first rounding to the next higher or equal integer and then, if needed, using the current rounding mode. **rint_floor(...)** rint_floor(x) returns x rounded to the nearest integer by first rounding to the next lower or equal integer and then, if needed, using the current rounding mode. **rint_round(...)** rint_round(x) returns x rounded to the nearest integer by first rounding to the nearest integer (ties away from 0) and then, if needed, using the current rounding mode. **rint_trunc(...)** rint_trunc(x) returns x rounded to the nearest integer by first rounding towards zero and then, if needed, using the current rounding mode. **root(...)** root(x, n) returns n-th root of x. The result always an *mpfr*. **round2(...)** round2(x[, n]) returns x rounded to n bits. Uses default precision if n is not specified. See round_away() to access the mpfr_round() function. Use the builtin round() to round x to n decimal digits. **round_away(...)** round_away(x) returns an *mpfr* by rounding x the nearest integer, with ties rounded away from 0. **sec(...)** sec(x) returns the secant of x. x is measured in radians. **sech(...)** sech(x) returns the hyperbolic secant of x. **set_exp(...)** set_exp(x, n) sets the exponent of a given *mpfr* to n. If n is outside the range of valid exponents, set_exp() will set the erange flag and either return the original value or raise an exception if trap_erange is set. **set_sign(...)** set_sign(x, bool) returns a copy of x with it's sign bit set if *bool* evaluates to True. **sign(...)** sign(x) returns -1 if x < 0, 0 if x == 0, or +1 if x >0. **sin(...)** sin(x) returns the sine of x. x is measured in radians. **sin_cos(...)** sin_cos(x) returns a tuple containing the sine and cosine of x. x is measured in radians. **sinh(...)** sinh(x) returns the hyberbolic sine of x. **sinh_cosh(...)** sinh_cosh(x) returns a tuple containing the hyperbolic sine and cosine of x. **sqrt(...)** sqrt(x) returns the square root of x. If x is integer, rational, or real, then an *mpfr* will be returned. If x is complex, then an *mpc* will be returned. If context.allow_complex is True, negative values of x will return an *mpc*. **square(...)** square(x) returns x * x. The type of the result is based on the types of the arguments. **sub(...)** sub(x, y) returns x - y. The type of the result is based on the types of the arguments. **tan(...)** tan(x) returns the tangent of x. x is measured in radians. **tanh(...)** tanh(x) returns the hyperbolic tangent of x. **trunc(...)** trunc(x) returns an 'mpfr' that is x truncated towards 0. Same as x.floor() if x>=0 or x.ceil() if x<0. **y0(...)** y0(x) returns the Bessel function of the second kind of order 0 of x. **y1(...)** y1(x) returns the Bessel function of the second kind of order 1 of x. **yn(...)** yn(x,n) returns the Bessel function of the second kind of order n of x. **zero(...)** zero(n) returns an *mpfr* inialized to 0.0 with the same sign as n. If n is not given, +0.0 is returned. **zeta(...)** zeta(x) returns the Riemann zeta of x. mpfr Formatting --------------- The *mpfr* type supports the __format__() special method to allow custom output formatting. **__format__(...)** x.__format__(fmt) returns a Python string by formatting 'x' using the format string 'fmt'. A valid format string consists of: | 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:: The formatting codes must be specified in the order shown above. :: >>> 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-2.0.7/docs/mpc.rst0000666000000000000000000002330512204747352013532 0ustar rootrootMultiple-precision Complex ========================== 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 specifiy 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 Methods ----------- **conjugate()** Returns the complex conjugate. **digits()** Returns a two element tuple where each element represents the real and imaginary components as a 3-tuple containing the mantissa, the exponent, and the number of bits of precision. The mantissa is represented as a string in the specified base with up to 'prec' digits. If 'prec' is 0, as many digits that are available are returned. No more digits than available given x's precision are returned. 'base' must be between 2 and 62, inclusive. mpc Attributes -------------- **imag** Returns the imaginary component. **precision** Returns a 2-tuple containing the the precision of the real and imaginary components. **rc** Returns a 2-tuple containing the ternary value of the real and imaginary components. The ternary value is 0 if the value of the component is exactly equal to the exact, infinite precision value. If the result code is 1, then the value of the component is greater than the exact value. If the result code is -1, then the value of the component is less than the exact, infinite precision value. **real** Returns the real component. mpc Functions ------------- **acos(...)** acos(x) returns the arc-cosine of x. **acosh(...)** acosh(x) returns the inverse hyperbolic cosine of x. **add(...)** add(x, y) returns x + y. The type of the result is based on the types of the arguments. **asin(...)** asin(x) returns the arc-sine of x. **asinh(...)** asinh(x) return the inverse hyperbolic sine of x. **atan(...)** atan(x) returns the arc-tangent of x. **atanh(...)** atanh(x) returns the inverse hyperbolic tangent of x. **cos(...)** cos(x) seturns the cosine of x. **cosh(...)** cosh(x) returns the hyperbolic cosine of x. **div(...)** div(x, y) returns x / y. The type of the result is based on the types of the arguments. **div_2exp(...)** div_2exp(x, n) returns an 'mpfr' or 'mpc' divided by 2**n. **exp(...)** exp(x) returns e**x. **fma(...)** fma(x, y, z) returns correctly rounded result of (x * y) + z. **fms(...)** fms(x, y, z) returns correctly rounded result of (x * y) - z. **is_inf(...)** is_inf(x) returns True if either the real or imaginary component of x is Infinity or -Infinity. **is_nan(...)** is_nan(x) returns True if either the real or imaginary component of x is NaN (Not-A-Number). **is_zero(...)** is_zero(x) returns True if x is zero. **log(...)** log(x) returns the natural logarithm of x. **log10(...)** log10(x) returns the base-10 logarithm of x. **mpc(...)** mpc() returns an *mpc* object set to 0.0+0.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 precision can be specified either a single number that is used for both the real and imaginary components, or as a 2-tuple that can specify different precisions for the real and imaginary components. **mpc_random(...)** mpfc_random(random_state) returns a uniformly distributed number in the unit square [0,1]x[0,1]. The parameter *random_state* must be created by random_state() first. **mul(...)** mul(x, y) returns x * y. The type of the result is based on the types of the arguments. **mul_2exp(...)** mul_2exp(x, n) returns 'mpfr' or 'mpc' multiplied by 2**n. **norm(...)** norm(x) returns the norm of a complex x. The norm(x) is defined as x.real**2 + x.imag**2. abs(x) is the square root of norm(x). **phase(...)** phase(x) returns the phase angle, also known as argument, of a complex x. **polar(...)** polar(x) returns the polar coordinate form of a complex x that is in rectangular form. **proj(...)** proj(x) returns the projection of a complex x on to the Riemann sphere. **rect(...)** rect(x) returns the polar coordinate form of a complex x that is in rectangular form. **sin(...)** sin(x) returns the sine of x. **sinh(...)** sinh(x) returns the hyberbolic sine of x. **sqrt(...)** sqrt(x) returns the square root of x. If x is integer, rational, or real, then an *mpfr* will be returned. If x is complex, then an *mpc* will be returned. If context.allow_complex is True, negative values of x will return an *mpc*. **square(...)** square(x) returns x * x. The type of the result is based on the types of the arguments. **sub(...)** sub(x, y) returns x - y. The type of the result is based on the types of the arguments. **tan(...)** tan(x) returns the tangent of x. x is measured in radians. **tanh(...)** tanh(x) returns the hyperbolic tangent of x. mpc Formatting -------------- The *mpc* type supports the __format__() special method to allow custom output formatting. **__format__(...)** x.__format__(fmt) returns a Python string by formatting 'x' using the format string 'fmt'. A valid format string consists of: | 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:: The formatting codes must be specified in the order shown above. :: >>> 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 ' gmpy2-2.0.7/docs/Makefile0000666000000000000000000001075212204747352013663 0ustar rootroot# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GMPY2.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GMPY2.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/GMPY2" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GMPY2" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." gmpy2-2.0.7/docs/make.bat0000644000000000000000000001063512204747352013624 0ustar rootroot@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\GMPY2.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\GMPY2.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end gmpy2-2.0.7/docs/intro.rst0000666000000000000000000003054112341422134014074 0ustar rootrootIntroduction to gmpy2 ===================== 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: * GMP for integer and rational arithmetic Home page: http://gmplib.org * MPIR is based on the GMP library but adds support for Microsoft's Visual Studio compiler. It is used to create the Windows binaries. Home page: http://www.mpir.org * MPFR for correctly rounded real floating-point arithmetic Home page: http://www.mpfr.org * MPC for correctly rounded complex floating-point arithmetic Home page: http://mpc.multiprecision.org * Generalized Lucas sequences and primality tests are based on the following code: mpz_lucas: http://sourceforge.net/projects/mpzlucas/ mpz_prp: http://sourceforge.net/projects/mpzprp/ Changes in gmpy2 2.0.4 ---------------------- * Fixed bit_scan0() for negative values. * Added option to setup.py (--static) to support static linking. * Manpage is now installed in section 3. Changes in gmpy2 2.0.3 ---------------------- * Fixed bugs in lucas2() and atanh() that caused incorrect results. Changes in gmpy2 2.0.2 ---------------------- * Rebuild the Windows binary installers due to a bug in MPIR. * Correct test in is_extra_strong_lucas_prp(). Note: The incorrect test is not known to cause any errors. Changes in gmpy2 2.0.1 ---------------------- * Updated setup.py to work in more situations. * Corrected exception handling in basic operations with mpfr type. * Correct InvalidOperation exception not raised in certain circumstances. * invert() now raises an exception if the modular inverse does not exist. * Fixed internal exception in is_bpsw_prp() and is_strong_bpsw_prp(). * Updated is_extra_strong_lucas_prp() to latest version. Changes in gmpy2 2.0.0 ---------------------- * Fix segmentation fault in _mpmath_normalize (an undocumented helper function specifically for mpmath.) * Improved setup.py See below for documentation on the changes. * Fix issues when compiled without support for MPFR. * Conversion of too large an mpz to float now raises OverflowError instead of returning *inf*. * Renamed min2()/max2() to minnum()/maxnum() * The build and install process (i.e. setup.py) has been completely rewritten. See the Installation section for more information. * get_context() no longer accepts keyword arguments. Known issues in gmpy2 2.0.0 ----------------------------- * The test suite is still incomplete. Changes in gmpy2 2.0.0b4 ------------------------ * Added __ceil__, __floor__, __trunc__, and __round__ methods to mpz and mpq types. * Added __complex__ to mpc type. * round(mpfr) now correctly returns an mpz type. * If no arguments are given to mpz, mpq, mpfr, mpc, and xmpz, return 0 of the appropriate type. * Fix broken comparison between mpz and mpq when mpz is on the left. * Added __sizeof__ to all types. *Note: sys.getsizeof() calls __sizeof__ to get the memory size of a gmpy2 object. The returned value reflects the size of the allocated memory which may be larger than the actual minimum memory required by the object.* Known issues in gmpy2 2.0.0b4 ----------------------------- * The new test suite (test/runtest.py) is incomplete and some tests fail on Python 2.x due to formating issues. Changes in gmpy2 2.0.0b3 ------------------------ * mp_version(), mpc_version(), and mpfr_version() now return normal strings on Python 2.x instead of Unicode strings. * Faster conversion of the standard library Fraction type to mpq. * Improved conversion of the Decimal type to mpfr. * Consistently return OverflowError when converting "inf". * Fix mpz.__format__() when the format code includes "#". * Add is_infinite() and deprecate is_inf(). * Add is_finite() and deprecate is_number(). * Fixed the various is_XXX() tests when used with mpc. * Added caching for mpc objects. * Faster code path for basic operation is both operands are mpfr or mpc. * Fix mpfr + float segmentation fault. Changes in gmpy2 2.0.0b2 ------------------------ * Allow xmpz slice assignment to increase length of xmpz instance by specifying a value for stop. * Fixed reference counting bug in several is_xxx_prp() tests. * Added iter_bits(), iter_clear(), iter_set() methods to xmpz. * Added powmod() for easy access to three argument pow(). * Removed addmul() and submul() which were added in 2.0.0b1 since they are slower than just using Python code. * Bug fix in gcd_ext when both arguments are not mpz. * Added ieee() to create contexts for 32, 64, or 128 bit floats. * Bug fix in context() not setting emax/emin correctly if they had been changed earlier. * Contexts can be directly used in with statement without requiring set_context()/local_context() sequence. * local_context() now accepts an optional context. Changes in gmpy2 2.0.0b1 and earlier ------------------------------------ * Renamed functions that manipulate individual bits to bit_XXX() to align with bit_length(). * Added caching for mpq. * Added rootrem(), fib2(), lucas(), lucas2(). * Support changed hash function in Python 3.2. * Added is_even(), is_odd(). * Add caching of the calculated hash value. * Add xmpz (mutable mpz) type. * Fix mpq formatting issue. * Add read/write bit access using slices to xmpz. * Add read-only bit access using slices to mpz. * Add pack()/unpack() methods to split/join an integer into n-bit chunks. * Add support for MPFR (casevh) * Removed fcoform float conversion modifier. * Add support for MPC. * Added context manager. * Allow building with just GMP/MPIR if MPFR not available. * Allow building with GMP/MPIR and MPFR if MPC not available. * Removed most instance methods in favor of gmpy2.function. The general guideline is that *properties* of an instance can be done via instance methods but *functions* that return a new result are done using gmpy2.function. * Added __ceil__, __floor__, and __trunc__ methods since they are called by math.ceil(), math.floor(), and math.trunc(). * Removed gmpy2.pow() to avoid conflicts. * Removed gmpy2._copy and added xmpz.copy. * Added support for __format__. * Added as_integer_ratio, as_mantissa_exp, as_simple_fraction. * Updated rich_compare. * Require MPFR 3.1.0+ to get divby0 support. * Added fsum(), degrees(), radians(). * Updated random number generation support. * Changed license to LGPL 3+. * Added lucasu, lucasu_mod, lucasv, and lucasv_mod. *Based on code contributed by David Cleaver.* * Added probable-prime tests. *Based on code contributed by David Cleaver.* * Added to_binary()/from_binary. * Renamed numdigits() to num_digits(). * Added keyword precision to constants. * Added addmul() and submul(). * Added __round__(), round2(), round_away() for mpfr. * round() is no longer a module level function. * Renamed module functions min()/max() to min2()/max2(). * No longer conflicts with builtin min() and max() * Removed set_debug() and related functionality. Installation ============ Installing gmpy2 on Windows --------------------------- Pre-compiled versions of gmpy2 are available at `PyPi `_ . Please select the installer that corresponds to the version of Python installed on your computer. Note that either a 32 or 64-bit version of Python can be installed on a 64-bit version of Windows. If you get an error message stating that Python could not be found in the registry, you have the wrong version of the gmpy2 installer. Installing gmpy2 on Unix/Linux ------------------------------ Requirements ^^^^^^^^^^^^ gmpy2 has only been tested with recent versions of GMP, MPFR and MPC. Specifically, for integer and rational support, gmpy2 requires GMP 5.1.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. Short Instructions ^^^^^^^^^^^^^^^^^^ You will need to install the development libraries for Python, GMP, MPFR, and MPC. Different Linux distributions may the development packages differently. Typical names are libpython-dev, libgmp-dev, libmpfr-dev, and libmpc-dev. If your system includes recent versions of GMP, MPFR and MPC, and you have the development libraries installed, compiling should be as simple as: :: cd python setup.py build sudo python setup.py install If this fails, read on. Detailed Instructions ^^^^^^^^^^^^^^^^^^^^^ 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. setup.py will automatically search the following directories for the required libraries: #. /opt/local #. /opt #. /usr/local #. /usr #. /sw If you can't use one of these directories, you can use a directory located in your home directory. The examples will use /home//local. If you use one of standard directories (say /opt/local), then you won't need to specify --prefix=/home/case/local to setup.py but you will need to specify the prefix when compiling GMP, MPFR, and MPC. Please substitute your actual user name for . Create the desired destination directory for GMP, MPFR, and MPC. :: $ mkdir /home//local Download and un-tar the GMP source code. Change to the GMP source directory and compile GMP. :: $ cd /home//local/src/gmp-6.0.0 $ ./configure --prefix=/home//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//local/src/mpfr-3.1.2 $ ./configure --prefix=/home//local --with-gmp=/home//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//local/src/mpc-1.0.2 $ ./configure --prefix=/home//local --with-gmp=/home//local --with-mpfr=/home//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//local If you get a "permission denied" error message, you may need to use:: $ python setup.py build --prefix=/home//local $ sudo python setup.py install --prefix=/home//local Options for setup.py ^^^^^^^^^^^^^^^^^^^^ **--force** Ignore the timestamps on all files and recompile. Normally, the results of a previous compile are cached. To force gmpy2 to recognize external changes (updated version of GMP, etc.), you will need to use this option. **--mpir** Force the use of MPIR instead of GMP. GMP is the default library on non-Windows operating systems. **--gmp** Force the use of GMP instead of MPIR. MPIR is the default library on Windows operating systems. **--prefix=<...>** Specify the directory prefix where GMP/MPIR, MPFR, and MPC are located. For example, **--prefix=/opt/local** instructs setup.py to search /opt/local/include for header files and /opt/local/lib for libraries. **--nompfr** Disables support for MPFR and MPC. This option is intended for testing purposes and is not offically supported. MPFR will be required for future versions of gmpy2. **--nompc** Disables support for MPC. This option is intended for testing purposes and is not officially supported. MPC will be required for future versions of gmpy2. **--static** Builds a statically linked library. This option will likely require the use of --prefix=<...> to specify the directory where the static libraries are located. To successfully link with gmpy2, the GMP, MPFR, and MPC libraries must be compiled with the --with-pic option. gmpy2-2.0.7/docs/index.rst0000666000000000000000000000073712204747352014066 0ustar rootroot.. gmpy2 documentation master file, created by sphinx-quickstart on Fri Feb 24 19:56:16 2012. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to gmpy2's documentation! ================================= Contents: .. toctree:: :maxdepth: 2 intro overview mpz advmpz mpq mpfr mpc Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` gmpy2-2.0.7/docs/conf.py0000666000000000000000000001555712341422134013520 0ustar rootroot# -*- coding: utf-8 -*- # # gmpy2 documentation build configuration file, created by # sphinx-quickstart on Fri Feb 24 19:56:16 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.pngmath'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'gmpy2' copyright = u'2012, 2013, 2014 Case Van Horsen' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '2.0' # The full version, including alpha/beta/rc tags. release = '2.0.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'gmpy2doc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'gmpy2.tex', u'gmpy2 Documentation', u'Case Van Horsen', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'gmpy2', u'gmpy2 Documentation', [u'Case Van Horsen'], 3) ] gmpy2-2.0.7/docs/advmpz.rst0000666000000000000000000002022112204747352014246 0ustar rootrootMultiple-precision Integers (Advanced topics) ============================================= The xmpz type ------------- gmpy2 provides access to an experimental integer type called *xmpz*. The *xmpz* type is a mutable integer type. In-place operations (+=, //=, etc.) modify the orignal 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)) Advanced Number Theory Functions -------------------------------- 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 **is_bpsw_prp(...)** is_bpsw_prp(n) will return True if *n* is a Baillie-Pomerance-Selfridge-Wagstaff probable prime. A BPSW probable prime passes the is_strong_prp() test with base 2 and the is_selfridge_prp() test. **is_euler_prp(...)** is_euler_prp(n,a) will return True if *n* is an Euler (also known as Solovay-Strassen) probable prime to the base *a*. | Assuming: | gcd(n, a) == 1 | n is odd | | Then an Euler probable prime requires: | a**((n-1)/2) == 1 (mod n) **is_extra_strong_lucas_prp(...)** is_extra_strong_lucas_prp(n,p) will return True if *n* is an extra strong Lucas probable prime with parameters (p,1). | 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 **is_fermat_prp(...)** is_fermat_prp(n,a) will return True if *n* is a Fermat probable prime to the base a. | Assuming: | gcd(n,a) == 1 | | Then a Fermat probable prime requires: | a**(n-1) == 1 (mod n) **is_fibonacci_prp(...)** is_fibonacci_prp(n,p,q) will return True if *n* is an Fibonacci probable prime with parameters (p,q). | 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). **is_lucas_prp(...)** is_lucas_prp(n,p,q) will return True if *n* is a Lucas probable prime with parameters (p,q). | 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) **is_selfridge_prp(...)** is_selfridge_prp(n) will return True if *n* is a Lucas probable prime with Selfidge parameters (p,q). The Selfridge parameters are chosen by finding the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) == -1. Let p=1 and q = (1-D)/4 and then perform a Lucas probable prime test. **is_strong_bpsw_prp(...)** is_strong_bpsw_prp(n) will return True if *n* is a strong Baillie-Pomerance-Selfridge-Wagstaff probable prime. A strong BPSW probable prime passes the is_strong_prp() test with base 2 and the is_strongselfridge_prp() test. **is_strong_lucas_prp(...)** is_strong_lucas_prp(n,p,q) will return True if *n* is a strong Lucas probable prime with parameters (p,q). | 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 **is_strong_prp(...)** is_strong_prp(n,a) will return True if *n* is an strong (also known as Miller-Rabin) probable prime to the base a. | 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. **is_strong_selfridge_prp(...)** is_strong_selfridge_prp(n) will return True if *n* is a strong Lucas probable prime with Selfidge parameters (p,q). The Selfridge parameters are chosen by finding the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) == -1. Let p=1 and q = (1-D)/4 and then perform a strong Lucas probable prime test. **lucasu(...)** lucasu(p,q,k) will return the k-th element of the Lucas U sequence defined by p,q. p*p - 4*q must not equal 0; k must be greater than or equal to 0. **lucasu_mod(...)** lucasu_mod(p,q,k,n) will return the k-th element of the Lucas U sequence defined by p,q (mod n). p*p - 4*q must not equal 0; k must be greater than or equal to 0; n must be greater than 0. **lucasv(...)** lucasv(p,q,k) will return the k-th element of the Lucas V sequence defined by parameters (p,q). p*p - 4*q must not equal 0; k must be greater than or equal to 0. **lucasv_mod(...)** lucasv_mod(p,q,k,n) will return the k-th element of the Lucas V sequence defined by parameters (p,q) (mod n). p*p - 4*q must not equal 0; k must be greater than or equal to 0; n must be greater than 0. gmpy2-2.0.7/build.vc9/0000755000000000000000000000000012567136721013065 5ustar rootrootgmpy2-2.0.7/build.vc9/gmpy2.sln0000666000000000000000000000540612204747360014645 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python27", "gmpy2.python27\gmpy2.python27.vcproj", "{3960600D-E796-4080-A23D-299A7B6A1098}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python31", "gmpy2.python31\gmpy2.python31.vcproj", "{2EB66D8F-F107-41CD-AB07-B5512523935C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python26", "gmpy2.python26\gmpy2.python26.vcproj", "{4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3960600D-E796-4080-A23D-299A7B6A1098}.Debug|Win32.ActiveCfg = Debug|Win32 {3960600D-E796-4080-A23D-299A7B6A1098}.Debug|Win32.Build.0 = Debug|Win32 {3960600D-E796-4080-A23D-299A7B6A1098}.Debug|x64.ActiveCfg = Debug|x64 {3960600D-E796-4080-A23D-299A7B6A1098}.Debug|x64.Build.0 = Debug|x64 {3960600D-E796-4080-A23D-299A7B6A1098}.Release|Win32.ActiveCfg = Release|Win32 {3960600D-E796-4080-A23D-299A7B6A1098}.Release|Win32.Build.0 = Release|Win32 {3960600D-E796-4080-A23D-299A7B6A1098}.Release|x64.ActiveCfg = Release|x64 {3960600D-E796-4080-A23D-299A7B6A1098}.Release|x64.Build.0 = Release|x64 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Debug|Win32.ActiveCfg = Debug|Win32 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Debug|Win32.Build.0 = Debug|Win32 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Debug|x64.ActiveCfg = Debug|x64 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Debug|x64.Build.0 = Debug|x64 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Release|Win32.ActiveCfg = Release|Win32 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Release|Win32.Build.0 = Release|Win32 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Release|x64.ActiveCfg = Release|x64 {2EB66D8F-F107-41CD-AB07-B5512523935C}.Release|x64.Build.0 = Release|x64 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Debug|Win32.ActiveCfg = Debug|Win32 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Debug|Win32.Build.0 = Debug|Win32 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Debug|x64.ActiveCfg = Debug|x64 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Debug|x64.Build.0 = Debug|x64 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Release|Win32.ActiveCfg = Release|Win32 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Release|Win32.Build.0 = Release|Win32 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Release|x64.ActiveCfg = Release|x64 {4A305DD3-5FE9-4B76-AB1F-8C0C2263BEF8}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal gmpy2-2.0.7/build.vc10/0000755000000000000000000000000012567136721013135 5ustar rootrootgmpy2-2.0.7/build.vc10/gmpy2.sln0000666000000000000000000001044312204747362014714 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python27", "gmpy2.python27\gmpy2.python27.vcxproj", "{2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python31", "gmpy2.python31\gmpy2.python31.vcxproj", "{EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python26", "gmpy2.python26\gmpy2.python26.vcxproj", "{BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python32", "gmpy2.python32\gmpy2.python32.vcxproj", "{B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmpy2.python33", "gmpy2.python33\gmpy2.python33.vcxproj", "{3CC03A4A-FA38-473F-B3D7-0B9660B758AA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Debug|Win32.ActiveCfg = Debug|Win32 {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Debug|Win32.Build.0 = Debug|Win32 {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Debug|x64.ActiveCfg = Debug|x64 {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Debug|x64.Build.0 = Debug|x64 {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Release|Win32.ActiveCfg = Release|Win32 {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Release|Win32.Build.0 = Release|Win32 {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Release|x64.ActiveCfg = Release|x64 {2410C45F-AA6C-4F9E-9B4F-E1F9356C3DFE}.Release|x64.Build.0 = Release|x64 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Debug|Win32.ActiveCfg = Debug|Win32 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Debug|Win32.Build.0 = Debug|Win32 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Debug|x64.ActiveCfg = Debug|x64 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Debug|x64.Build.0 = Debug|x64 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Release|Win32.ActiveCfg = Release|Win32 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Release|Win32.Build.0 = Release|Win32 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Release|x64.ActiveCfg = Release|x64 {EC1A078B-F935-4FE6-9558-C90EDFD1E0FC}.Release|x64.Build.0 = Release|x64 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Debug|Win32.ActiveCfg = Debug|Win32 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Debug|Win32.Build.0 = Debug|Win32 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Debug|x64.ActiveCfg = Debug|x64 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Debug|x64.Build.0 = Debug|x64 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Release|Win32.ActiveCfg = Release|Win32 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Release|Win32.Build.0 = Release|Win32 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Release|x64.ActiveCfg = Release|x64 {BA1902F2-29B2-4F1B-8C67-2977E7EFE8D4}.Release|x64.Build.0 = Release|x64 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Debug|Win32.ActiveCfg = Debug|Win32 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Debug|Win32.Build.0 = Debug|Win32 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Debug|x64.ActiveCfg = Debug|x64 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Debug|x64.Build.0 = Debug|x64 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Release|Win32.ActiveCfg = Release|Win32 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Release|Win32.Build.0 = Release|Win32 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Release|x64.ActiveCfg = Release|x64 {B7EF078D-1DE7-45B7-9764-D1BF1BB57EE6}.Release|x64.Build.0 = Release|x64 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Debug|Win32.ActiveCfg = Debug|Win32 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Debug|Win32.Build.0 = Debug|Win32 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Debug|x64.ActiveCfg = Debug|x64 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Debug|x64.Build.0 = Debug|x64 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Release|Win32.ActiveCfg = Release|Win32 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Release|Win32.Build.0 = Release|Win32 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Release|x64.ActiveCfg = Release|x64 {3CC03A4A-FA38-473F-B3D7-0B9660B758AA}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal gmpy2-2.0.7/win_x64_sdk_build.txt0000666000000000000000000000615112204747362015351 0ustar rootroot Building MPIR and GMPY using the Windows SDK tools It is possible to build MPIR and GMPY from source on a Microsoft Windows platform using the command-line compiler that is included with the Microsoft Platform SDK. I've documented the process for a 64-bit build. The operating system was Windows XP x64. The process isn't difficult but assumes some familiarity with the command line. 1) You should have an program for processing .zip and .tar.gz archives. 2) Python should be installed on your system and the installation directory should be added to your system's PATH environment variable. 3) Install .NET Framework 2.0 or later. (This is required for the installer used by the SDK.) 4) Install the Microsoft Windows SDK. I used "Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 Service Pack 1". It can be found at "http://msdn.microsoft.com/en-us/windowsserver/bb980924.aspx". Use the version appropriate for your system: X86 for a 32-bit system or AMD64 for a 64-bit system. 5) Download the current version of the YASM assembler. It can be found at "http://www.tortall.net/projects/yasm/". Again, use the version approp- riate for your system. The executable must be renamed to "yasm.exe" and copied to the SDK installation directory, typically: C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin 6) Create a directory to use for the build process. I used C:\src. mkdir c:\src 7) Download the GMPY and MPIR source code. This example uses gmpy-1.12.zip and mpir-2.1.1.tar.gz. They should be unzipped (or untarred) into c:\src. There should be c:\src\gmpy-1.12 and c:\src\mpir-2.1.1 directories in c:\src. 8) The file "yasm.rules" must be copied from c:\src\mpir-2.1.1\build.vc9\ to C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCProjectDefaults 9) Open a command window and enter the following commands: rem Configure the environment for 64-bit builds. rem Use "vcvars32.bat" for a 32-bit build. "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat" rem Build mpir first. cd C:\src\mpir-2.1.1\build.vc9 rem Check contents of configure.bat to see allowed options. Verify that rem all tests pass. rem 64-bit binaries were built with --cpu-k8. configure make make check rem Copy the required to a convenient location for gmpy. rem The files are located in "lib\Win32\release" for 32-bit rem build. mkdir c:\src\lib mkdir c:\src\include xcopy /Y lib\x64\release\*.h c:\src\include\*.* xcopy /Y lib\x64\release\*.??b c:\src\lib\*.* rem Done with mpir, now build gmpy. cd c:\src\gmpy-1.12 rem Convince setup.py to use the SDK tools. set MSSdk=1 set DISTUTILS_USE_SDK=1 rem Build and install gmpy.pyd python setup.py build_ext -DMPIR -Ic:\src\include -Lc:\src\lib install rem Run the test suite python test\gmpy_test.py rem (Optional) Build an installer, located in c:\src\gmpy-1.12\dist. python setup.py bdist_wininst gmpy2-2.0.7/windows_build.txt0000666000000000000000000001247512542614506014710 0ustar rootrootAssumptions =========== The build files for MPIR, MPFR, and MPC only support VS 2010. However, if VS 2008 is also installed, the "Platform Toolset" setting can be used to select a specific compiler: v100 = VS 2010, v90 = VS 2008. Assumes MPIR is placed in c:\src\mpir. (No version number.) Assumes MPFR is placed in c:\src\mpfr. (No version number.) Assumes MPC is placed in c:\src\mpc. (No version number.) Assumes gmpy2 is placed in c:\src\gmpy2. (No version number.) Assumes vsyasm is installed. Compiling MPIR ============== cd c:\src\mpir\build.vc10 python mpir_config.py # enter 3 (Pentium 3) and 18 (AMD K8) Start Visual Studio 2010 and open c:\src\mpir\build.vc10\mpir.sln. Select "Release" and "Win32" Open "lib_mpir_p3" properties - Change "Platform Toolset" if needed. - Change "Character Set" to "Not Set". (Probably not needed.) - Change "Optimization" to "/O2". (Set uniformly in MPFR and MPC too.) - Change "Runtime Library" to "Multi-threaded DLL /MD". - Change "Buffer Security Check" to "No". Select "Build" - Ignore preinv* warnings (I think) - Ignore *_ux and *_sx warnings if using v90 toolset (i.e. VS2008). Select "Release" and "x64" Open "lib_mpir_k8" properties - Change "Platform Toolset" if needed. - Change "Character Set" to "Not Set". (Probably not needed.) - Change "Optimization" to "/O2". (Set uniformly in MPFR and MPC too.) - Change "Runtime Library" to "Multi-threaded DLL /MD". - Change "Buffer Security Check" to "No". Select "Build" - Ignore preinv* warnings (I think) - Ignore *_ux and *_sx warnings if using v90 toolset (i.e. VS2008). Compiling MPFR ============== Start Visual Studio 2010 and open c:\src\mpfr\build.vc10\lib_mpfr.sln. Select "Release" and "Win32" Open "lib_mpfr" properties - Change "Platform Toolset: if needed. - Change settings to match MPIR except "Enable Fiber-Safe Optimizations" should be set. Select "Build" Select "Release" and "x64" Open "lib_mpfr" properties - Change "Platform Toolset: if needed. - Change settings to match MPIR except "Enable Fiber-Safe Optimizations" should be set. Select "Build" Compiling MPC ============= Start Visual Studio 2010 and open c:\src\mpfr\build.vc10\mpc.sln. Select "Release" and "Win32" Open "mpc_lib" properties - Change "Platform Toolset: if needed. - Change remaining settings to match MPIR. Select "Build" Select "Release" and "x64" Open "lib_mpfr" properties - Change "Platform Toolset: if needed. - Change remaining settings to match MPIR. Select "Build" Copy the library files ====================== The header files will be copied c:\src\BB\vsNNNN\include and the library files will be copied to c:\src\BB\vsNNNN\lib where BB is 32 or 64, and NNNN is 2008 or 2010. 32-bit, VS 2008 cd c:\src xcopy /y c:\src\mpir\lib\Win32\Release\*.h c:\src\32\vs2008\include\ xcopy /y c:\src\mpir\lib\Win32\Release\*.lib c:\src\32\vs2008\lib\ xcopy /y c:\src\mpfr\lib\Win32\Release\*.h c:\src\32\vs2008\include\ xcopy /y c:\src\mpfr\lib\Win32\Release\*.lib c:\src\32\vs2008\lib\ xcopy /y c:\src\mpc\lib\Win32\Release\*.h c:\src\32\vs2008\include\ xcopy /y c:\src\mpc\lib\Win32\Release\*.lib c:\src\32\vs2008\lib\ 64-bit, VS 2008 cd c:\src xcopy /y c:\src\mpir\lib\x64\Release\*.h c:\src\64\vs2008\include\ xcopy /y c:\src\mpir\lib\x64\Release\*.lib c:\src\64\vs2008\lib\ xcopy /y c:\src\mpfr\lib\x64\Release\*.h c:\src\64\vs2008\include\ xcopy /y c:\src\mpfr\lib\x64\Release\*.lib c:\src\64\vs2008\lib\ xcopy /y c:\src\mpc\lib\x64\Release\*.h c:\src\64\vs2008\include\ xcopy /y c:\src\mpc\lib\x64\Release\*.lib c:\src\64\vs2008\lib\ 32-bit, VS 2010 cd c:\src xcopy /y c:\src\mpir\lib\Win32\Release\*.h c:\src\32\vs2010\include\ xcopy /y c:\src\mpir\lib\Win32\Release\*.lib c:\src\32\vs2010\lib\ xcopy /y c:\src\mpfr\lib\Win32\Release\*.h c:\src\32\vs2010\include\ xcopy /y c:\src\mpfr\lib\Win32\Release\*.lib c:\src\32\vs2010\lib\ xcopy /y c:\src\mpc\lib\Win32\Release\*.h c:\src\32\vs2010\include\ xcopy /y c:\src\mpc\lib\Win32\Release\*.lib c:\src\32\vs2010\lib\ 64-bit, VS 2010 cd c:\src xcopy /y c:\src\mpir\lib\x64\Release\*.h c:\src\64\vs2010\include\ xcopy /y c:\src\mpir\lib\x64\Release\*.lib c:\src\64\vs2010\lib\ xcopy /y c:\src\mpfr\lib\x64\Release\*.h c:\src\64\vs2010\include\ xcopy /y c:\src\mpfr\lib\x64\Release\*.lib c:\src\64\vs2010\lib\ xcopy /y c:\src\mpc\lib\x64\Release\*.h c:\src\64\vs2010\include\ xcopy /y c:\src\mpc\lib\x64\Release\*.lib c:\src\64\vs2010\lib\ Compile gmpy2 ============= c:\32\Python26\python.exe setup.py build_ext -f -Ddir=c:\src\32\vs2008 bdist_wininst c:\32\Python27\python.exe setup.py build_ext -f -Ddir=c:\src\32\vs2008 bdist_wininst c:\32\Python32\python.exe setup.py build_ext -f -Ddir=c:\src\32\vs2008 bdist_wininst c:\32\Python33\python.exe setup.py build_ext -f -Ddir=c:\src\32\vs2010 bdist_wininst c:\32\Python34\python.exe setup.py build_ext -f -Ddir=c:\src\32\vs2010 bdist_wininst c:\64\Python26\python.exe setup.py build_ext -f -Ddir=c:\src\64\vs2008 bdist_wininst c:\64\Python27\python.exe setup.py build_ext -f -Ddir=c:\src\64\vs2008 bdist_wininst c:\64\Python32\python.exe setup.py build_ext -f -Ddir=c:\src\64\vs2008 bdist_wininst c:\64\Python33\python.exe setup.py build_ext -f -Ddir=c:\src\64\vs2010 bdist_wininst c:\64\Python34\python.exe setup.py build_ext -f -Ddir=c:\src\64\vs2010 bdist_wininst gmpy2-2.0.7/setup.py0000666000000000000000000002460712564433154013012 0ustar rootrootimport sys import os from distutils.core import setup, Extension from distutils.command.clean import clean from distutils.command.build_ext import build_ext from distutils.sysconfig import get_python_inc, get_python_lib def writeln(s): sys.stdout.write('%s\n' % s) sys.stdout.flush() # Some operating systems may use a different library directory under the # prefix specified by --shared. It must be manually changed. lib_path = 'lib' # Fail gracefully for old versions of Python. if sys.version[:3] < '2.6': writeln("GMPY2 requires Python 2.6 or later.") writeln("Please use GMPY 1.x for earlier versions of Python.") sys.exit() # Improved clean command. class gmpy_clean(clean): def run(self): self.all = True clean.run(self) # Define a custom build class to force a new build. class gmpy_build_ext(build_ext): # Extract the version information from the various header files. Since header # store the information differently, a separate function is provided for each # library. def check_versions(self): # Check the specified list of include directories to verify that valid # versions of MPFR and MPC are available. If so, add entries to the # appropriate lists # Find the directory specfied for SHARED or STATIC. prefix = [] for d in self.extensions[0].define_macros[:]: if d[0] in ('SHARED', 'STATIC'): if d[1]: prefix.extend(map(os.path.expanduser, d[1].split(":"))) try: self.extensions[0].define_macros.remove(d) except ValueError: pass if sys.version.find('MSC') == -1: windows = False base_dir = ['/usr'] addin_dirs = ['/usr/local'] else: windows = True base_dir = [] addin_dirs = [] if prefix: search_dirs = base_dir + addin_dirs + prefix else: search_dirs = base_dir + addin_dirs if 'gmp' in self.extensions[0].libraries: mplib = 'gmp' else: mplib = 'mpir' use_mpfr = 'mpfr' in self.extensions[0].libraries use_mpc = 'mpc' in self.extensions[0].libraries if not search_dirs: return gmp_found = '' mpfr_found = '' mpc_found = '' for adir in search_dirs: lookin = os.path.join(adir, 'include') if os.path.isfile(os.path.join(lookin, mplib + '.h')): gmp_found = adir if os.path.isfile(os.path.join(lookin, 'mpfr.h')): mpfr_found = adir if os.path.isfile(os.path.join(lookin, 'mpc.h')): mpc_found = adir # Add the directory information for location where valid versions were # found. This can cause confusion if there are multiple installations of # the same version of Python on the system. for adir in (gmp_found, mpfr_found, mpc_found): if not adir: continue if adir in base_dir: continue if os.path.join(adir, 'include') in self.extensions[0].include_dirs: continue self.extensions[0].include_dirs += [os.path.join(adir, 'include')] self.extensions[0].library_dirs += [os.path.join(adir, lib_path)] if shared and not windows: self.extensions[0].runtime_library_dirs += [os.path.join(adir, lib_path)] def finalize_options(self): build_ext.finalize_options(self) gmpy_build_ext.check_versions(self) # Check if --force was specified. for i,d in enumerate(self.extensions[0].define_macros[:]): if d[0] == 'FORCE': self.force = 1 try: self.extensions[0].define_macros.remove(d) except ValueError: pass # Several command line options can be used to modify compilation of GMPY2. To # maintain backwards compatibility with older versions of setup.py, the old # options are still supported. # # New-style options # # --force -> ignore timestamps and recompile # --mpir -> use MPIR instead of GMP (GMP is the default on # non-Windows operating systems) # --gmp -> use GMP instead of MPIR # --nompfr -> disable MPFR and MPC library support # --nompc -> disable MPC support (MPFR should still work) # --lib64 -> use /<...>/lib64 instead of /<...>/lib # --prefix=<...> -> add the specified directory prefix to the beginning of # the list of directories that are searched for GMP, MPFR, # and MPC shared libraries # --static=<...> -> create a statically linked library using static files from # the specified directory # # Old-stype options # # -DMPIR -> use MPIR instead of GMP # -DGMP -> use GMP instead of MPIR # -DNOMPFR -> disable MPFR and MPC library support # -DNOMPC -> disable MPC support (MPFR should still work) # -Ddir=<...> -> add the specified directory to beginning of the list of # directories that are searched for GMP, MPFR, and MPC # Windows build defaults to using MPIR. if sys.version.find('MSC') == -1: mplib='gmp' else: mplib='mpir' # If 'clean' is the only argument to setup.py then we want to skip looking for # header files. if sys.argv[1].lower() in ['build', 'install']: do_search = True else: do_search = False # Parse command line arguments. If custom prefix location is specified, it is # passed as a define so it can be processed in the custom build_ext defined # above. defines = [] # Beginning with v2.1.0, MPFR and MPC will be required. use_mpc = True use_mpfr = True force = False static = False shared = False for token in sys.argv[:]: if token.lower() == '--force': defines.append( ('FORCE', 1) ) sys.argv.remove(token) if token.lower() == '--lib64': lib_path = '/lib64' sys.argv.remove(token) if token.lower() == '--mpir': mplib = 'mpir' sys.argv.remove(token) if token.lower() == '--gmp': mplib = 'gmp' sys.argv.remove(token) if token.lower() == '--nompc': use_mpc = False sys.argv.remove(token) if token.lower() == '--nompfr': use_mpfr = False use_mpc = False sys.argv.remove(token) if token.lower().startswith('--shared'): shared = True try: defines.append( ('SHARED', token.split('=')[1]) ) except IndexError: pass sys.argv.remove(token) if token.lower().startswith('--static'): static = True try: defines.append( ('STATIC', token.split('=')[1]) ) except IndexError: pass sys.argv.remove(token) # The following options are deprecated and will be removed in the future. if token.upper().startswith('-DMPIR'): mplib='mpir' sys.argv.remove(token) writeln('The -DMPIR option is deprecated. Use --mpir instead.') if token.upper().startswith('-DGMP'): mplib='gmp' sys.argv.remove(token) writeln('The -DGMP option is deprecated. Use --gmp instead.') if token.upper().startswith('-DNOMPC'): use_mpc = False sys.argv.remove(token) writeln('The -DNOMPC option is deprecated. Use --nompc instead.') if token.upper().startswith('-DNOMPFR'): use_mpfr = False use_mpc = False sys.argv.remove(token) writeln('The -DNOMPFR option is deprecated. Use --nompfr instead.') if token.upper().startswith('-DDIR'): try: defines.append( ('SHARED', token.split('=')[1]) ) except: writeln('Please include a directory location.') sys.argv.remove(token) writeln('The -DDIR option is deprecated. Use --shared instead.') incdirs = ['./src'] libdirs = [] rundirs = [] extras = [] # Specify extra link arguments for Windows. if sys.version.find('MSC') == -1: my_extra_link_args = None else: my_extra_link_args = ["/MANIFEST"] mp_found = False prefix = '' for i,d in enumerate(defines): if d[0] in ('SHARED', 'STATIC'): prefix = d[1] if mplib == 'mpir': defines.append( ('MPIR', None) ) libs = ['mpir'] if static: extras.append(os.path.join(prefix, lib_path, 'libmpir.a')) else: libs = ['gmp'] if static: extras.append(os.path.join(prefix, lib_path, 'libgmp.a')) if use_mpfr: defines.append( ('WITHMPFR', None) ) libs.append('mpfr') if static: extras.append(os.path.join(prefix, lib_path, 'libmpfr.a')) if use_mpc: defines.append( ('WITHMPC', None) ) libs.append('mpc') if static: extras.append(os.path.join(prefix, lib_path, 'libmpc.a')) # decomment next line (w/gcc, only!) to support gcov # os.environ['CFLAGS'] = '-fprofile-arcs -ftest-coverage -O0' # prepare the extension for building my_commands = {'clean' : gmpy_clean, 'build_ext' : gmpy_build_ext} gmpy2_ext = Extension('gmpy2', sources=[os.path.join('src', 'gmpy2.c')], libraries=libs, define_macros = defines, extra_objects = extras, extra_link_args = my_extra_link_args) setup(name = "gmpy2", version = "2.0.7", maintainer = "Case Van Horsen", maintainer_email = "casevh@gmail.com", url = "http://code.google.com/p/gmpy/", description = "GMP/MPIR, MPFR, and MPC interface to Python 2.6+ and 3.x", classifiers = [ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'Intended Audience :: Science/Research' 'License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)', 'Natural Language :: English', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Programming Language :: C', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: Implementation :: CPython', 'Topic :: Scientific/Engineering :: Mathematics', 'Topic :: Software Development :: Libraries :: Python Modules', ], cmdclass = my_commands, ext_modules = [gmpy2_ext] ) gmpy2-2.0.7/README0000666000000000000000000000621112204747362012147 0ustar rootrootInstalling gmpy2 on Unix/Linux ------------------------------ Requirements 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. The MPC and MPFR libraries are optional. If the MPC library is not available, gmpy2 will still support integer, rational, and real floating-point arithmetic. If the MPFR library is not available, gmpy2 will only support integer and rational arithmetic. The mpf type included with GMP is no longer supported. Quick Instructions If your system includes sufficiently recent versions of GMP, MPFR and MPC, and you have the development libraries installed, compiling should be as simple as: $ cd $ python setup.py install If this fails, read on. Detailed Instructions 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. setup.py will automatically search the following directories for the required libraries: 1) /opt/local 2) /opt 3) /usr/local 4) /usr 5) /sw If you can't use one of these directories, you can use a directory located in your home directory. The examples will use /home/case/local. If you use one of standard directories (say /opt/local), then you won't need to specify --prefix=/home/case/local to setup.py but you will need to specify the prefix when compiling GMP, MPFR, and MPC. Create the desired destination directory for GMP, MPFR, and MPC. $ mkdir /home/case/local Download and un-tar the GMP source code. Change to GMP source directory and compile GMP. $ cd /home/case/local/src/gmp-5.1.0 $ ./configure --prefix=/home/case/local $ make $ make check $ make install Download and un-tar the MPFR source code. Change to MPFR source directory and compile MPFR. $ cd /home/case/local/mpfr-3.1.1 $ ./configure --prefix=/home/case/local --with-gmp=/home/case/local $ make $ make check $ make install Download and un-tar the MPC source code. Change to MPC source directory and compile MPC. $ cd /home/case/local/mpc-1.0.1 $ ./configure --prefix=/home/case/local --with-gmp=/home/case/local --with-mpfr=/home/case/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 gmpy2-2.0.7/PKG-INFO0000666000000000000000000000200412564433260012356 0ustar rootrootMetadata-Version: 1.1 Name: gmpy2 Version: 2.0.7 Summary: GMP/MPIR, MPFR, and MPC interface to Python 2.6+ and 3.x Home-page: http://code.google.com/p/gmpy/ Author: Case Van Horsen Author-email: casevh@gmail.com License: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Science/ResearchLicense :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Classifier: Natural Language :: English Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Programming Language :: C Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Topic :: Scientific/Engineering :: Mathematics Classifier: Topic :: Software Development :: Libraries :: Python Modules gmpy2-2.0.7/COPYING.LESSER0000666000000000000000000001674312204747362013331 0ustar rootroot GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. gmpy2-2.0.7/COPYING0000666000000000000000000010451312204747362012326 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read .