From 6ed45bb719486b67e3cdab65ac7f23ddb4e9059e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Tue, 31 Mar 2026 19:46:33 -0300 Subject: [PATCH 01/18] ecl: update to 26.3.27. --- common/shlibs | 2 +- srcpkgs/ecl/files/cross_config | 4 +++- srcpkgs/ecl/template | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/common/shlibs b/common/shlibs index 7d054d773f6672..9ca8a92ba7d849 100644 --- a/common/shlibs +++ b/common/shlibs @@ -4250,7 +4250,7 @@ libcxsparse.so.4 SuiteSparse-6.0.1_1 libspqr.so.4 SuiteSparse-7.2.0_1 libsuitesparseconfig.so.7 SuiteSparse-7.0.1_1 libumfpack.so.6 SuiteSparse-6.0.1_1 -libecl.so.24.5 ecl-24.5.10_1 +libecl.so.26.3 ecl-26.3.27_1 libecm.so.1 ecm-7.0.4_3 libcliquer.so.1 cliquer-1.22_1 libomalloc-0.9.6.so singular-4.2.1_1 diff --git a/srcpkgs/ecl/files/cross_config b/srcpkgs/ecl/files/cross_config index 78b074c3c7c0e2..d490c2d0bbf7e6 100644 --- a/srcpkgs/ecl/files/cross_config +++ b/srcpkgs/ecl/files/cross_config @@ -13,10 +13,11 @@ ECL_STACK_DIR=down ### 1.2) Choose an integer datatype which is large enough to host a pointer if [ "$XBPS_TARGET_WORDSIZE" = "64" ]; then - CL_FIXNUM_TYPE="long long int" + CL_FIXNUM_TYPE=long CL_FIXNUM_BITS=64 CL_FIXNUM_MAX=2305843009213693951LL CL_FIXNUM_MIN=-2305843009213693952LL + CL_SHORT_BITS=16 CL_INT_BITS=32 CL_LONG_BITS=64 else @@ -24,6 +25,7 @@ else CL_FIXNUM_BITS=32 CL_FIXNUM_MAX=536870911L CL_FIXNUM_MIN=-536870912L + CL_SHORT_BITS=16 CL_INT_BITS=32 CL_LONG_BITS=32 fi diff --git a/srcpkgs/ecl/template b/srcpkgs/ecl/template index de21325cb01876..2fdcfdf8656c83 100644 --- a/srcpkgs/ecl/template +++ b/srcpkgs/ecl/template @@ -1,6 +1,6 @@ # Template file for 'ecl' pkgname=ecl -version=24.5.10 +version=26.3.27 revision=1 build_style=gnu-configure configure_args="--enable-gmp=system --enable-boehm=system @@ -14,7 +14,7 @@ license="LGPL-2.1-or-later" homepage="https://ecl.common-lisp.dev/" changelog="https://gitlab.com/embeddable-common-lisp/ecl/-/raw/develop/CHANGELOG" distfiles="https://ecl.common-lisp.dev/static/files/release/ecl-${version}.tgz" -checksum=e4ea65bb1861e0e495386bfa8bc673bd014e96d3cf9d91e9038f91435cbe622b +checksum=416d5707bf11d2b3d8d33d6791419a786e4cc59ac0cc3ec505ee59b51a9f5c9a if [ "$CROSS_BUILD" ]; then # Depend on system ecl From c29a972b6acd85ab16188f64c7b707f0a1e70d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Sun, 19 Apr 2026 22:03:01 -0300 Subject: [PATCH 02/18] ecl: fix abort in mprotect() --- .../patches/first_env_page_alignment.patch | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 srcpkgs/ecl/patches/first_env_page_alignment.patch diff --git a/srcpkgs/ecl/patches/first_env_page_alignment.patch b/srcpkgs/ecl/patches/first_env_page_alignment.patch new file mode 100644 index 00000000000000..ed979328592b40 --- /dev/null +++ b/srcpkgs/ecl/patches/first_env_page_alignment.patch @@ -0,0 +1,24 @@ +ECL 26.3.27 changed the main thread environment from mmap-allocated +(page-aligned) to a static struct first_env. The ECL_USE_MPROTECT fast +interrupt dispatch calls mprotect() on this struct, which requires the +address to be page-aligned. The unaligned static variable causes +mprotect() to fail with EINVAL when a signal arrives while interrupts +are disabled (e.g. inside ecl_cons), crashing with "Unable to mprotect +environment". Align first_env to 65536 bytes (covers 4K/16K/64K pages). +See https://github.com/sagemath/sage/pull/41879 + +diff --git a/src/c/main.d b/src/c/main.d +--- a/src/c/main.d ++++ b/src/c/main.d +@@ -49,7 +49,12 @@ + + const char *ecl_self; +-static struct cl_env_struct first_env; ++/* Align to page boundary: ECL_USE_MPROTECT calls mprotect() on this ++ struct for fast interrupt dispatch, which requires a page-aligned ++ address. Use 65536 to cover all common page sizes (4K/16K/64K). ++ Prior ECL versions allocated this via mmap() which is always ++ page-aligned; this was changed to a static variable in 26.3.27. */ ++static struct cl_env_struct __attribute__((aligned(65536))) first_env; + + /************************ GLOBAL INITIALIZATION ***********************/ From b9c7f62e93312bb341be2cf627abcb8b54f8ae62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 17:52:03 -0300 Subject: [PATCH 03/18] maxima: update to 5.49.0. --- srcpkgs/maxima/template | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/srcpkgs/maxima/template b/srcpkgs/maxima/template index 9259b48f50822b..6044cae7918eaa 100644 --- a/srcpkgs/maxima/template +++ b/srcpkgs/maxima/template @@ -1,10 +1,10 @@ # Template file for 'maxima' pkgname=maxima -version=5.47.0 -revision=4 +version=5.49.0 +revision=1 build_style=gnu-configure -configure_args="$(vopt_enable clisp) $(vopt_enable sbcl) $(vopt_enable ecl) - makeinfo_found=true" +configure_args="$(vopt_enable clisp) $(vopt_enable sbcl) $(vopt_enable ecl)" +hostmakedepends="texinfo" makedepends="$(vopt_if clisp clisp) $(vopt_if sbcl sbcl) $(vopt_if ecl ecl)" depends="$(vopt_if clisp clisp) rlwrap" checkdepends="gnuplot" @@ -14,7 +14,7 @@ license="GPL-2.0-only" homepage="http://maxima.sourceforge.net" changelog="https://sourceforge.net/p/maxima/code/ci/master/tree/changelogs/ChangeLog-${version%.*}.md?format=raw" distfiles="${SOURCEFORGE_SITE}/maxima/maxima-${version}.tar.gz" -checksum=9104021b24fd53e8c03a983509cb42e937a925e8c0c85c335d7709a14fd40f7a +checksum=6d401a4aa307cd3a5a9cadca4fa96c4ef0e24ff95a18bb6a8f803e3d2114adee nocross=yes # maxima-sbcl is nopie and should NOT be stripped or it won't work @@ -43,22 +43,6 @@ esac vopt_conflict clisp sbcl -pre_build() { - # do not rebuild these files if they exist - touch -c doc/info/*.html - touch -c doc/info/maxima.info* - touch -c doc/info/maxima_toc.html - touch -c doc/info/maxima-index.lisp - touch -c doc/info/maxima-index-html.lisp - touch -c interfaces/xmaxima/doc/xmaxima.info - touch -c interfaces/xmaxima/doc/xmaxima.html -} - -post_build() { - # this one needs to be done after building - touch -c interfaces/emacs/imaxima/imaxima.info -} - do_check() { if [ "$build_option_ecl" ]; then echo "maxima-ecl: check that maxima.fas works (#34273)" @@ -80,7 +64,7 @@ do_check() { timeout -v 30s ./maxima-local -q -l sbcl --batch-string=" showtime : true $ a : 10^(10^5) $ - b : a^1000 $ + b : a^600 $ " echo PASS fi From 005b09a5974e300faa1f77aa3bfebda201808f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 20:27:36 -0300 Subject: [PATCH 04/18] sagemath: patch for maxima 5.49.0 --- .../patches/40679-Update_to_maxima_5.49.patch | 615 ++++++++++++++++++ .../patches/fix-doctest-maxima-5.49.patch | 11 + srcpkgs/sagemath/patches/get_patches | 1 + srcpkgs/sagemath/template | 2 +- 4 files changed, 628 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch create mode 100644 srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch diff --git a/srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch b/srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch new file mode 100644 index 00000000000000..cd7e96ee47c0ae --- /dev/null +++ b/srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch @@ -0,0 +1,615 @@ +diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py +index 270e3c49058..0f64e09e18b 100644 +--- a/src/sage/calculus/calculus.py ++++ b/src/sage/calculus/calculus.py +@@ -133,8 +133,8 @@ + [x^2 + x 2*x^3] + [ 2 x^2 + x] + sage: e^M +- [ 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x)) 1/2*(x*e^(2*sqrt(x)) - x)*sqrt(x)*e^(x - sqrt(x))] +- [ 1/2*(e^(2*sqrt(x)) - 1)*e^(x - sqrt(x))/x^(3/2) 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x))] ++ [ 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x)) 1/2*x^(3/2)*(e^(2*sqrt(x)) - 1)*e^(x - sqrt(x))] ++ [1/2*(e^(2*sqrt(x)) - 1)*e^(x - sqrt(x))/x^(3/2) 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x))] + + Complex exponentiation works, but may require a patched version of + maxima (:issue:`32898`) for now:: +@@ -1247,7 +1247,7 @@ def limit(ex, *args, dir=None, taylor=False, algorithm='maxima', **kwargs): + + sage: limit(sin(x)/x, x, 0, algorithm='sympy') + 1 +- sage: limit(sin(x)/x, x, 0, algorithm='giac') # needs sage.libs.giac ++ sage: limit(sin(x)/x, x, 0, algorithm='giac') # needs sage.libs.giac + 1 + sage: limit(x^x, x, 0, dir='+', algorithm='fricas') # optional - fricas + 1 +diff --git a/src/sage/calculus/test_sympy.py b/src/sage/calculus/test_sympy.py +index aa084799a10..e081e9674d9 100644 +--- a/src/sage/calculus/test_sympy.py ++++ b/src/sage/calculus/test_sympy.py +@@ -63,7 +63,7 @@ + sage: diff(tan(x), x) + tan(x)^2 + 1 + sage: limit((tan(x+y) - tan(x))/y, y=0) +- cos(x)^(-2) ++ tan(x)^2 + 1 + sage: diff(sin(2*x), x, 1) + 2*cos(2*x) + sage: diff(sin(2*x), x, 2) +diff --git a/src/sage/calculus/tests.py b/src/sage/calculus/tests.py +index 2879dda115d..abdbbad932e 100644 +--- a/src/sage/calculus/tests.py ++++ b/src/sage/calculus/tests.py +@@ -119,7 +119,7 @@ + sage: integrate(exp(1-x^2),x) + 1/2*sqrt(pi)*erf(x)*e + sage: integrate(sin(x^2),x) +- 1/16*sqrt(pi)*((I + 1)*sqrt(2)*erf((1/2*I + 1/2)*sqrt(2)*x) + (I - 1)*sqrt(2)*erf((1/2*I - 1/2)*sqrt(2)*x) - (I - 1)*sqrt(2)*erf(sqrt(-I)*x) + (I + 1)*sqrt(2)*erf((-1)^(1/4)*x)) ++ 1/16*sqrt(pi)*((I + 1)*sqrt(2)*erf((1/2*I + 1/2)*sqrt(2)*x) - (I - 1)*sqrt(2)*erf(sqrt(-I)*x) - 2*sqrt(2)*imag_part(erf((-1)^(1/4)*x)) + 2*sqrt(2)*real_part(erf((-1)^(1/4)*x))) + + sage: integrate((1-x^2)^n,x) # long time + x*hypergeometric((1/2, -n), (3/2,), x^2*exp_polar(2*I*pi)) +diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py +index db32eebe381..056bceaf49c 100644 +--- a/src/sage/functions/bessel.py ++++ b/src/sage/functions/bessel.py +@@ -1864,7 +1864,7 @@ class SphericalHankel1(BuiltinFunction): + sage: spherical_hankel1(3 + 0.2 * I, 3) + 0.201654587512037 - 0.531281544239273*I + sage: spherical_hankel1(1, x).simplify() +- -(x + I)*e^(I*x)/x^2 ++ -I*(-I*x + 1)*e^(I*x)/x^2 + sage: spherical_hankel1(3 + 2 * I, 5 - 0.2 * I) + 1.25375216869913 - 0.518011435921789*I + sage: integrate(spherical_hankel1(3, x), x) +@@ -1962,11 +1962,11 @@ class SphericalHankel2(BuiltinFunction): + sage: spherical_hankel2(3 + 0.2 * I, 3) + 0.0998874108557565 + 0.479149050937147*I + sage: spherical_hankel2(1, x).simplify() +- -(x - I)*e^(-I*x)/x^2 ++ I*(I*x + 1)*e^(-I*x)/x^2 + sage: spherical_hankel2(2,i).simplify() + -e + sage: spherical_hankel2(2,x).simplify() +- (-I*x^2 - 3*x + 3*I)*e^(-I*x)/x^3 ++ -I*(x^2 - 3*I*x - 3)*e^(-I*x)/x^3 + sage: spherical_hankel2(3 + 2*I, 5 - 0.2*I) + 0.0217627632692163 + 0.0224001906110906*I + sage: integrate(spherical_hankel2(3, x), x) +diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py +index 154a2cc34e0..1eebc46e03a 100644 +--- a/src/sage/interfaces/maxima.py ++++ b/src/sage/interfaces/maxima.py +@@ -194,7 +194,7 @@ + You can even nicely typeset the solution in latex:: + + sage: latex(s) +- \left[ \left[ a=-...{{\sqrt{79}\,i-11}\over{4}}... , b={{...\sqrt{79}\,i+9...}\over{4}} , c={{\sqrt{79}\,i+1}\over{10}} \right] , \left[ a={{...\sqrt{79}\,i+11}\over{4}} , b=-...{{\sqrt{79}\,i-9...}\over{4}}... , c=-...{{...\sqrt{79}\,i-1}\over{10}}... \right] \right] ++ \left[ \left[ a=-\left({{\sqrt{79}\,i-11}\over{4}}\right) , b={{\sqrt{79}\,i +9}\over{4}} , c={{\sqrt{79}\,i+1}\over{10}} \right] , \left[ a={{\sqrt{79} \,i+11}\over{4}} , b=-\left({{\sqrt{79}\,i-9}\over{4}}\right) , c=-\left({{ \sqrt{79}\,i-1}\over{10}}\right) \right] \right] + + To have the above appear onscreen via ``xdvi``, type + ``view(s)``. (TODO: For OS X should create pdf output +@@ -216,11 +216,11 @@ + :: + + sage: f = maxima('x^3 * %e^(k*x) * sin(w*x)'); f +- x^3*%e^(k*x)*sin(w*x) ++ %e^(k*x)*x^3*sin(w*x) + sage: f.diff('x') +- k*x^3*%e^(k*x)*sin(w*x)+3*x^2*%e^(k*x)*sin(w*x)+w*x^3*%e^(k*x) *cos(w*x) ++ %e^(k*x)*k*x^3*sin(w*x)+3*%e^(k*x)*x^2*sin(w*x)+%e^(k*x)*w*x^3 *cos(w*x) + sage: f.integrate('x') +- (((k*w^6+3*k^3*w^4+3*k^5*w^2+k^7)*x^3 +(3*w^6+3*k^2*w^4-3*k^4*w^2-3*k^6)*x^2+(...-...18*k*w^4)-12*k^3*w^2+6*k^5)*x-6*w^4 +36*k^2*w^2-6*k^4) *%e^(k*x)*sin(w*x) +((...-w^7...-3*k^2*w^5-3*k^4*w^3-k^6*w)*x^3...+(6*k*w^5+12*k^3*w^3+6*k^5*w)*x^2...+(6*w^5-12*k^2*w^3-18*k^4*w)*x-24*k*w^3 +24*k^3*w) *%e^(k*x)*cos(w*x)) /(w^8+4*k^2*w^6+6*k^4*w^4+4*k^6*w^2+k^8) ++ (((%e^(k*x)*k*w^6+3*%e^(k*x)*k^3*w^4+3*%e^(k*x)*k^5*w^2+%e^(k*x)*k^7)*x ^3 +(3*%e^(k*x)*w^6+3*%e^(k*x)*k^2*w^4-3*%e^(k*x)*k^4*w^2-3*%e^(k*x)*k^6)*x^2 +(-(18*%e^(k*x)*k*w^4)-12*%e^(k*x)*k^3*w^2+6*%e^(k*x)*k^5)*x-6*%e^(k*x)*w^4 +36*%e^(k*x)*k^2*w^2-6*%e^(k*x)*k^4) *sin(w*x) +((-(%e^(k*x)*w^7)-3*%e^(k*x)*k^2*w^5-3*%e^(k*x)*k^4*w^3-%e^(k*x)*k^6*w)*x^3 +(6*%e^(k*x)*k*w^5+12*%e^(k*x)*k^3*w^3+6*%e^(k*x)*k^5*w)*x^2 +(6*%e^(k*x)*w^5-12*%e^(k*x)*k^2*w^3-18*%e^(k*x)*k^4*w)*x-24*%e^(k*x)*k*w^3 +24*%e^(k*x)*k^3*w) *cos(w*x)) /(w^8+4*k^2*w^6+6*k^4*w^4+4*k^6*w^2+k^8) + + :: + +@@ -291,13 +291,14 @@ + + sage: _ = maxima.eval("f(t) := t^5*exp(t)*sin(t)") + sage: maxima("laplace(f(t),t,s)") +- (360*(2*s-2))/(s^2-2*s+2)^4-(480*(2*s-2)^3)/(s^2-2*s+2)^5 +(120*(2*s-2)^5)/(s^2-2*s+2)^6 ++ (720*s^5-3600*s^4+4800*s^3-2880*s+960) /(s^12-12*s^11+72*s^10-280*s^9+780*s^8-1632*s^7+2624*s^6-3264*s^5+3120*s^4 -2240*s^3+1152*s^2-384*s+64) + sage: print(maxima("laplace(f(t),t,s)")) +- 3 5 +- 360 (2 s - 2) 480 (2 s - 2) 120 (2 s - 2) +- --------------- - --------------- + --------------- +- 2 4 2 5 2 6 +- (s - 2 s + 2) (s - 2 s + 2) (s - 2 s + 2) ++ 5 4 3 ++ (720 s - 3600 s + 4800 s - 2880 s + 960) ++ 12 11 10 9 8 7 6 5 ++ /(s - 12 s + 72 s - 280 s + 780 s - 1632 s + 2624 s - 3264 s ++ 4 3 2 ++ + 3120 s - 2240 s + 1152 s - 384 s + 64) + + :: + +@@ -363,11 +364,11 @@ + + sage: S = maxima('nusum(exp(1+2*i/n),i,1,n)') + sage: print(S) +- 2/n + 3 2/n + 1 +- %e %e +- ----------------------- - ----------------------- +- 1/n 1/n 1/n 1/n +- (%e - 1) (%e + 1) (%e - 1) (%e + 1) ++ 2/n + 3 2/n + 1 ++ %e %e ++ ─────────────────────── - ─────────────────────── ++ 1/n 1/n 1/n 1/n ++ (%e - 1) (%e + 1) (%e - 1) (%e + 1) + + We formally compute the limit as `n\to\infty` of + `2S/n` as follows:: +@@ -418,7 +419,7 @@ + sage: from sage.interfaces.maxima import maxima + sage: g = maxima('exp(3*%i*x)/(6*%i) + exp(%i*x)/(2*%i) + c') + sage: latex(g) +- -...{{i\,e^{3\,i\,x}}\over{6}}...-{{i\,e^{i\,x}}\over{2}}+c ++ c-{{e^{3\,i\,x}\,i}\over{6}}-{{e^{i\,x}\,i}\over{2}} + + Long Input + ---------- +diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py +index 5866b955bb0..e7c1da2a277 100644 +--- a/src/sage/interfaces/maxima_abstract.py ++++ b/src/sage/interfaces/maxima_abstract.py +@@ -866,11 +866,11 @@ def de_solve(self, de, vars, ics=None): + sage: maxima.de_solve('diff(y,x,2) + 3*x = y', ['x','y'], [1,1,1]) + y = 3*x-2*%e^(x-1) + sage: maxima.de_solve('diff(y,x,2) + 3*x = y', ['x','y']) +- y = %k1*%e^x+%k2*%e^-x+3*x ++ y = 3*x+%e^-x*%k2+%e^x*%k1 + sage: maxima.de_solve('diff(y,x) + 3*x = y', ['x','y']) +- y = (%c-3*(...-x...-1)*%e^-x)*%e^x ++ y = %e^x*(%c-3*%e^-x*(-x-1)) + sage: maxima.de_solve('diff(y,x) + 3*x = y', ['x','y'],[1,1]) +- y = -...%e^-1*(5*%e^x-3*%e*x-3*%e)... ++ y = %e^-1*(3*%e*x-5*%e^x+3*%e) + """ + if not isinstance(vars, str): + str_vars = '%s, %s' % (vars[1], vars[0]) +@@ -910,20 +910,20 @@ def de_solve_laplace(self, de, vars, ics=None): + sage: from sage.interfaces.maxima_lib import maxima + sage: maxima.clear('x'); maxima.clear('f') + sage: maxima.de_solve_laplace("diff(f(x),x,2) = 2*diff(f(x),x)-f(x)", ["x","f"], [0,1,2]) +- f(x) = x*%e^x+%e^x ++ f(x) = %e^x*x+%e^x + + :: + + sage: maxima.clear('x'); maxima.clear('f') + sage: f = maxima.de_solve_laplace("diff(f(x),x,2) = 2*diff(f(x),x)-f(x)", ["x","f"]) + sage: f +- f(x) = x*%e^x*('at('diff(f(x),x,1),x = 0))-f(0)*x*%e^x+f(0)*%e^x ++ f(x) = %e^x*x*('at('diff(f(x),x,1),x = 0))-%e^x*f(0)*x+%e^x*f(0) + sage: print(f) +- ! +- x d ! x x +- f(x) = x %e (-- (f(x))! ) - f(0) x %e + f(0) %e +- dx ! +- !x = 0 ++ │ ++ x d │ x x ++ f(x) = %e x (── (f(x))│ ) - %e f(0) x + %e f(0) ++ dx │ ++ │x = 0 + + .. NOTE:: + +@@ -1136,10 +1136,10 @@ def __str__(self): + sage: f = maxima('1/(x-1)^3'); f + 1/(x-1)^3 + sage: print(f) +- 1 +- -------- +- 3 +- (x - 1) ++ 1 ++ ──────── ++ 3 ++ (x - 1) + """ + return self.display2d(onscreen=False) + +@@ -1798,9 +1798,9 @@ def _latex_(self): + sage: y,d = var('y,d') + sage: f = function('f') + sage: latex(maxima(derivative(f(x*y), x))) +- \left(\left.{{{\it \partial}}\over{{\it \partial}\, {\it \_symbol}_{0}}}\,f\left( {\it \_symbol}_{0}\right)\right|_{ {\it \_symbol}_{0}={\it x}\, {\it y}}\right)\,{\it y} ++ \left(\left.{{{\it \partial}}\over{{\it \partial}\, {\it \_symbol}_{0}}}\,f\left({\it \_symbol}_{0} \right)\right|_{{\it \_symbol}_{0}={\it x}\, {\it y}}\right)\,{\it y} + sage: latex(maxima(derivative(f(x,y,d), d,x,x,y))) +- {{{\it \partial}^4}\over{{\it \partial}\,{\it d}\, {\it \partial}\,{\it x}^2\,{\it \partial}\, {\it y}}}\,f\left({\it x} , {\it y} , {\it d}\right) ++ {{{\it \partial}^4}\over{{\it \partial}\,{\it d}\, {\it \partial}\,{\it x}^2\,{\it \partial}\,{\it y} }}\,f\left({\it x} , {\it y} , {\it d} \right) + sage: latex(maxima(d/(d-2))) + {{{\it d}}\over{{\it d}-2}} + """ +@@ -1929,9 +1929,9 @@ def partial_fraction_decomposition(self, var='x'): + sage: f.partial_fraction_decomposition('x') + 1/(2*(x-1))-1/(2*(x+1)) + sage: print(f.partial_fraction_decomposition('x')) +- 1 1 +- --------- - --------- +- 2 (x - 1) 2 (x + 1) ++ 1 1 ++ ───────── - ───────── ++ 2 (x - 1) 2 (x + 1) + """ + return self.partfrac(var) + +diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py +index 637ef29a6f2..fff2a6ee39c 100644 +--- a/src/sage/interfaces/maxima_lib.py ++++ b/src/sage/interfaces/maxima_lib.py +@@ -164,7 +164,7 @@ + ecl_eval("(setq $nolabels t))") + ecl_eval("(defun add-lineinfo (x) x)") + ecl_eval(r"(defun tex-derivative (x l r) (tex (if $derivabbrev (tex-dabbrev x) (tex-d x '\\partial)) l r lop rop ))") +-ecl_eval('(defun principal nil (cond ($noprincipal (diverg)) ((not pcprntd) (merror "Divergent Integral"))))') ++ecl_eval('(defun principal nil (cond ($noprincipal (diverg)) ((not *pcprntd*) (merror "Divergent Integral"))))') + ecl_eval("(remprop 'mfactorial 'grind)") # don't use ! for factorials (#11539) + ecl_eval("(setf $errormsg nil)") + +@@ -1224,6 +1224,8 @@ def reduce_load_MaximaLib(): + sage.functions.error.erf: "%ERF", + sage.functions.gamma.gamma_inc: "%GAMMA_INCOMPLETE", + sage.functions.other.conjugate: "$CONJUGATE", ++ sage.functions.other.imag_part: "%IMAGPART", ++ sage.functions.other.real_part: "%REALPART", + } + # we compile the dictionary + sage_op_dict = {k: EclObject(sage_op_dict[k]) for k in sage_op_dict} +diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py +index 7232f0c4ddb..1240fe5ad83 100644 +--- a/src/sage/manifolds/chart.py ++++ b/src/sage/manifolds/chart.py +@@ -3761,7 +3761,7 @@ def set_inverse(self, *transformations, **kwds): + sage: spher_to_cart.set_inverse(sqrt(x^2+y^2), atan2(y,x)) + Check of the inverse coordinate transformation: + r == r *passed* +- ph == arctan2(r*sin(ph), r*cos(ph)) **failed** ++ ph == -2*pi*ceil(-1/2*(pi - ph)/pi) + ph **failed** + x == x *passed* + y == y *passed* + NB: a failed report can reflect a mere lack of simplification. +@@ -3798,8 +3798,8 @@ def set_inverse(self, *transformations, **kwds): + + sage: spher_to_cart.set_inverse(sqrt(x^3+y^2), atan2(y,x)) + Check of the inverse coordinate transformation: +- r == sqrt(r*cos(ph)^3 + sin(ph)^2)*r **failed** +- ph == arctan2(r*sin(ph), r*cos(ph)) **failed** ++ r == r*sqrt(abs(r*cos(ph)^3 + sin(ph)^2)) **failed** ++ ph == -2*pi*ceil(-1/2*(pi - ph)/pi) + ph **failed** + x == sqrt(x^3 + y^2)*x/sqrt(x^2 + y^2) **failed** + y == sqrt(x^3 + y^2)*y/sqrt(x^2 + y^2) **failed** + NB: a failed report can reflect a mere lack of simplification. +diff --git a/src/sage/manifolds/continuous_map.py b/src/sage/manifolds/continuous_map.py +index e673f0ced6d..bd9db2f3e2b 100644 +--- a/src/sage/manifolds/continuous_map.py ++++ b/src/sage/manifolds/continuous_map.py +@@ -1578,7 +1578,7 @@ def expr(self, chart1=None, chart2=None): + sage: ch_spher_cart.set_inverse(sqrt(x^2+y^2), atan2(y,x)) + Check of the inverse coordinate transformation: + r == r *passed* +- ph == arctan2(r*sin(ph), r*cos(ph)) **failed** ++ ph == -2*pi*ceil(-1/2*(pi - ph)/pi) + ph **failed** + x == x *passed* + y == y *passed* + NB: a failed report can reflect a mere lack of simplification. +@@ -1627,7 +1627,7 @@ def set_expr(self, chart1, chart2, coord_functions): + x == x *passed* + y == y *passed* + r == r *passed* +- ph == arctan2(r*sin(ph), r*cos(ph)) **failed** ++ ph == -2*pi*ceil(-1/2*(pi - ph)/pi) + ph **failed** + NB: a failed report can reflect a mere lack of simplification. + sage: rot = U.continuous_map(U, ((x - sqrt(3)*y)/2, (sqrt(3)*x + y)/2), + ....: name='R') +@@ -1681,7 +1681,7 @@ def set_expr(self, chart1, chart2, coord_functions): + x == x *passed* + y == y *passed* + r == r *passed* +- ph == arctan2(r*sin(ph), r*cos(ph)) **failed** ++ ph == -2*pi*ceil(-1/2*(pi - ph)/pi) + ph **failed** + NB: a failed report can reflect a mere lack of simplification. + sage: rot = U.continuous_map(U, ((x - sqrt(3)*y)/2, (sqrt(3)*x + y)/2), + ....: name='R') +@@ -1770,7 +1770,7 @@ def add_expr(self, chart1, chart2, coord_functions): + x == x *passed* + y == y *passed* + r == r *passed* +- ph == arctan2(r*sin(ph), r*cos(ph)) **failed** ++ ph == -2*pi*ceil(-1/2*(pi - ph)/pi) + ph **failed** + NB: a failed report can reflect a mere lack of simplification. + sage: rot = U.continuous_map(U, ((x - sqrt(3)*y)/2, (sqrt(3)*x + y)/2), + ....: name='R') +@@ -1784,7 +1784,7 @@ def add_expr(self, chart1, chart2, coord_functions): + + sage: rot.display(c_spher, c_spher) + R: U → U +- (r, ph) ↦ (r, arctan2(1/2*(sqrt(3)*cos(ph) + sin(ph))*r, -1/2*(sqrt(3)*sin(ph) - cos(ph))*r)) ++ (r, ph) ↦ (r, arctan2(1/2*sqrt(3)*cos(ph) + 1/2*sin(ph), -1/2*sqrt(3)*sin(ph) + 1/2*cos(ph))) + + Therefore, we use the method :meth:`add_expr` to set the + spherical-coordinate expression by hand:: +diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py +index 45a2fad087a..11a548a0317 100644 +--- a/src/sage/manifolds/differentiable/automorphismfield_group.py ++++ b/src/sage/manifolds/differentiable/automorphismfield_group.py +@@ -535,8 +535,7 @@ class AutomorphismFieldParalGroup(FreeModuleLinearGroup): + Field of tangent-space automorphisms t^(-1) on the 2-dimensional + differentiable manifold M + sage: (t1^(-1)).display() +- t^(-1) = 1/(e^y + 1) ∂/∂x⊗dx - x*y/(x^2 + (x^2 + 1)*e^y + 1) ∂/∂x⊗dy +- + 1/(x^2 + 1) ∂/∂y⊗dy ++ t^(-1) = 1/(e^y + 1) ∂/∂x⊗dx - x*y/(x^2*(e^y + 1) + e^y + 1) ∂/∂x⊗dy + 1/(x^2 + 1) ∂/∂y⊗dy + + Since any automorphism field can be considered as a tensor field of + type-`(1,1)` on ``M``, there is a coercion map from ``G`` to the +diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py +index 8a1cfc2e77e..9c1d518acc3 100644 +--- a/src/sage/manifolds/differentiable/curve.py ++++ b/src/sage/manifolds/differentiable/curve.py +@@ -466,7 +466,7 @@ def coord_expr(self, chart=None): + x == x *passed* + y == y *passed* + r == r *passed* +- ph == arctan2(r*sin(ph), r*cos(ph)) **failed** ++ ph == -2*pi*ceil(-1/2*(pi - ph)/pi) + ph **failed** + NB: a failed report can reflect a mere lack of simplification. + sage: R. = manifolds.RealLine() + sage: c = U.curve({c_spher: (1,t)}, (t, 0, 2*pi), name='c') +diff --git a/src/sage/manifolds/differentiable/metric.py b/src/sage/manifolds/differentiable/metric.py +index 01b48ef9724..43758ba7e73 100644 +--- a/src/sage/manifolds/differentiable/metric.py ++++ b/src/sage/manifolds/differentiable/metric.py +@@ -1556,9 +1556,9 @@ def sqrt_abs_det(self, frame=None): + [ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2 1/4*u] + [ 1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2] + sage: g.sqrt_abs_det(Y.frame()).expr() +- 1/2*sqrt(-x^2*y^2 - (x + 1)*y + x + 1) ++ 1/2*sqrt(abs(x^2*y^2 + (x + 1)*y - x - 1)) + sage: g.sqrt_abs_det(Y.frame()).expr(Y) +- 1/8*sqrt(-u^4 - v^4 + 2*(u^2 + 2)*v^2 - 4*u^2 + 16*v + 16) ++ 1/8*sqrt(abs(u^4 + v^4 - 2*(u^2 + 2)*v^2 + 4*u^2 - 16*v - 16)) + + A chart can be passed instead of a frame:: + +@@ -1578,9 +1578,9 @@ def sqrt_abs_det(self, frame=None): + sage: g.sqrt_abs_det().expr() + sqrt(-x**2*y**2 - x*y + x - y + 1) + sage: g.sqrt_abs_det(Y.frame()).expr() +- sqrt(-x**2*y**2 - x*y + x - y + 1)/2 ++ sqrt(Abs(x**2*y**2 + x*y - x + y - 1))/2 + sage: g.sqrt_abs_det(Y.frame()).expr(Y) +- sqrt(-u**4 + 2*u**2*v**2 - 4*u**2 - v**4 + 4*v**2 + 16*v + 16)/8 ++ sqrt(Abs(-u**4 + 2*u**2*v**2 - 4*u**2 - v**4 + 4*v**2 + 16*v + 16))/8 + """ + dom = self._domain + if frame is None: +diff --git a/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py b/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +index 57dc1c99862..e7c7aaebeea 100644 +--- a/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py ++++ b/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +@@ -819,8 +819,7 @@ def normal(self): + ....: atan2(-y,-x)+pi) + Check of the inverse coordinate transformation: + the == 2*arctan(sqrt(-cos(the) + 1)/sqrt(cos(the) + 1)) **failed** +- phi == pi + arctan2(sin(phi)*sin(the)/(cos(the) - 1), +- cos(phi)*sin(the)/(cos(the) - 1)) **failed** ++ phi == pi + arctan2(cos(the)*sin(phi) - sin(phi), cos(phi)*cos(the) - cos(phi)) **failed** + x == x *passed* + y == y *passed* + NB: a failed report can reflect a mere lack of simplification. +diff --git a/src/sage/manifolds/utilities.py b/src/sage/manifolds/utilities.py +index b1eed3b8b2e..57b35bef6cc 100644 +--- a/src/sage/manifolds/utilities.py ++++ b/src/sage/manifolds/utilities.py +@@ -225,10 +225,10 @@ class SimplifyAbsTrig(ExpressionTreeWalker): + sage: a = abs(cos(x)) + abs(sin(x)) + + The method :meth:`~sage.symbolic.expression.Expression.simplify_full()` +- is ineffective on such an expression:: ++ works on such an expression:: + + sage: a.simplify_full() +- abs(cos(x)) + abs(sin(x)) ++ -cos(x) + sin(x) + + We construct a :class:`SimplifyAbsTrig` object ``s`` from the symbolic + expression ``a``:: +@@ -436,9 +436,9 @@ def simplify_abs_trig(expr): + + sage: s = abs(sin(x)) + abs(sin(y)) + abs(sin(3*z)) + sage: s.simplify_trig() +- abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y)) ++ -4*sin(-z)^3 + abs(sin(x)) + sin(y) + 3*sin(-z) + sage: s.simplify_full() +- abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y)) ++ -4*sin(-z)^3 + abs(sin(x)) + sin(y) + 3*sin(-z) + + despite the following assumptions hold:: + +@@ -571,10 +571,10 @@ def simplify_chain_real(expr): + sage: s = abs(sin(pi*x)) + sage: simplify_chain_real(s) # correct output since x in (0,1) + sin(pi*x) +- sage: s.simplify_real() # unsimplified output +- abs(sin(pi*x)) +- sage: s.simplify_full() # unsimplified output +- abs(sin(pi*x)) ++ sage: s.simplify_real() # simplified output with maxima>=5.48 ++ sin(pi*x) ++ sage: s.simplify_full() # simplified output with maxima>=5.48 ++ sin(pi*x) + + :: + +diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx +index 7ff5a3a95bc..6c057a23bbe 100644 +--- a/src/sage/matrix/matrix2.pyx ++++ b/src/sage/matrix/matrix2.pyx +@@ -16669,8 +16669,8 @@ cdef class Matrix(Matrix1): + sage: # needs sage.symbolic + sage: a = matrix([[1,2], [3,4]]) + sage: a.exp() +- [-1/22*((sqrt(33) - 11)*e^sqrt(33) - sqrt(33) - 11)*e^(-1/2*sqrt(33) + 5/2) 2/33*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2)] +- [ 1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) 1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)] ++ [ 1/22*((sqrt(33) + 11)*e^2 - (sqrt(33) - 11)*e^(sqrt(33) + 2))*e^(-1/2*sqrt(33) + 1/2) -2/33*(sqrt(33)*e^2 - sqrt(33)*e^(sqrt(33) + 2))*e^(-1/2*sqrt(33) + 1/2)] ++ [ -1/11*(sqrt(33)*e^2 - sqrt(33)*e^(sqrt(33) + 2))*e^(-1/2*sqrt(33) + 1/2) -1/22*((sqrt(33) - 11)*e^2 - (sqrt(33) + 11)*e^(sqrt(33) + 2))*e^(-1/2*sqrt(33) + 1/2)] + + sage: type(a.exp()) # needs sage.symbolic + +diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py +index 65a35b45a53..74ecc2198a6 100644 +--- a/src/sage/misc/functional.py ++++ b/src/sage/misc/functional.py +@@ -721,9 +721,7 @@ def integral(x, *args, **kwds): + real + sage: f = exp(-x) * sinh(sqrt(x)) + sage: t = integrate(f, x, 0, Infinity); t # long time +- 1/4*sqrt(pi)*(erf(1) - 1)*e^(1/4) +- - 1/4*(sqrt(pi)*(erf(1) - 1) - sqrt(pi) + 2*e^(-1) - 2)*e^(1/4) +- + 1/4*sqrt(pi)*e^(1/4) - 1/2*e^(1/4) + 1/2*e^(-3/4) ++ 1/2*sqrt(pi)*e^(1/4) + sage: t.canonicalize_radical() # long time + 1/2*sqrt(pi)*e^(1/4) + sage: sage.calculus.calculus.maxima('domain: complex') +@@ -932,7 +930,7 @@ def krull_dimension(x): + 0 + sage: ZZ.krull_dimension() + 1 +- sage: ZZ[sqrt(5)].krull_dimension() # needs sage.rings.number_field sage.symbolic ++ sage: ZZ[sqrt(5)].krull_dimension() # needs sage.rings.number_field sage.symbolic + 1 + sage: U. = PolynomialRing(ZZ, 3); U + Multivariate Polynomial Ring in x, y, z over Integer Ring +diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx +index 691acf2c947..07b191522c9 100644 +--- a/src/sage/symbolic/expression.pyx ++++ b/src/sage/symbolic/expression.pyx +@@ -13019,21 +13019,21 @@ cdef class Expression(Expression_abc): + Check that the sum in :issue:`10682` is done right:: + + sage: sum(binomial(n,k)*k^2, k, 2, n) +- 1/4*(n^2 + n)*2^n - n ++ 1/4*2^n*n^2 + 1/4*(2^n - 4)*n + + This sum used to give a wrong result (:issue:`9635`) but + now gives correct results with all relevant assumptions:: + + sage: (n,k,j)=var('n,k,j') + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) +- -(-1)^j*sum((-1)^k*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) ++ -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) + sage: assume(j>-1) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) + 1 + sage: forget() + sage: assume(n>=j) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) +- -(-1)^j*sum((-1)^k*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) ++ -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) + sage: forget() + sage: assume(j==-1) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) +@@ -13041,7 +13041,7 @@ cdef class Expression(Expression_abc): + sage: forget() + sage: assume(j<-1) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) +- -(-1)^j*sum((-1)^k*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) ++ -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) + sage: forget() + + Check that :issue:`16176` is fixed:: +diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py +index c99676c0b88..105e8e3bbbd 100644 +--- a/src/sage/symbolic/integration/external.py ++++ b/src/sage/symbolic/integration/external.py +@@ -31,12 +31,7 @@ def maxima_integrator(expression, v, a=None, b=None): + Check that :issue:`25817` is fixed:: + + sage: maxima_integrator(log(e^x*log(x)*sin(x))/x^2, x) +- 1/2*(x*(Ei(-log(x)) + conjugate(Ei(-log(x)))) +- - 2*x*integrate(sin(x)/(x*cos(x)^2 + x*sin(x)^2 +- + 2*x*cos(x) + x), x) + 2*x*integrate(sin(x)/(x*cos(x)^2 +- + x*sin(x)^2 - 2*x*cos(x) + x), x) + 2*x*log(x) + 2*log(2) +- - log(cos(x)^2 + sin(x)^2 + 2*cos(x) + 1) - log(cos(x)^2 +- + sin(x)^2 - 2*cos(x) + 1) - 2*log(log(x)))/x ++ -1/2*(2*x*integrate(sin(x)/(x*cos(x)^2 + x*sin(x)^2 + 2*x*cos(x) + x), x) - 2*x*integrate(sin(x)/(x*cos(x)^2 + x*sin(x)^2 - 2*x*cos(x) + x), x) - 2*x*log(x) - 2*x*real_part(Ei(-log(x))) - 2*log(2) + log(cos(x)^2 + sin(x)^2 + 2*cos(x) + 1) + log(cos(x)^2 + sin(x)^2 - 2*cos(x) + 1) + 2*log(log(x)))/x + """ + from sage.calculus.calculus import maxima + if not isinstance(expression, Expression): +diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py +index b3d1dd1c2bf..1002343e884 100644 +--- a/src/sage/symbolic/integration/integral.py ++++ b/src/sage/symbolic/integration/integral.py +@@ -614,10 +614,7 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): + x y + Sqrt[--] FresnelS[Sqrt[--] x] + 2 Pi + sage: print(f.integral(x)) +- x*y^z + 1/16*sqrt(pi)*((I + 1)*sqrt(2)*erf((1/2*I + 1/2)*sqrt(2)*x) +- + (I - 1)*sqrt(2)*erf((1/2*I - 1/2)*sqrt(2)*x) +- - (I - 1)*sqrt(2)*erf(sqrt(-I)*x) +- + (I + 1)*sqrt(2)*erf((-1)^(1/4)*x)) ++ x*y^z + 1/16*sqrt(pi)*((I + 1)*sqrt(2)*erf((1/2*I + 1/2)*sqrt(2)*x) - (I - 1)*sqrt(2)*erf(sqrt(-I)*x) - 2*sqrt(2)*imag_part(erf((-1)^(1/4)*x)) + 2*sqrt(2)*real_part(erf((-1)^(1/4)*x))) + + Alternatively, just use algorithm='mathematica_free' to integrate via Mathematica + over the internet (does NOT require a Mathematica license!):: +@@ -1011,8 +1008,8 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): + sage: f = log(sin(x))*sin(x)^2 + sage: g = integrate(f, x) ; g + 1/4*I*x^2 ++ - 1/2*I*x*arctan2(-sin(x), -cos(x) + 1) + - 1/2*I*x*arctan2(sin(x), cos(x) + 1) +- + 1/2*I*x*arctan2(sin(x), -cos(x) + 1) + - 1/4*x*log(cos(x)^2 + sin(x)^2 + 2*cos(x) + 1) + - 1/4*x*log(cos(x)^2 + sin(x)^2 - 2*cos(x) + 1) + + 1/4*(2*x - sin(2*x))*log(sin(x)) +@@ -1036,7 +1033,7 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): + sage: assume(a > 0) + sage: assume(a < 1) + sage: integrate(x*log(1/(a*x+(1-x)^2)), x, 0, 1, algorithm='maxima') +- 1/4*a^2*log(a) + 1/2*sqrt(-a^2 + 4*a)*a*arctan(sqrt(-a^2 + 4*a)*(a - 2)/(a^2 - 4*a)) - 1/2*sqrt(-a^2 + 4*a)*a*arctan(sqrt(-a^2 + 4*a)/(a - 4)) - a*log(a) - sqrt(-a^2 + 4*a)*arctan(sqrt(-a^2 + 4*a)*(a - 2)/(a^2 - 4*a)) + sqrt(-a^2 + 4*a)*arctan(sqrt(-a^2 + 4*a)/(a - 4)) - 1/2*a + 3/2 ++ 1/4*a^2*log(a) - 1/2*sqrt(-a^2 + 4*a)*a*arctan(sqrt(-a^2 + 4*a)/(a - 4)) + 1/2*sqrt(-a^2 + 4*a)*a*arctan(sqrt(-a^2 + 4*a)*(a - 2)/((a - 4)*a)) - a*log(a) + sqrt(-a^2 + 4*a)*arctan(sqrt(-a^2 + 4*a)/(a - 4)) - sqrt(-a^2 + 4*a)*arctan(sqrt(-a^2 + 4*a)*(a - 2)/((a - 4)*a)) - 1/2*a + 3/2 + + Check that :issue:`25905` is fixed:: + +diff --git a/src/sage/symbolic/relation.py b/src/sage/symbolic/relation.py +index 8fada2b4e9b..02cfc43f282 100644 +--- a/src/sage/symbolic/relation.py ++++ b/src/sage/symbolic/relation.py +@@ -1338,20 +1338,6 @@ def _solve_expression(f, x, explicit_solutions, multiplicities, + sage: (x^2>1).solve(x) + [[x < -1], [x > 1]] + +- Catch error message from Maxima:: +- +- sage: solve(acot(x),x) +- Traceback (most recent call last): +- ... +- TypeError: ECL says: cot: argument 0 isn't in the domain of cot. +- +- :: +- +- sage: solve(acot(x),x,to_poly_solve=True) +- Traceback (most recent call last): +- ... +- TypeError: ECL says: cot: argument 0 isn't in the domain of cot. +- + :issue:`7491` fixed:: + + sage: y = var('y') +diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py +index b5531b112b4..15f74fe5779 100644 +--- a/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py ++++ b/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py +@@ -256,7 +256,7 @@ + Sage example in ./calculus.tex, line 1086:: + + sage: solve(x^(1/x)==(1/x)^x, x) +- [(1/x)^x == x^(1/x)] ++ [x^(1/x) == (1/x)^x] + + Sage example in ./calculus.tex, line 1124:: + diff --git a/srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch b/srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch new file mode 100644 index 00000000000000..393bb5a79b0bc5 --- /dev/null +++ b/srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch @@ -0,0 +1,11 @@ +--- a/src/sage/calculus/calculus.py ++++ b/src/sage/calculus/calculus.py +@@ -1824,7 +1824,7 @@ def laplace(ex, t, s, algorithm='maxima'): + sage: f = exp (2*t + a) * sin(t) * t; f + t*e^(a + 2*t)*sin(t) + sage: L = laplace(f, t, s); L +- 2*(s - 2)*e^a/(s^2 - 4*s + 5)^2 ++ 2*(s - 2)*e^a/(s^4 - 8*s^3 + 26*s^2 - 40*s + 25) + sage: inverse_laplace(L, s, t) + t*e^(a + 2*t)*sin(t) + diff --git a/srcpkgs/sagemath/patches/get_patches b/srcpkgs/sagemath/patches/get_patches index d0093639f7d867..e7f3d188f71eb2 100755 --- a/srcpkgs/sagemath/patches/get_patches +++ b/srcpkgs/sagemath/patches/get_patches @@ -40,3 +40,4 @@ get_pr 41346 "Fix execution_count for newer ipython version" get_pr 41394 "Fix doctest failure with python 3.14" get_pr 41433 "Fix test failures with scipy 1.17" get_pr 41469 "Prevent leaking file descriptors" +get_pr 40679 "Update to maxima 5.49" diff --git a/srcpkgs/sagemath/template b/srcpkgs/sagemath/template index 3f27587fc5c170..87f906d87e1a26 100644 --- a/srcpkgs/sagemath/template +++ b/srcpkgs/sagemath/template @@ -1,7 +1,7 @@ # Template file for 'sagemath' pkgname=sagemath version=10.8 -revision=1 +revision=2 _pypi_version=${version/.beta/b} _pypi_version=${_pypi_version/.rc/rc} build_style=python3-pep517 From 22646499efa07a4e1e061e192d5191399da00fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 16:34:41 -0300 Subject: [PATCH 05/18] sagemath: fix doctest for ipython 9.12 --- .../sagemath/patches/fix-doctest-ipython-9.12.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 srcpkgs/sagemath/patches/fix-doctest-ipython-9.12.patch diff --git a/srcpkgs/sagemath/patches/fix-doctest-ipython-9.12.patch b/srcpkgs/sagemath/patches/fix-doctest-ipython-9.12.patch new file mode 100644 index 00000000000000..000e50345e7ed3 --- /dev/null +++ b/srcpkgs/sagemath/patches/fix-doctest-ipython-9.12.patch @@ -0,0 +1,12 @@ +diff --git a/src/sage/doctest/test.py b/src/sage/doctest/test.py +index 8e7ecac8bbe..7831de313cc 100644 +--- a/src/sage/doctest/test.py ++++ b/src/sage/doctest/test.py +@@ -469,6 +469,7 @@ Test the ``--debug`` option:: + s...: b = 5 + s...: a + b + 8 ++ ... + sage: + + Returning to doctests... From a1945de4a0a5a2d3f2b386edf9a42c19403bc9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 21:02:40 -0300 Subject: [PATCH 06/18] sagemath: fix cypari2 warning --- .../patches/fix-cypari2-warning.patch | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 srcpkgs/sagemath/patches/fix-cypari2-warning.patch diff --git a/srcpkgs/sagemath/patches/fix-cypari2-warning.patch b/srcpkgs/sagemath/patches/fix-cypari2-warning.patch new file mode 100644 index 00000000000000..5d4b06dab691e3 --- /dev/null +++ b/srcpkgs/sagemath/patches/fix-cypari2-warning.patch @@ -0,0 +1,30 @@ +diff --git a/src/sage/rings/factorint_pari.pyx b/src/sage/rings/factorint_pari.pyx +index 1774cbf0886..be0a500c2b6 100644 +--- a/src/sage/rings/factorint_pari.pyx ++++ b/src/sage/rings/factorint_pari.pyx +@@ -53,8 +53,6 @@ def factor_using_pari(n, int_=False, debug_level=0, proof=None): + sage: from sage.doctest.util import ensure_interruptible_after + sage: with ensure_interruptible_after(0.5): factor(2^1000 - 1, verbose=5) + ... +- doctest:warning... +- RuntimeWarning: cypari2 leaked ... bytes on the PARI stack + sage: pari.get_debug_level() + 0 + """ +diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx +index 358aac0339c..dc4dcc4866e 100644 +--- a/src/sage/rings/integer.pyx ++++ b/src/sage/rings/integer.pyx +@@ -7305,10 +7305,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): + check for reliable interrupting, see :issue:`18919`:: + + sage: from cysignals import AlarmInterrupt ++ sage: from warnings import filterwarnings ++ sage: filterwarnings("ignore", r"cypari2 leaked \d+ bytes on the PARI stack") + sage: for i in [1..10]: # long time (5s) # needs sage.libs.pari + ....: with ensure_interruptible_after(i/11): + ....: (2^100).binomial(2^22, algorithm='pari') +- doctest:...: RuntimeWarning: cypari2 leaked ... bytes on the PARI stack... + """ + cdef Integer x + cdef Integer mm From 244b5bb904db4620b2c53d9929934d3589e834ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Sun, 26 Apr 2026 16:40:28 -0300 Subject: [PATCH 07/18] ecl: use upstream fix for abort in mprotect() --- srcpkgs/ecl/patches/370.patch | 33 +++++++++++++++++++ .../patches/first_env_page_alignment.patch | 24 -------------- 2 files changed, 33 insertions(+), 24 deletions(-) create mode 100644 srcpkgs/ecl/patches/370.patch delete mode 100644 srcpkgs/ecl/patches/first_env_page_alignment.patch diff --git a/srcpkgs/ecl/patches/370.patch b/srcpkgs/ecl/patches/370.patch new file mode 100644 index 00000000000000..30aea6345f063a --- /dev/null +++ b/srcpkgs/ecl/patches/370.patch @@ -0,0 +1,33 @@ +See: + - https://gitlab.com/embeddable-common-lisp/ecl/-/merge_requests/370 + - https://github.com/sagemath/sage/pull/41879#issuecomment-4244171007 + +--- a/src/c/main.d ++++ b/src/c/main.d +@@ -49,7 +49,6 @@ + /******************************* EXPORTS ******************************/ + + const char *ecl_self; +-static struct cl_env_struct first_env; + + /************************ GLOBAL INITIALIZATION ***********************/ + +@@ -419,7 +418,7 @@ struct cl_core_struct cl_core = { + + .system_properties = ECL_NIL, + +- .first_env = &first_env, ++ .first_env = NULL, + #ifdef ECL_THREADS + .processes = ECL_NIL, + #endif +@@ -498,6 +497,9 @@ cl_boot(int argc, char **argv) + setbuf(stdin, stdin_buf); + setbuf(stdout, stdout_buf); + #endif ++ ++ /* The first environment must be available at all times. */ ++ cl_core.first_env = _ecl_alloc_env(NULL); + init_process(); + + ARGC = argc; diff --git a/srcpkgs/ecl/patches/first_env_page_alignment.patch b/srcpkgs/ecl/patches/first_env_page_alignment.patch deleted file mode 100644 index ed979328592b40..00000000000000 --- a/srcpkgs/ecl/patches/first_env_page_alignment.patch +++ /dev/null @@ -1,24 +0,0 @@ -ECL 26.3.27 changed the main thread environment from mmap-allocated -(page-aligned) to a static struct first_env. The ECL_USE_MPROTECT fast -interrupt dispatch calls mprotect() on this struct, which requires the -address to be page-aligned. The unaligned static variable causes -mprotect() to fail with EINVAL when a signal arrives while interrupts -are disabled (e.g. inside ecl_cons), crashing with "Unable to mprotect -environment". Align first_env to 65536 bytes (covers 4K/16K/64K pages). -See https://github.com/sagemath/sage/pull/41879 - -diff --git a/src/c/main.d b/src/c/main.d ---- a/src/c/main.d -+++ b/src/c/main.d -@@ -49,7 +49,12 @@ - - const char *ecl_self; --static struct cl_env_struct first_env; -+/* Align to page boundary: ECL_USE_MPROTECT calls mprotect() on this -+ struct for fast interrupt dispatch, which requires a page-aligned -+ address. Use 65536 to cover all common page sizes (4K/16K/64K). -+ Prior ECL versions allocated this via mmap() which is always -+ page-aligned; this was changed to a static variable in 26.3.27. */ -+static struct cl_env_struct __attribute__((aligned(65536))) first_env; - - /************************ GLOBAL INITIALIZATION ***********************/ From 9f32dd0817fdc50c9a7d1d053978ee38e6f87636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Thu, 7 May 2026 15:54:32 -0300 Subject: [PATCH 08/18] ecl: update to 26.5.5. --- common/shlibs | 2 +- srcpkgs/ecl/patches/370.patch | 33 --------------------------------- srcpkgs/ecl/template | 4 ++-- 3 files changed, 3 insertions(+), 36 deletions(-) delete mode 100644 srcpkgs/ecl/patches/370.patch diff --git a/common/shlibs b/common/shlibs index 9ca8a92ba7d849..47de8309518977 100644 --- a/common/shlibs +++ b/common/shlibs @@ -4250,7 +4250,7 @@ libcxsparse.so.4 SuiteSparse-6.0.1_1 libspqr.so.4 SuiteSparse-7.2.0_1 libsuitesparseconfig.so.7 SuiteSparse-7.0.1_1 libumfpack.so.6 SuiteSparse-6.0.1_1 -libecl.so.26.3 ecl-26.3.27_1 +libecl.so.26.5 ecl-26.5.5_1 libecm.so.1 ecm-7.0.4_3 libcliquer.so.1 cliquer-1.22_1 libomalloc-0.9.6.so singular-4.2.1_1 diff --git a/srcpkgs/ecl/patches/370.patch b/srcpkgs/ecl/patches/370.patch deleted file mode 100644 index 30aea6345f063a..00000000000000 --- a/srcpkgs/ecl/patches/370.patch +++ /dev/null @@ -1,33 +0,0 @@ -See: - - https://gitlab.com/embeddable-common-lisp/ecl/-/merge_requests/370 - - https://github.com/sagemath/sage/pull/41879#issuecomment-4244171007 - ---- a/src/c/main.d -+++ b/src/c/main.d -@@ -49,7 +49,6 @@ - /******************************* EXPORTS ******************************/ - - const char *ecl_self; --static struct cl_env_struct first_env; - - /************************ GLOBAL INITIALIZATION ***********************/ - -@@ -419,7 +418,7 @@ struct cl_core_struct cl_core = { - - .system_properties = ECL_NIL, - -- .first_env = &first_env, -+ .first_env = NULL, - #ifdef ECL_THREADS - .processes = ECL_NIL, - #endif -@@ -498,6 +497,9 @@ cl_boot(int argc, char **argv) - setbuf(stdin, stdin_buf); - setbuf(stdout, stdout_buf); - #endif -+ -+ /* The first environment must be available at all times. */ -+ cl_core.first_env = _ecl_alloc_env(NULL); - init_process(); - - ARGC = argc; diff --git a/srcpkgs/ecl/template b/srcpkgs/ecl/template index 2fdcfdf8656c83..7969952113e723 100644 --- a/srcpkgs/ecl/template +++ b/srcpkgs/ecl/template @@ -1,6 +1,6 @@ # Template file for 'ecl' pkgname=ecl -version=26.3.27 +version=26.5.5 revision=1 build_style=gnu-configure configure_args="--enable-gmp=system --enable-boehm=system @@ -14,7 +14,7 @@ license="LGPL-2.1-or-later" homepage="https://ecl.common-lisp.dev/" changelog="https://gitlab.com/embeddable-common-lisp/ecl/-/raw/develop/CHANGELOG" distfiles="https://ecl.common-lisp.dev/static/files/release/ecl-${version}.tgz" -checksum=416d5707bf11d2b3d8d33d6791419a786e4cc59ac0cc3ec505ee59b51a9f5c9a +checksum=a01a5bcda8c5b73e59dda3494fd13e5fec5db6aa1dad782c3cc3bb57f1633435 if [ "$CROSS_BUILD" ]; then # Depend on system ecl From d0f8530f882015b0c7340ae315e42d140deddf95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 6 Apr 2026 16:08:04 -0300 Subject: [PATCH 09/18] python3-cypari2: add fix for memleak --- .../python3-cypari2/patches/fix-memleak.patch | 18 ++++++++++++++++++ srcpkgs/python3-cypari2/template | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/python3-cypari2/patches/fix-memleak.patch diff --git a/srcpkgs/python3-cypari2/patches/fix-memleak.patch b/srcpkgs/python3-cypari2/patches/fix-memleak.patch new file mode 100644 index 00000000000000..c5ecf28f0ada78 --- /dev/null +++ b/srcpkgs/python3-cypari2/patches/fix-memleak.patch @@ -0,0 +1,18 @@ +--- a/cypari2/custom_block.pyx ++++ b/cypari2/custom_block.pyx +@@ -6,6 +6,7 @@ + #***************************************************************************** + + from cysignals.signals cimport add_custom_signals ++from .stack cimport reset_avma + + cdef extern from "pari/pari.h": + int PARI_SIGINT_block, PARI_SIGINT_pending +@@ -16,6 +17,7 @@ cdef int custom_signal_is_blocked() noexcept: + cdef void custom_signal_unblock() noexcept: + global PARI_SIGINT_block + PARI_SIGINT_block = 0 ++ reset_avma() + + cdef void custom_set_pending_signal(int sig) noexcept: + global PARI_SIGINT_pending diff --git a/srcpkgs/python3-cypari2/template b/srcpkgs/python3-cypari2/template index 3dfa683d22d922..31056974043705 100644 --- a/srcpkgs/python3-cypari2/template +++ b/srcpkgs/python3-cypari2/template @@ -1,7 +1,7 @@ # Template file for 'python3-cypari2' pkgname=python3-cypari2 version=2.2.4 -revision=1 +revision=2 build_style=python3-pep517 build_helper="meson qemu" hostmakedepends="python3-meson-python python3-Cython From 747b6dbf4a62a9174e56b3a6b05e2ac284943d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 23:03:15 -0300 Subject: [PATCH 10/18] lcalc: update to 2.2.1. --- srcpkgs/lcalc/template | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/srcpkgs/lcalc/template b/srcpkgs/lcalc/template index 70e2797611bc93..62af3836aa96d1 100644 --- a/srcpkgs/lcalc/template +++ b/srcpkgs/lcalc/template @@ -1,28 +1,24 @@ # Template file for 'lcalc' pkgname=lcalc -version=2.1.1 +version=2.2.1 revision=1 build_style=gnu-configure configure_args="--with-pari" -hostmakedepends="automake libtool pkg-config gengetopt" +hostmakedepends="gengetopt" makedepends="gmp-devel pari-devel" short_desc="Michael Rubinstein's L-function calculator" maintainer="Gonzalo Tornaría " license="GPL-2.0-or-later" homepage="https://gitlab.com/sagemath/lcalc" changelog="https://gitlab.com/sagemath/lcalc/-/raw/master/doc/ChangeLog" -distfiles="https://gitlab.com/sagemath/lcalc/-/archive/${version}/lcalc-${version}.tar.bz2" -checksum=f93c1ac7ad6d5524f52888cae5eefc5a00af635d34d53831e16e221166b5b6cd +distfiles="https://gitlab.com/-/project/12934202/uploads/0bcf82cdd02412faf9ec0cf80e656610/lcalc-${version}.tar.xz" +checksum=aa2c3979b12e12df2ecb681c1a25a0f5a3811c195f61a3baa7512fef1460c40f case $XBPS_TARGET_MACHINE in # avoid numerical noise caused by extended-precision of registers i686*) CXXFLAGS="-mfpmath=sse -msse2" ;; esac -pre_configure() { - autoreconf -fi -} - lcalc-devel_package() { depends="${sourcepkg}>=${version}_${revision}" short_desc+=" - development files" From 87b501382b0dc0c038ca2320d0b51f4a97966e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 23:38:37 -0300 Subject: [PATCH 11/18] libbraiding: update to 1.3.2. --- srcpkgs/libbraiding/template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srcpkgs/libbraiding/template b/srcpkgs/libbraiding/template index 9a7dce708562db..af55ba689932af 100644 --- a/srcpkgs/libbraiding/template +++ b/srcpkgs/libbraiding/template @@ -1,7 +1,7 @@ # Template file for 'libbraiding' pkgname=libbraiding -version=1.3.1 -revision=2 +version=1.3.2 +revision=1 build_style=gnu-configure short_desc="Library to compute several properties of braids" maintainer="Gonzalo Tornaría " @@ -9,7 +9,7 @@ license="GPL-2.0-or-later" homepage="https://github.com/miguelmarco/libbraiding/" changelog="https://github.com/miguelmarco/libbraiding/releases" distfiles="https://github.com/miguelmarco/libbraiding/releases/download/$version/libbraiding-$version.tar.gz" -checksum=d1738c3ad64a90ca0ad968d2e3c9069b0de08abcf37fb44a151a229d88203950 +checksum=d43a32e7770d5c9a89ae489c5ac353da9610a761f76745382cf7612eab046ffd libbraiding-devel_package() { depends="${sourcepkg}>=${version}_${revision} ${makedepends}" From 74b15229da4f4d422a82a0c16f20d2b66ee643ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 23:43:57 -0300 Subject: [PATCH 12/18] libhomfly: update to 1.04. --- srcpkgs/libhomfly/template | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/srcpkgs/libhomfly/template b/srcpkgs/libhomfly/template index 4b703dbd6cf046..d61e89c0991279 100644 --- a/srcpkgs/libhomfly/template +++ b/srcpkgs/libhomfly/template @@ -1,6 +1,6 @@ # Template file for 'libhomfly' pkgname=libhomfly -version=1.03 +version=1.04 revision=1 build_style=gnu-configure makedepends="gc-devel" @@ -8,8 +8,9 @@ short_desc="Library to compute the homfly polynomial of knots and links" maintainer="Gonzalo Tornaría " license="custom:unlicense" homepage="https://github.com/miguelmarco/libhomfly/" +changelog="https://github.com/miguelmarco/libhomfly/releases" distfiles="https://github.com/miguelmarco/libhomfly/releases/download/${version}/libhomfly-${version}.tar.gz" -checksum=2a06e93cccd91d33ed9c345eba2e59b2ba175c11e454cf2029644a9364250871 +checksum=659a77b4f4b53340d24a7d6a69f4219e77ab9439a6ab8afa0156b7f6bd7af64f post_install() { vlicense LICENSE From 629dd0c55750b85538378dbab3b478af72abc7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 13 Apr 2026 23:00:20 -0300 Subject: [PATCH 13/18] libmpc: update to 1.4.0. --- srcpkgs/libmpc/template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srcpkgs/libmpc/template b/srcpkgs/libmpc/template index 0d5622143a584e..ed35e345c3a051 100644 --- a/srcpkgs/libmpc/template +++ b/srcpkgs/libmpc/template @@ -1,6 +1,6 @@ # Template file for 'libmpc' pkgname=libmpc -version=1.3.1 +version=1.4.0 revision=1 bootstrap=yes build_style=gnu-configure @@ -10,8 +10,8 @@ maintainer="Gonzalo Tornaría " license="LGPL-3.0-or-later" homepage="https://www.multiprecision.org/mpc/" changelog="https://gitlab.inria.fr/mpc/mpc/-/raw/master/NEWS" -distfiles="${GNU_SITE}/mpc/mpc-${version}.tar.gz" -checksum=ab642492f5cf882b74aa0cb730cd410a81edcdbec895183ce930e706c1c759b8 +distfiles="${GNU_SITE}/mpc/mpc-${version}.tar.xz" +checksum=3210b3a546b1cb00c296ca360891d7740ee6ff06deb02a27a35b20cd3c0bb1a5 if [ -z "$CHROOT_READY" ]; then CFLAGS="-I${XBPS_MASTERDIR}/usr/include" From eb20762bd0a69f56070b4e1ad3dbef43fcaa2ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Fri, 6 Mar 2026 18:47:03 -0300 Subject: [PATCH 14/18] python3-mpmath: update to 1.4.1. --- .../python3-mpmath/patches/fix-pytest.patch | 47 ------------------- srcpkgs/python3-mpmath/template | 12 ++--- 2 files changed, 6 insertions(+), 53 deletions(-) delete mode 100644 srcpkgs/python3-mpmath/patches/fix-pytest.patch diff --git a/srcpkgs/python3-mpmath/patches/fix-pytest.patch b/srcpkgs/python3-mpmath/patches/fix-pytest.patch deleted file mode 100644 index f67d5b39b3299a..00000000000000 --- a/srcpkgs/python3-mpmath/patches/fix-pytest.patch +++ /dev/null @@ -1,47 +0,0 @@ -commit ccebfbacbe1dc65716b8b7a9cd3c930447dbfa03 -Author: Gonzalo Tornaría -Date: Sun Mar 19 11:03:30 2023 -0300 - - Fix running pytest - - Running pytest doesn't work quite right. Changes here: - - move all pytest configuration from setup.cfg to pytest.ini to avoid - having different configurations - - add . to pythonpath so the mpmath module here takes precedence in - case mpmath is installed in system - - fix norecursedirs: doc/source/plots -> docs/plots - - add build to norecursedirs so pytest works even after building mpmath - - add '*.rst' to globs so pytest picks a few tests in docs/*.rst - -diff --git a/pytest.ini b/pytest.ini -index 95697f2..93f753f 100644 ---- a/pytest.ini -+++ b/pytest.ini -@@ -0,0 +1,10 @@ -+[pytest] -+pythonpath = . -+doctest_optionflags = IGNORE_EXCEPTION_DETAIL -+addopts = --doctest-modules -+ --ignore=setup.py -+ --doctest-glob='*.txt' -+ --doctest-glob='*.rst' -+norecursedirs = docs/plots demo .eggs .git build -+markers = -+ slow: marks tests as slow (deselect with '-m "not slow"') -diff --git a/setup.cfg b/setup.cfg -index 9dd3067..2761b08 100644 ---- a/setup.cfg -+++ b/setup.cfg -@@ -45,12 +45,6 @@ docs = sphinx - select = E101,W191,W291,W293,E111,E112,E113,W292,W391 - exclude = .eggs,.git - --[tool:pytest] --doctest_optionflags = IGNORE_EXCEPTION_DETAIL --addopts = --doctest-modules -- --ignore=setup.py -- --doctest-glob='*.txt' --norecursedirs = doc/source/plots demo .eggs .git - - [coverage:run] - branch = True diff --git a/srcpkgs/python3-mpmath/template b/srcpkgs/python3-mpmath/template index fccf8b7881929a..7698e23f1f1138 100644 --- a/srcpkgs/python3-mpmath/template +++ b/srcpkgs/python3-mpmath/template @@ -1,18 +1,18 @@ # Template file for 'python3-mpmath' pkgname=python3-mpmath -version=1.3.0 -revision=4 -build_style=python3-module -hostmakedepends="python3-setuptools" +version=1.4.1 +revision=1 +build_style=python3-pep517 +hostmakedepends="python3-setuptools_scm" depends="python3 python3-gmpy2" -checkdepends="$depends python3-pytest" +checkdepends="$depends python3-pytest python3-hypothesis python3-pexpect" short_desc="Python3 library for arbitrary-precision floating-point arithmetic" maintainer="Gonzalo Tornaría " license="BSD-3-Clause" homepage="http://mpmath.org/" changelog="https://github.com/mpmath/mpmath/raw/master/CHANGES" distfiles="${PYPI_SITE}/m/mpmath/mpmath-${version}.tar.gz" -checksum=7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f +checksum=efd6d1b75f09d69524a67609949812668b28e81ecbfe0ab449ced8c13e92642e if [ "$XBPS_CHECK_PKGS" != full ]; then make_check_args="-m not(slow)" From 2e86652cb55c8493d0706d75a6d28ada3426fc59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Fri, 6 Mar 2026 23:21:03 -0300 Subject: [PATCH 15/18] python3-sympy: patch for mpmath 1.4 --- srcpkgs/python3-sympy/patches/28060.patch | 390 ++++++++++++++++++++++ srcpkgs/python3-sympy/patches/29250.patch | 71 ++++ srcpkgs/python3-sympy/template | 2 +- 3 files changed, 462 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/python3-sympy/patches/28060.patch create mode 100644 srcpkgs/python3-sympy/patches/29250.patch diff --git a/srcpkgs/python3-sympy/patches/28060.patch b/srcpkgs/python3-sympy/patches/28060.patch new file mode 100644 index 00000000000000..174531fc1a331b --- /dev/null +++ b/srcpkgs/python3-sympy/patches/28060.patch @@ -0,0 +1,390 @@ +From 2bfc02884645447072ebb02afa93acd648eb1970 Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sat, 10 May 2025 20:02:30 +0200 +Subject: [PATCH 1/8] Replace deprecated bitcount + +--- + sympy/core/evalf.py | 3 +-- + sympy/core/numbers.py | 4 ++-- + sympy/ntheory/partitions_.py | 5 +++-- + sympy/physics/quantum/qubit.py | 6 +++--- + 4 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/sympy/core/evalf.py b/sympy/core/evalf.py +index 55a981090360..da173bf6d21d 100644 +--- a/sympy/core/evalf.py ++++ b/sympy/core/evalf.py +@@ -16,7 +16,6 @@ + mpf_atan, mpf_atan2, mpf_cmp, mpf_cos, mpf_e, mpf_exp, mpf_log, mpf_lt, + mpf_mul, mpf_neg, mpf_pi, mpf_pow, mpf_pow_int, mpf_shift, mpf_sin, + mpf_sqrt, normalize, round_nearest, to_int, to_str, mpf_tan) +-from mpmath.libmp import bitcount as mpmath_bitcount + from mpmath.libmp.backend import MPZ + from mpmath.libmp.libmpc import _infs_nan + from mpmath.libmp.libmpf import dps_to_prec, prec_to_dps +@@ -50,7 +49,7 @@ + def bitcount(n): + """Return smallest integer, b, such that |n|/2**b < 1. + """ +- return mpmath_bitcount(abs(int(n))) ++ return MPZ(abs(int(n))).bit_length() + + # Used in a few places as placeholder values to denote exponents and + # precision levels, e.g. of exact numbers. Must be careful to avoid +diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py +index a5483ea707f8..4d9c65132dd2 100644 +--- a/sympy/core/numbers.py ++++ b/sympy/core/numbers.py +@@ -24,7 +24,7 @@ + from sympy.multipledispatch import dispatch + import mpmath + import mpmath.libmp as mlib +-from mpmath.libmp import bitcount, round_nearest as rnd ++from mpmath.libmp import round_nearest as rnd + from mpmath.libmp.backend import MPZ + from mpmath.libmp import mpf_pow, mpf_pi, mpf_e, phi_fixed + from mpmath.ctx_mp_python import mpnumeric +@@ -910,7 +910,7 @@ def __new__(cls, num, dps=None, precision=None): + # don't compute number or else it may + # over/underflow + return Float._new( +- (num[0], num[1], num[2], bitcount(num[1])), ++ (num[0], num[1], num[2], MPZ(num[1]).bit_length()), + precision) + elif isinstance(num, (Number, NumberSymbol)): + _mpf_ = num._as_mpf_val(precision) +diff --git a/sympy/ntheory/partitions_.py b/sympy/ntheory/partitions_.py +index 953fa9e2fef1..ebabdcdf64ac 100644 +--- a/sympy/ntheory/partitions_.py ++++ b/sympy/ntheory/partitions_.py +@@ -1,7 +1,8 @@ + from mpmath.libmp import (fzero, from_int, from_rational, +- fone, fhalf, bitcount, to_int, mpf_mul, mpf_div, mpf_sub, ++ fone, fhalf, to_int, mpf_mul, mpf_div, mpf_sub, + mpf_add, mpf_sqrt, mpf_pi, mpf_cosh_sinh, mpf_cos, mpf_sin) + from .residue_ntheory import _sqrt_mod_prime_power, is_quad_residue ++from sympy.core.evalf import bitcount + from sympy.utilities.decorator import deprecated + from sympy.utilities.memoization import recurrence_memo + +@@ -236,7 +237,7 @@ def _M(n, N): + # On average, the terms decrease rapidly in magnitude. + # Dynamically reducing the precision greatly improves + # performance. +- p = bitcount(abs(to_int(d))) + 50 ++ p = bitcount(to_int(d)) + 50 + return int(to_int(mpf_add(s, fhalf, prec))) + + +diff --git a/sympy/physics/quantum/qubit.py b/sympy/physics/quantum/qubit.py +index 71d1dbc01e3a..83cb0b0f128f 100644 +--- a/sympy/physics/quantum/qubit.py ++++ b/sympy/physics/quantum/qubit.py +@@ -10,6 +10,7 @@ + import math + + from sympy.core.add import Add ++from sympy.core.evalf import bitcount + from sympy.core.mul import Mul + from sympy.core.numbers import Integer + from sympy.core.power import Pow +@@ -29,7 +30,6 @@ + from sympy.physics.quantum.matrixutils import ( + numpy_ndarray, scipy_sparse_matrix + ) +-from mpmath.libmp.libintmath import bitcount + + __all__ = [ + 'Qubit', +@@ -307,7 +307,7 @@ def _eval_args(cls, args, nqubits=None): + # that integer with the minimal number of bits. + if len(args) == 1 and args[0] > 1: + #rvalues is the minimum number of bits needed to express the number +- rvalues = reversed(range(bitcount(abs(args[0])))) ++ rvalues = reversed(range(bitcount(args[0]))) + qubit_values = [(args[0] >> i) & 1 for i in rvalues] + return QubitState._eval_args(qubit_values) + # For two numbers, the second number is the number of bits +@@ -319,7 +319,7 @@ def _eval_args(cls, args, nqubits=None): + + @classmethod + def _eval_args_with_nqubits(cls, number, nqubits): +- need = bitcount(abs(number)) ++ need = bitcount(number) + if nqubits < need: + raise ValueError( + 'cannot represent %s with %s bits' % (number, nqubits)) + +From b1adb17b276d45665392c5a397ee4308c07a8f5a Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sat, 10 May 2025 20:45:35 +0200 +Subject: [PATCH 2/8] Use mpmath native bit_length + +--- + sympy/ntheory/partitions_.py | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/sympy/ntheory/partitions_.py b/sympy/ntheory/partitions_.py +index ebabdcdf64ac..bcadd0b813c2 100644 +--- a/sympy/ntheory/partitions_.py ++++ b/sympy/ntheory/partitions_.py +@@ -2,7 +2,6 @@ + fone, fhalf, to_int, mpf_mul, mpf_div, mpf_sub, + mpf_add, mpf_sqrt, mpf_pi, mpf_cosh_sinh, mpf_cos, mpf_sin) + from .residue_ntheory import _sqrt_mod_prime_power, is_quad_residue +-from sympy.core.evalf import bitcount + from sympy.utilities.decorator import deprecated + from sympy.utilities.memoization import recurrence_memo + +@@ -237,7 +236,7 @@ def _M(n, N): + # On average, the terms decrease rapidly in magnitude. + # Dynamically reducing the precision greatly improves + # performance. +- p = bitcount(to_int(d)) + 50 ++ p = to_int(d).bit_length() + 50 + return int(to_int(mpf_add(s, fhalf, prec))) + + + +From 942ff9c2452585892c4cd6ff247323f38733b3e4 Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sat, 10 May 2025 20:53:05 +0200 +Subject: [PATCH 3/8] Use python native bit_length for qubit + +--- + sympy/physics/quantum/qubit.py | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/sympy/physics/quantum/qubit.py b/sympy/physics/quantum/qubit.py +index 83cb0b0f128f..a1abc856e4b1 100644 +--- a/sympy/physics/quantum/qubit.py ++++ b/sympy/physics/quantum/qubit.py +@@ -10,7 +10,6 @@ + import math + + from sympy.core.add import Add +-from sympy.core.evalf import bitcount + from sympy.core.mul import Mul + from sympy.core.numbers import Integer + from sympy.core.power import Pow +@@ -307,7 +306,7 @@ def _eval_args(cls, args, nqubits=None): + # that integer with the minimal number of bits. + if len(args) == 1 and args[0] > 1: + #rvalues is the minimum number of bits needed to express the number +- rvalues = reversed(range(bitcount(args[0]))) ++ rvalues = reversed(range(int(args[0]).bit_length())) + qubit_values = [(args[0] >> i) & 1 for i in rvalues] + return QubitState._eval_args(qubit_values) + # For two numbers, the second number is the number of bits +@@ -319,7 +318,7 @@ def _eval_args(cls, args, nqubits=None): + + @classmethod + def _eval_args_with_nqubits(cls, number, nqubits): +- need = bitcount(number) ++ need = int(number).bit_length() + if nqubits < need: + raise ValueError( + 'cannot represent %s with %s bits' % (number, nqubits)) + +From 86df1f99890ff1afb01959c382618c5970fcf582 Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sat, 10 May 2025 21:41:05 +0200 +Subject: [PATCH 4/8] Remove bitcount from documentations + +--- + sympy/core/evalf.py | 7 +++---- + sympy/core/sympify.py | 4 ++-- + 2 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/sympy/core/evalf.py b/sympy/core/evalf.py +index da173bf6d21d..97fd66346063 100644 +--- a/sympy/core/evalf.py ++++ b/sympy/core/evalf.py +@@ -83,10 +83,9 @@ class PrecisionExhausted(ArithmeticError): + Explanation + =========== + +->>> from sympy.core.evalf import bitcount + >>> sign, man, exp, bc = 0, 5, 1, 3 + >>> n = [1, -1][sign]*man*2**exp +->>> n, bitcount(man) ++>>> n, man.bit_length() + (10, 3) + + A temporary result is a tuple (re, im, re_acc, im_acc) where +@@ -133,9 +132,9 @@ def fastlog(x: MPF_TUP | None) -> int | Any: + ======== + + >>> from sympy import log +- >>> from sympy.core.evalf import fastlog, bitcount ++ >>> from sympy.core.evalf import fastlog + >>> s, m, e = 0, 5, 1 +- >>> bc = bitcount(m) ++ >>> bc = m.bit_length() + >>> n = [1, -1][s]*m*2**e + >>> n, (log(n)/log(2)).evalf(2), fastlog((s, m, e, bc)) + (10, 3.3, 4) +diff --git a/sympy/core/sympify.py b/sympy/core/sympify.py +index df30fbb85d5f..33a88d98579d 100644 +--- a/sympy/core/sympify.py ++++ b/sympy/core/sympify.py +@@ -202,11 +202,11 @@ def sympify(a, locals=None, convert_xor=True, strict=False, rational=False, + ... + TypeError: unbound method... + +- In order to have ``bitcount`` be recognized it can be imported into a ++ In order to have ``bitcount`` be recognized it can be defined in a + namespace dictionary and passed as locals: + + >>> ns = {} +- >>> exec('from sympy.core.evalf import bitcount', ns) ++ >>> exec('bitcount = lambda n: int(n).bit_length()', ns) + >>> sympify(s, locals=ns) + 6 + + +From 4a660fbabe750c7b8fc7f84521ac3ee10755a7f2 Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sat, 10 May 2025 22:08:15 +0200 +Subject: [PATCH 5/8] Use mpz(n).bit_length() + +--- + sympy/core/evalf.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/sympy/core/evalf.py b/sympy/core/evalf.py +index 97fd66346063..fa7d8bcdc03a 100644 +--- a/sympy/core/evalf.py ++++ b/sympy/core/evalf.py +@@ -553,7 +553,7 @@ def add_terms(terms: list, prec: int, target_prec: int) -> \ + # first: quick test + if ((delta > working_prec) and + ((not sum_man) or +- delta - bitcount(abs(sum_man)) > working_prec)): ++ delta - MPZ(sum_man).bit_length() > working_prec)): + sum_man = man + sum_exp = exp + else: +@@ -575,7 +575,7 @@ def add_terms(terms: list, prec: int, target_prec: int) -> \ + sum_man = -sum_man + else: + sum_sign = 0 +- sum_bc = bitcount(sum_man) ++ sum_bc = MPZ(sum_man).bit_length() + sum_accuracy = sum_exp + sum_bc - absolute_error + r = normalize(sum_sign, sum_man, sum_exp, sum_bc, target_prec, + rnd), sum_accuracy +@@ -715,7 +715,7 @@ def evalf_mul(v: 'Mul', prec: int, options: OPT_DICT) -> TMP_RES: + acc = min(acc, w_acc) + sign = (direction & 2) >> 1 + if not complex_factors: +- v = normalize(sign, man, exp, bitcount(man), prec, rnd) ++ v = normalize(sign, man, exp, MPZ(man).bit_length(), prec, rnd) + # multiply by i + if direction & 1: + return None, v, None, acc +@@ -725,7 +725,7 @@ def evalf_mul(v: 'Mul', prec: int, options: OPT_DICT) -> TMP_RES: + # initialize with the first term + if (man, exp, bc) != start: + # there was a real part; give it an imaginary part +- re, im = (sign, man, exp, bitcount(man)), (0, MPZ(0), 0, 0) ++ re, im = (sign, man, exp, MPZ(man).bit_length()), (0, MPZ(0), 0, 0) + i0 = 0 + else: + # there is no real part to start (other than the starting 1) + +From 7f32c2d9044e3fce1d42df3ef402fb934c251db7 Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sat, 10 May 2025 23:31:52 +0200 +Subject: [PATCH 6/8] Remove redundant MPZ + +--- + sympy/core/evalf.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/sympy/core/evalf.py b/sympy/core/evalf.py +index fa7d8bcdc03a..8c2881f2d598 100644 +--- a/sympy/core/evalf.py ++++ b/sympy/core/evalf.py +@@ -553,7 +553,7 @@ def add_terms(terms: list, prec: int, target_prec: int) -> \ + # first: quick test + if ((delta > working_prec) and + ((not sum_man) or +- delta - MPZ(sum_man).bit_length() > working_prec)): ++ delta - sum_man.bit_length() > working_prec)): + sum_man = man + sum_exp = exp + else: +@@ -575,7 +575,7 @@ def add_terms(terms: list, prec: int, target_prec: int) -> \ + sum_man = -sum_man + else: + sum_sign = 0 +- sum_bc = MPZ(sum_man).bit_length() ++ sum_bc = sum_man.bit_length() + sum_accuracy = sum_exp + sum_bc - absolute_error + r = normalize(sum_sign, sum_man, sum_exp, sum_bc, target_prec, + rnd), sum_accuracy +@@ -715,7 +715,7 @@ def evalf_mul(v: 'Mul', prec: int, options: OPT_DICT) -> TMP_RES: + acc = min(acc, w_acc) + sign = (direction & 2) >> 1 + if not complex_factors: +- v = normalize(sign, man, exp, MPZ(man).bit_length(), prec, rnd) ++ v = normalize(sign, man, exp, man.bit_length(), prec, rnd) + # multiply by i + if direction & 1: + return None, v, None, acc +@@ -725,7 +725,7 @@ def evalf_mul(v: 'Mul', prec: int, options: OPT_DICT) -> TMP_RES: + # initialize with the first term + if (man, exp, bc) != start: + # there was a real part; give it an imaginary part +- re, im = (sign, man, exp, MPZ(man).bit_length()), (0, MPZ(0), 0, 0) ++ re, im = (sign, man, exp, man.bit_length()), (0, MPZ(0), 0, 0) + i0 = 0 + else: + # there is no real part to start (other than the starting 1) + +From 4cdb80777410909085e500a5bd1cf8397b869112 Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sun, 11 May 2025 01:10:33 +0200 +Subject: [PATCH 7/8] Remove extra mpz + +--- + sympy/core/numbers.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py +index 4d9c65132dd2..46424fb5579b 100644 +--- a/sympy/core/numbers.py ++++ b/sympy/core/numbers.py +@@ -910,7 +910,7 @@ def __new__(cls, num, dps=None, precision=None): + # don't compute number or else it may + # over/underflow + return Float._new( +- (num[0], num[1], num[2], MPZ(num[1]).bit_length()), ++ (num[0], num[1], num[2], num[1].bit_length(), + precision) + elif isinstance(num, (Number, NumberSymbol)): + _mpf_ = num._as_mpf_val(precision) + +From e0a7d9121432ce94bd2cf90b4502abed34231d88 Mon Sep 17 00:00:00 2001 +From: Sangyub Lee +Date: Sun, 11 May 2025 01:13:09 +0200 +Subject: [PATCH 8/8] Fix syntax error + +--- + sympy/core/numbers.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py +index 46424fb5579b..2425e0c081f2 100644 +--- a/sympy/core/numbers.py ++++ b/sympy/core/numbers.py +@@ -910,7 +910,7 @@ def __new__(cls, num, dps=None, precision=None): + # don't compute number or else it may + # over/underflow + return Float._new( +- (num[0], num[1], num[2], num[1].bit_length(), ++ (num[0], num[1], num[2], num[1].bit_length()), + precision) + elif isinstance(num, (Number, NumberSymbol)): + _mpf_ = num._as_mpf_val(precision) diff --git a/srcpkgs/python3-sympy/patches/29250.patch b/srcpkgs/python3-sympy/patches/29250.patch new file mode 100644 index 00000000000000..004078f0a5f152 --- /dev/null +++ b/srcpkgs/python3-sympy/patches/29250.patch @@ -0,0 +1,71 @@ +Backported from https://github.com/sympy/sympy/pull/29250 + +--- a/sympy/core/evalf.py ++++ b/sympy/core/evalf.py +@@ -13,7 +13,7 @@ + from mpmath import inf as mpmath_inf + from mpmath.libmp import (from_int, from_man_exp, from_rational, fhalf, + fnan, finf, fninf, fnone, fone, fzero, mpf_abs, mpf_add, +- mpf_atan, mpf_atan2, mpf_cmp, mpf_cos, mpf_e, mpf_exp, mpf_log, mpf_lt, ++ mpf_atan, mpf_atan2, mpf_cmp, mpf_cos, mpf_e, mpf_exp, mpf_ln, mpf_lt, + mpf_mul, mpf_neg, mpf_pi, mpf_pow, mpf_pow_int, mpf_shift, mpf_sin, + mpf_sqrt, normalize, round_nearest, to_int, to_str, mpf_tan) + from mpmath.libmp import bitcount as mpmath_bitcount +@@ -992,7 +992,7 @@ + + imaginary_term = (mpf_cmp(xre, fzero) < 0) + +- re = mpf_log(mpf_abs(xre), prec, rnd) ++ re = mpf_ln(mpf_abs(xre), prec, rnd) + size = fastlog(re) + if prec - size > workprec and re != fzero: + from .add import Add +@@ -1001,7 +1001,7 @@ + xre, xim, _, _ = evalf_add(add, prec, options) + prec2 = workprec - fastlog(xre) + # xre is now x - 1 so we add 1 back here to calculate x +- re = mpf_log(mpf_abs(mpf_add(xre, fone, prec2)), prec, rnd) ++ re = mpf_ln(mpf_abs(mpf_add(xre, fone, prec2)), prec, rnd) + + re_acc = prec + +--- a/sympy/core/expr.py ++++ b/sympy/core/expr.py +@@ -18,7 +18,7 @@ + from sympy.utilities.exceptions import sympy_deprecation_warning + from sympy.utilities.misc import as_int, func_name, filldedent + from sympy.utilities.iterables import has_variety, sift +-from mpmath.libmp import mpf_log, prec_to_dps ++from mpmath.libmp import mpf_ln, prec_to_dps + from mpmath.libmp.libintmath import giant_steps + + +@@ -4065,7 +4065,7 @@ + try: + mag_first_dig = int(ceil(log10(xpos))) + except (ValueError, OverflowError): +- mag_first_dig = int(ceil(Float(mpf_log(xpos._mpf_, 53))/log(10))) ++ mag_first_dig = int(ceil(Float(mpf_ln(xpos._mpf_, 53))/log(10))) + # check that we aren't off by 1 + if (xpos/S(10)**mag_first_dig) >= 1: + assert 1 <= (xpos/S(10)**mag_first_dig) < 10 +--- a/sympy/polys/polytools.py ++++ b/sympy/polys/polytools.py +@@ -3726,7 +3726,7 @@ + try: + # We need to add extra precision to guard against losing accuracy. + # 10 times the degree of the polynomial seems to work well. +- roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, ++ roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, asc=False, + cleanup=cleanup, error=False, extraprec=f.degree()*10) + + # Mpmath puts real roots first, then complex ones (as does all_roots) +@@ -3736,7 +3736,7 @@ + except NoConvergence: + try: + # If roots did not converge try again with more extra precision. +- roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, ++ roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, asc=False, + cleanup=cleanup, error=False, extraprec=f.degree()*15) + roots = list(map(sympify, + sorted(roots, key=lambda r: (1 if r.imag else 0, r.real, abs(r.imag), sign(r.imag))))) diff --git a/srcpkgs/python3-sympy/template b/srcpkgs/python3-sympy/template index 116d184de077ab..9225017fbf52e1 100644 --- a/srcpkgs/python3-sympy/template +++ b/srcpkgs/python3-sympy/template @@ -1,7 +1,7 @@ # Template file for 'python3-sympy' pkgname=python3-sympy version=1.14.0 -revision=2 +revision=3 build_style=python3-pep517 hostmakedepends="python3-setuptools python3-wheel" depends="python3-mpmath" From a50cfc2a4096d9be03f6e1820d5a4e0f8fb34783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Fri, 6 Mar 2026 20:38:24 -0300 Subject: [PATCH 16/18] sagemath: patch for mpmath 1.4 --- .../patches/41728-Patch_for_mpmath_1.4.patch | 5691 +++++++++++++++++ srcpkgs/sagemath/patches/get_patches | 1 + 2 files changed, 5692 insertions(+) create mode 100644 srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch diff --git a/srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch b/srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch new file mode 100644 index 00000000000000..5a8ff7fc50626c --- /dev/null +++ b/srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch @@ -0,0 +1,5691 @@ +diff --git a/src/sage/env.py b/src/sage/env.py +index a1092291650..f6c198a8617 100644 +--- a/src/sage/env.py ++++ b/src/sage/env.py +@@ -228,8 +228,9 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st + OPENMP_CFLAGS = var("OPENMP_CFLAGS", "") + OPENMP_CXXFLAGS = var("OPENMP_CXXFLAGS", "") + +-# Make sure mpmath uses Sage types +-os.environ['MPMATH_SAGE'] = '1' ++# Make sure that mpmath < 1.4 does not try to use Sage types ++os.environ.pop('MPMATH_SAGE', None) ++os.environ['MPMATH_NOSAGE'] = '1' + + # misc + SAGE_BANNER = var("SAGE_BANNER", "") +diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py +index 78eb4992aa6..59966f40bd0 100644 +--- a/src/sage/functions/error.py ++++ b/src/sage/functions/error.py +@@ -256,8 +256,8 @@ def _evalf_(self, x, parent=None, algorithm=None): + 0.995322265018953 + sage: erf(2).n(200) # needs sage.symbolic + 0.99532226501895273416206925636725292861089179704006007673835 +- sage: erf(pi - 1/2*I).n(100) # needs sage.symbolic +- 1.0000111669099367825726058952 + 1.6332655417638522934072124547e-6*I ++ sage: erf(pi - 1/2*I).n(100) # needs sage.symbolic # abs tol 1e-28 ++ 1.0000111669099367825726058952 + 1.6332655417638522934072124548e-6*I + + TESTS: + +diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py +index e074c430808..09d2bbda71b 100644 +--- a/src/sage/functions/exp_integral.py ++++ b/src/sage/functions/exp_integral.py +@@ -993,7 +993,7 @@ def _evalf_(self, z, parent=None, algorithm=None): + sage: N(cos_integral(10^-10), digits=30) # needs sage.symbolic + -22.4486352650389239795759024568 + sage: cos_integral(ComplexField(100)(I)) # needs sage.symbolic +- 0.83786694098020824089467857943 + 1.5707963267948966192313216916*I ++ 0.83786694098020824089467857944 + 1.5707963267948966192313216916*I + """ + return _mpmath_utils_call(_mpmath_ci, z, parent=parent) + +diff --git a/src/sage/libs/mpmath/all.py b/src/sage/libs/mpmath/all.py +index ea35faeb721..14a4be971e6 100644 +--- a/src/sage/libs/mpmath/all.py ++++ b/src/sage/libs/mpmath/all.py +@@ -22,5 +22,5 @@ + + + def eval_constant(name, ring): +- prec = ring.precision() + 20 ++ prec = int(ring.precision() + 20) + return ring(_constants_funcs[name](prec)) >> prec +diff --git a/src/sage/libs/mpmath/ext_impl.pxd b/src/sage/libs/mpmath/ext_impl.pxd +deleted file mode 100644 +index 586d10d17f2..00000000000 +--- a/src/sage/libs/mpmath/ext_impl.pxd ++++ /dev/null +@@ -1,66 +0,0 @@ +-from sage.libs.gmp.all cimport mpz_t +- +-ctypedef struct MPopts: +- long prec +- int rounding +- +-cdef mpz_set_integer(mpz_t v, x) +-cdef mpzi(mpz_t n) +-cdef mpzl(mpz_t n) +-cdef str rndmode_to_python(int rnd) +-cdef rndmode_from_python(str rnd) +- +-ctypedef struct MPF: +- mpz_t man +- mpz_t exp +- int special +- +-cdef void MPF_init(MPF *x) noexcept +-cdef void MPF_clear(MPF *x) noexcept +-cdef void MPF_set(MPF *dest, MPF *src) noexcept +-cdef void MPF_set_zero(MPF *x) noexcept +-cdef void MPF_set_one(MPF *x) noexcept +-cdef void MPF_set_nan(MPF *x) noexcept +-cdef void MPF_set_inf(MPF *x) noexcept +-cdef void MPF_set_ninf(MPF *x) noexcept +-cdef MPF_set_si(MPF *x, long n) +-cdef MPF_set_int(MPF *x, n) +-cdef MPF_set_man_exp(MPF *x, man, exp) +-cdef MPF_set_tuple(MPF *x, tuple value) +-cdef MPF_to_tuple(MPF *x) +-cdef MPF_set_double(MPF *r, double x) +-cdef double MPF_to_double(MPF *x, bint strict) noexcept +-cdef MPF_to_fixed(mpz_t r, MPF *x, long prec, bint truncate) +-cdef int MPF_sgn(MPF *x) noexcept +-cdef void MPF_neg(MPF *r, MPF *s) noexcept +-cdef void MPF_abs(MPF *r, MPF *s) noexcept +-cdef MPF_normalize(MPF *x, MPopts opts) +-cdef void MPF_pos(MPF *x, MPF *y, MPopts opts) noexcept +-cdef MPF_add(MPF *r, MPF *s, MPF *t, MPopts opts) +-cdef MPF_sub(MPF *r, MPF *s, MPF *t, MPopts opts) +-cdef bint MPF_eq(MPF *s, MPF *t) noexcept +-cdef bint MPF_ne(MPF *s, MPF *t) noexcept +-cdef int MPF_cmp(MPF *s, MPF *t) noexcept +-cdef bint MPF_lt(MPF *s, MPF *t) noexcept +-cdef bint MPF_le(MPF *s, MPF *t) noexcept +-cdef bint MPF_gt(MPF *s, MPF *t) noexcept +-cdef bint MPF_ge(MPF *s, MPF *t) noexcept +-cdef MPF_mul(MPF *r, MPF *s, MPF *t, MPopts opts) +-cdef MPF_div(MPF *r, MPF *s, MPF *t, MPopts opts) +-cdef int MPF_sqrt(MPF *r, MPF *s, MPopts opts) noexcept +-cdef MPF_hypot(MPF *r, MPF *a, MPF *b, MPopts opts) +-cdef MPF_pow_int(MPF *r, MPF *x, mpz_t n, MPopts opts) +-cdef MPF_set_double(MPF *r, double x) +-cdef MPF_exp(MPF *y, MPF *x, MPopts opts) +-cdef MPF_complex_sqrt(MPF *c, MPF *d, MPF *a, MPF *b, MPopts opts) +-cdef MPF_complex_exp(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts) +-cdef int MPF_log(MPF *y, MPF *x, MPopts opts) noexcept +-cdef MPF_set_pi(MPF *x, MPopts opts) +-cdef MPF_set_ln2(MPF *x, MPopts opts) +-cdef MPF_cos(MPF *c, MPF *x, MPopts opts) +-cdef MPF_sin(MPF *c, MPF *x, MPopts opts) +-cdef MPF_cos_sin(MPF *c, MPF *s, MPF *x, MPopts opts) +-cdef int MPF_pow(MPF *z, MPF *x, MPF *y, MPopts opts) except -1 +-cdef MPF_complex_pow(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *yre, MPF *yim, MPopts opts) +-cdef MPF_hypsum(MPF *a, MPF *b, int p, int q, param_types, str ztype, coeffs, \ +- z, long prec, long wp, long epsshift, dict magnitude_check, kwargs) +diff --git a/src/sage/libs/mpmath/ext_impl.pyx b/src/sage/libs/mpmath/ext_impl.pyx +deleted file mode 100644 +index fb078719ac0..00000000000 +--- a/src/sage/libs/mpmath/ext_impl.pyx ++++ /dev/null +@@ -1,2284 +0,0 @@ +-""" +-This module provides the core implementation of multiprecision +-floating-point arithmetic. Operations are done in-place. +- +-TESTS: +- +-See if :issue:`15118` is fixed:: +- +- sage: import mpmath +- sage: mpmath.mpf(0)^(-2) +- Traceback (most recent call last): +- ... +- ZeroDivisionError +- sage: mpmath.zeta(2r, -3r) +- Traceback (most recent call last): +- ... +- ZeroDivisionError +-""" +- +-#***************************************************************************** +-# 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 2 of the License, or +-# (at your option) any later version. +-# http://www.gnu.org/licenses/ +-#***************************************************************************** +- +-from cpython.long cimport * +-from cpython.float cimport * +-from cpython.complex cimport * +-from cpython.number cimport * +- +-from libc.math cimport sqrt as fsqrt +-from libc.math cimport frexp +- +-from cysignals.signals cimport sig_check +- +-from sage.ext.stdsage cimport PY_NEW +-from sage.libs.gmp.all cimport * +-from sage.libs.mpfr cimport * +-from sage.rings.integer cimport Integer +- +-from sage.libs.gmp.pylong cimport * +- +-cdef mpz_set_integer(mpz_t v, x): +- if isinstance(x, int): +- mpz_set_pylong(v, x) +- elif isinstance(x, Integer): +- mpz_set(v, (x).value) +- else: +- raise TypeError("cannot convert %s to an integer" % x) +- +-cdef inline void mpz_add_si(mpz_t a, mpz_t b, long x) noexcept: +- if x >= 0: +- mpz_add_ui(a, b, x) +- else: +- # careful: overflow when negating LONG_MIN +- mpz_sub_ui(a, b, -x) +- +-cdef inline mpzi(mpz_t n): +- return mpz_get_pyintlong(n) +- +-cdef inline mpzl(mpz_t n): +- return mpz_get_pylong(n) +- +-# This should be done better +-cdef int mpz_tstbit_abs(mpz_t z, unsigned long bit_index) noexcept: +- cdef int res +- if mpz_sgn(z) < 0: +- mpz_neg(z, z) +- res = mpz_tstbit(z, bit_index) +- mpz_neg(z, z) +- else: +- res = mpz_tstbit(z, bit_index) +- return res +- +-cdef void mpz_set_fixed(mpz_t t, MPF *x, int prec, bint abs=False) noexcept: +- """ +- Set t = x, or t = |x|, as a fixed-point number with prec bits. +- """ +- cdef int offset +- offset = mpz_get_si(x.exp) + prec +- if offset >= 0: +- mpz_mul_2exp(t, x.man, offset) +- else: +- mpz_tdiv_q_2exp(t, x.man, -offset) +- if abs: +- mpz_abs(t, t) +- +-cdef unsigned long mpz_bitcount(mpz_t z) noexcept: +- if mpz_sgn(z) == 0: +- return 0 +- return mpz_sizeinbase(z, 2) +- +-# The following limits allowed exponent shifts. We could use mpz_fits_slong_p, +-# but then (-LONG_MIN) wraps around; we may also not be able to add large +-# shifts safely. A higher limit could be used on 64-bit systems, but +-# it is unlikely that anyone will run into this (adding numbers +-# that differ by 2^(2^30), at precisions of 2^30 bits). +- +-# Note: MPFR's emax is 1073741823 +-DEF MAX_SHIFT = 536870912 # 2^29 +- +-cdef int mpz_reasonable_shift(mpz_t z) noexcept: +- if mpz_sgn(z) > 0: +- return mpz_cmp_ui(z, MAX_SHIFT) < 0 +- else: +- return mpz_cmp_si(z, -MAX_SHIFT) > 0 +- +-DEF ROUND_N = 0 +-DEF ROUND_F = 1 +-DEF ROUND_C = 2 +-DEF ROUND_D = 3 +-DEF ROUND_U = 4 +- +-DEF S_NORMAL = 0 +-DEF S_ZERO = 1 +-DEF S_NZERO = 2 +-DEF S_INF = 3 +-DEF S_NINF = 4 +-DEF S_NAN = 5 +- +-cdef inline str rndmode_to_python(int rnd): +- if rnd == ROUND_N: return 'n' +- if rnd == ROUND_F: return 'f' +- if rnd == ROUND_C: return 'c' +- if rnd == ROUND_D: return 'd' +- if rnd == ROUND_U: return 'u' +- +-cdef inline rndmode_from_python(str rnd): +- if rnd == 'n': return ROUND_N +- if rnd == 'f': return ROUND_F +- if rnd == 'c': return ROUND_C +- if rnd == 'd': return ROUND_D +- if rnd == 'u': return ROUND_U +- +-cdef inline mpfr_rnd_t rndmode_to_mpfr(int rnd) noexcept: +- if rnd == ROUND_N: return MPFR_RNDN +- if rnd == ROUND_F: return MPFR_RNDD +- if rnd == ROUND_C: return MPFR_RNDU +- if rnd == ROUND_D: return MPFR_RNDZ +- if rnd == ROUND_U: return MPFR_RNDA +- +-cdef inline int reciprocal_rnd(int rnd) noexcept: +- if rnd == ROUND_N: return ROUND_N +- if rnd == ROUND_D: return ROUND_U +- if rnd == ROUND_U: return ROUND_D +- if rnd == ROUND_C: return ROUND_F +- if rnd == ROUND_F: return ROUND_C +- +-cdef MPopts opts_exact +-cdef MPopts opts_double_precision +-cdef MPopts opts_mini_prec +- +-opts_exact.prec = 0 +-opts_exact.rounding = ROUND_N +-opts_double_precision.prec = 53 +-opts_double_precision.rounding = ROUND_N +-opts_mini_prec.prec = 5 +-opts_mini_prec.rounding = ROUND_D +- +-cdef double _double_inf = float("1e300") * float("1e300") +-cdef double _double_ninf = -_double_inf +-cdef double _double_nan = _double_inf - _double_inf +- +-cdef inline void MPF_init(MPF *x) noexcept: +- """Allocate space and set value to zero. +- Must be called exactly once when creating a new MPF.""" +- x.special = S_ZERO +- mpz_init(x.man) +- mpz_init(x.exp) +- +-cdef inline void MPF_clear(MPF *x) noexcept: +- """Deallocate space. Must be called exactly once when finished with an MPF.""" +- mpz_clear(x.man) +- mpz_clear(x.exp) +- +-cdef inline void MPF_set(MPF *dest, MPF *src) noexcept: +- """Clone MPF value. Assumes source value is already normalized.""" +- if src is dest: +- return +- dest.special = src.special +- mpz_set(dest.man, src.man) +- mpz_set(dest.exp, src.exp) +- +-cdef inline void MPF_set_zero(MPF *x) noexcept: +- """Set value to 0.""" +- x.special = S_ZERO +- +-cdef inline void MPF_set_one(MPF *x) noexcept: +- """Set value to 1.""" +- x.special = S_NORMAL +- mpz_set_ui(x.man, 1) +- mpz_set_ui(x.exp, 0) +- +-cdef inline void MPF_set_nan(MPF *x) noexcept: +- """Set value to NaN (not a number).""" +- x.special = S_NAN +- +-cdef inline void MPF_set_inf(MPF *x) noexcept: +- """Set value to +infinity.""" +- x.special = S_INF +- +-cdef inline void MPF_set_ninf(MPF *x) noexcept: +- """Set value to -infinity.""" +- x.special = S_NINF +- +-cdef MPF_set_si(MPF *x, long n): +- """Set value to that of a given C (long) integer.""" +- if n: +- x.special = S_NORMAL +- mpz_set_si(x.man, n) +- mpz_set_ui(x.exp, 0) +- MPF_normalize(x, opts_exact) +- else: +- MPF_set_zero(x) +- +-cdef MPF_set_int(MPF *x, n): +- """Set value to that of a given Python integer.""" +- x.special = S_NORMAL +- mpz_set_integer(x.man, n) +- if mpz_sgn(x.man): +- mpz_set_ui(x.exp, 0) +- MPF_normalize(x, opts_exact) +- else: +- MPF_set_zero(x) +- +-cdef MPF_set_man_exp(MPF *x, man, exp): +- """ +- Set value to man*2^exp where man, exp may be of any appropriate +- Python integer types. +- """ +- x.special = S_NORMAL +- mpz_set_integer(x.man, man) +- mpz_set_integer(x.exp, exp) +- MPF_normalize(x, opts_exact) +- +- +-# Temporary variables. Note: not thread-safe. +-# Used by MPF_add/MPF_sub/MPF_div +-cdef mpz_t tmp_exponent +-mpz_init(tmp_exponent) +-cdef MPF tmp0 +-MPF_init(&tmp0) +- +-# Used by MPF_hypot and MPF_cmp, which may call MPF_add/MPF_sub +-cdef MPF tmp1 +-MPF_init(&tmp1) +-cdef MPF tmp2 +-MPF_init(&tmp2) +- +- +-# Constants needed in a few places +-cdef MPF MPF_C_1 +-MPF_init(&MPF_C_1) +-MPF_set_si(&MPF_C_1, 1) +-cdef Integer MPZ_ZERO = Integer(0) +-cdef tuple _mpf_fzero = (0, MPZ_ZERO, 0, 0) +-cdef tuple _mpf_fnan = (0, MPZ_ZERO, -123, -1) +-cdef tuple _mpf_finf = (0, MPZ_ZERO, -456, -2) +-cdef tuple _mpf_fninf = (1, MPZ_ZERO, -789, -3) +- +-cdef MPF_set_tuple(MPF *x, tuple value): +- """ +- Set value of an MPF to that of a normalized (sign, man, exp, bc) tuple +- in the format used by mpmath.libmp. +- """ +- #cdef int sign +- cdef Integer man +- sign, _man, exp, _ = value +- if isinstance(_man, Integer): +- man = _man +- else: +- # This is actually very unlikely; it should never happen +- # in internal code that man isn't an Integer. Maybe the check +- # can be avoided by doing checks in e.g. MPF_set_any? +- man = Integer(_man) +- if mpz_sgn(man.value): +- MPF_set_man_exp(x, man, exp) +- if sign: +- mpz_neg(x.man, x.man) +- return +- if value == _mpf_fzero: +- MPF_set_zero(x) +- elif value == _mpf_finf: +- MPF_set_inf(x) +- elif value == _mpf_fninf: +- MPF_set_ninf(x) +- else: +- MPF_set_nan(x) +- +-cdef MPF_to_tuple(MPF *x): +- """Convert MPF value to (sign, man, exp, bc) tuple.""" +- cdef Integer man +- if x.special: +- if x.special == S_ZERO: return _mpf_fzero +- #if x.special == S_NZERO: return _mpf_fnzero +- if x.special == S_INF: return _mpf_finf +- if x.special == S_NINF: return _mpf_fninf +- return _mpf_fnan +- man = PY_NEW(Integer) +- if mpz_sgn(x.man) < 0: +- mpz_neg(man.value, x.man) +- sign = 1 +- else: +- mpz_set(man.value, x.man) +- sign = 0 +- exp = mpz_get_pyintlong(x.exp) +- bc = mpz_sizeinbase(x.man, 2) +- return (sign, man, exp, bc) +- +-cdef MPF_set_double(MPF *r, double x): +- """ +- Set r to the value of a C double x. +- """ +- cdef int exp +- cdef double man +- if x != x: +- MPF_set_nan(r) +- return +- if x == _double_inf: +- MPF_set_inf(r) +- return +- if x == _double_ninf: +- MPF_set_ninf(r) +- return +- man = frexp(x, &exp) +- man *= 9007199254740992.0 +- mpz_set_d(r.man, man) +- mpz_set_si(r.exp, exp-53) +- r.special = S_NORMAL +- MPF_normalize(r, opts_exact) +- +-import math as pymath +- +-# TODO: implement this function safely without using the Python math module +-cdef double MPF_to_double(MPF *x, bint strict) noexcept: +- """Convert MPF value to a Python float.""" +- if x.special == S_NORMAL: +- man = mpzi(x.man) +- exp = mpzi(x.exp) +- bc = mpz_sizeinbase(x.man, 2) +- try: +- if bc < 100: +- return pymath.ldexp(man, exp) +- # Try resizing the mantissa. Overflow may still happen here. +- n = bc - 53 +- m = man >> n +- return pymath.ldexp(m, exp + n) +- except OverflowError: +- if strict: +- raise +- # Overflow to infinity +- if exp + bc > 0: +- if man < 0: +- return _double_ninf +- else: +- return _double_inf +- # Underflow to zero +- return 0.0 +- if x.special == S_ZERO: +- return 0.0 +- if x.special == S_INF: +- return _double_inf +- if x.special == S_NINF: +- return _double_ninf +- return _double_nan +- +-cdef MPF_to_fixed(mpz_t r, MPF *x, long prec, bint truncate): +- """ +- Set r = x, r being in the format of a fixed-point number with prec bits. +- Floor division is used unless truncate=True in which case +- truncating division is used. +- """ +- cdef long shift +- if x.special: +- if x.special == S_ZERO or x.special == S_NZERO: +- mpz_set_ui(r, 0) +- return +- raise ValueError("cannot create fixed-point number from special value") +- if mpz_reasonable_shift(x.exp): +- # XXX: signed integer overflow +- shift = mpz_get_si(x.exp) + prec +- if shift >= 0: +- mpz_mul_2exp(r, x.man, shift) +- else: +- if truncate: +- mpz_tdiv_q_2exp(r, x.man, -shift) +- else: +- mpz_fdiv_q_2exp(r, x.man, -shift) +- return +- # Underflow +- if mpz_sgn(x.exp) < 0: +- mpz_set_ui(r, 0) +- return +- raise OverflowError("cannot convert huge number to fixed-point format") +- +-cdef int MPF_sgn(MPF *x) noexcept: +- """ +- Give the sign of an MPF (-1, 0, or 1). +- """ +- if x.special: +- if x.special == S_INF: +- return 1 +- if x.special == S_NINF: +- return -1 +- return 0 +- return mpz_sgn(x.man) +- +-cdef void MPF_neg(MPF *r, MPF *s) noexcept: +- """ +- Set r = -s. MPF_neg(x, x) negates in place. +- """ +- if s.special: +- if s.special == S_ZERO: +- r.special = S_ZERO # r.special = S_NZERO +- elif s.special == S_NZERO: +- r.special = S_ZERO +- elif s.special == S_INF: +- r.special = S_NINF +- elif s.special == S_NINF: +- r.special = S_INF +- else: +- r.special = s.special +- return +- r.special = s.special +- mpz_neg(r.man, s.man) +- if r is not s: +- mpz_set(r.exp, s.exp) +- +-cdef void MPF_abs(MPF *r, MPF *s) noexcept: +- """ +- Set r = abs(s). MPF_abs(r, r) sets the absolute value in place. +- """ +- if s.special: +- if s.special == S_NINF: +- r.special = S_INF +- else: +- r.special = s.special +- return +- r.special = s.special +- mpz_abs(r.man, s.man) +- if r is not s: +- mpz_set(r.exp, s.exp) +- +-cdef MPF_normalize(MPF *x, MPopts opts): +- """ +- Normalize. +- +- With prec = 0, trailing zero bits are stripped but no rounding +- is performed. +- """ +- cdef int sign +- cdef long trail, bc, shift +- if x.special != S_NORMAL: +- return +- sign = mpz_sgn(x.man) +- if sign == 0: +- x.special = S_ZERO +- mpz_set_ui(x.exp, 0) +- return +- bc = mpz_sizeinbase(x.man, 2) +- shift = bc - opts.prec +- # Ok if mantissa small and no trailing zero bits +- if (shift <= 0 or not opts.prec) and mpz_odd_p(x.man): +- return +- # Mantissa is too large, so divide by appropriate power of 2 +- # Need to be careful about rounding +- if shift > 0 and opts.prec: +- if opts.rounding == ROUND_N: +- if mpz_tstbit_abs(x.man, shift-1): +- if mpz_tstbit_abs(x.man, shift) or mpz_scan1(x.man, 0) < (shift-1): +- if sign < 0: +- mpz_fdiv_q_2exp(x.man, x.man, shift) +- else: +- mpz_cdiv_q_2exp(x.man, x.man, shift) +- else: +- mpz_tdiv_q_2exp(x.man, x.man, shift) +- else: +- mpz_tdiv_q_2exp(x.man, x.man, shift) +- elif opts.rounding == ROUND_D: +- mpz_tdiv_q_2exp(x.man, x.man, shift) +- elif opts.rounding == ROUND_F: +- mpz_fdiv_q_2exp(x.man, x.man, shift) +- elif opts.rounding == ROUND_C: +- mpz_cdiv_q_2exp(x.man, x.man, shift) +- elif opts.rounding == ROUND_U: +- if sign < 0: +- mpz_fdiv_q_2exp(x.man, x.man, shift) +- else: +- mpz_cdiv_q_2exp(x.man, x.man, shift) +- else: +- raise ValueError("bad rounding mode") +- else: +- shift = 0 +- # Strip trailing bits +- trail = mpz_scan1(x.man, 0) +- if 0 < trail < bc: +- mpz_tdiv_q_2exp(x.man, x.man, trail) +- shift += trail +- mpz_add_si(x.exp, x.exp, shift) +- +-cdef void MPF_pos(MPF *x, MPF *y, MPopts opts) noexcept: +- """ +- Set x = +y (i.e. copy the value, and round if the +- working precision is smaller than the width +- of the mantissa of y). +- """ +- MPF_set(x, y) +- MPF_normalize(x, opts) +- +-cdef void _add_special(MPF *r, MPF *s, MPF *t) noexcept: +- if s.special == S_ZERO: +- # (+0) + (-0) = +0 +- if t.special == S_NZERO: +- MPF_set(r, s) +- # (+0) + x = x +- else: +- MPF_set(r, t) +- elif t.special == S_ZERO: +- # (-0) + (+0) = +0 +- if s.special == S_NZERO: +- MPF_set(r, t) +- # x + (+0) = x +- else: +- MPF_set(r, s) +- # (+/- 0) + x = x +- elif s.special == S_NZERO: +- MPF_set(r, t) +- elif t.special == S_NZERO: +- MPF_set(r, s) +- # (+/- inf) + (-/+ inf) = nan +- elif ((s.special == S_INF and t.special == S_NINF) or +- (s.special == S_NINF and t.special == S_INF)): +- MPF_set_nan(r) +- # nan or +/- inf trumps any finite number +- elif s.special == S_NAN or t.special == S_NAN: +- MPF_set_nan(r) +- elif s.special: +- MPF_set(r, s) +- else: +- MPF_set(r, t) +- return +- +-cdef void _sub_special(MPF *r, MPF *s, MPF *t) noexcept: +- if s.special == S_ZERO: +- # (+0) - (+/-0) = (+0) +- if t.special == S_NZERO: +- MPF_set(r, s) +- else: +- # (+0) - x = (-x) +- MPF_neg(r, t) +- elif t.special == S_ZERO: +- # x - (+0) = x; also covers (-0) - (+0) = (-0) +- MPF_set(r, s) +- # (-0) - x = x +- elif s.special == S_NZERO: +- # (-0) - (-0) = (+0) +- if t.special == S_NZERO: +- MPF_set_zero(r) +- # (-0) - x = -x +- else: +- MPF_neg(r, t) +- elif t.special == S_NZERO: +- # x - (-0) = x +- MPF_set(r, s) +- # (+/- inf) - (+/- inf) = nan +- elif ((s.special == S_INF and t.special == S_INF) or +- (s.special == S_NINF and t.special == S_NINF)): +- MPF_set_nan(r) +- elif s.special == S_NAN or t.special == S_NAN: +- MPF_set_nan(r) +- # nan - x or (+/-inf) - x = l.h.s +- elif s.special: +- MPF_set(r, s) +- # x - nan or x - (+/-inf) = (- r.h.s) +- else: +- MPF_neg(r, t) +- +-cdef void _mul_special(MPF *r, MPF *s, MPF *t) noexcept: +- if s.special == S_ZERO: +- if t.special == S_NORMAL or t.special == S_ZERO: +- MPF_set(r, s) +- elif t.special == S_NZERO: +- MPF_set(r, t) +- else: +- MPF_set_nan(r) +- elif t.special == S_ZERO: +- if s.special == S_NORMAL: +- MPF_set(r, t) +- elif s.special == S_NZERO: +- MPF_set(r, s) +- else: +- MPF_set_nan(r) +- elif s.special == S_NZERO: +- if t.special == S_NORMAL: +- if mpz_sgn(t.man) < 0: +- MPF_set_zero(r) +- else: +- MPF_set(r, s) +- else: +- MPF_set_nan(r) +- elif t.special == S_NZERO: +- if s.special == S_NORMAL: +- if mpz_sgn(s.man) < 0: +- MPF_set_zero(r) +- else: +- MPF_set(r, t) +- else: +- MPF_set_nan(r) +- elif s.special == S_NAN or t.special == S_NAN: +- MPF_set_nan(r) +- else: +- if MPF_sgn(s) == MPF_sgn(t): +- MPF_set_inf(r) +- else: +- MPF_set_ninf(r) +- +-cdef _div_special(MPF *r, MPF *s, MPF *t): +- # TODO: handle signed zeros correctly +- if s.special == S_NAN or t.special == S_NAN: +- MPF_set_nan(r) +- elif t.special == S_ZERO or t.special == S_NZERO: +- raise ZeroDivisionError +- elif s.special == S_ZERO or s.special == S_NZERO: +- MPF_set_zero(r) +- elif s.special == S_NORMAL: +- MPF_set_zero(r) +- elif s.special == S_INF or s.special == S_NINF: +- if t.special == S_INF or t.special == S_NINF: +- MPF_set_nan(r) +- elif MPF_sgn(s) == MPF_sgn(t): +- MPF_set_inf(r) +- else: +- MPF_set_ninf(r) +- # else: +- elif t.special == S_INF or t.special == S_NINF: +- MPF_set_zero(r) +- +-cdef _add_perturbation(MPF *r, MPF *s, int sign, MPopts opts): +- cdef long shift +- if opts.rounding == ROUND_N: +- MPF_set(r, s) +- else: +- shift = opts.prec - mpz_sizeinbase(s.man, 2) + 8 +- if shift < 0: +- shift = 8 +- mpz_mul_2exp(r.man, s.man, shift) +- mpz_add_si(r.man, r.man, sign) +- mpz_sub_ui(r.exp, s.exp, shift) +- MPF_normalize(r, opts) +- +-cdef MPF_add(MPF *r, MPF *s, MPF *t, MPopts opts): +- """ +- Set r = s + t, with exact rounding. +- +- With prec = 0, the addition is performed exactly. Note that this +- may cause overflow if the exponents are huge. +- """ +- cdef long shift, sbc, tbc +- #assert (r is not s) and (r is not t) +- if s.special or t.special: +- _add_special(r, s, t) +- return +- r.special = S_NORMAL +- # Difference between exponents +- mpz_sub(tmp_exponent, s.exp, t.exp) +- if mpz_reasonable_shift(tmp_exponent): +- shift = mpz_get_si(tmp_exponent) +- if shift >= 0: +- # |s| >> |t| +- if shift > 2*opts.prec and opts.prec: +- sbc = mpz_sizeinbase(s.man, 2) +- tbc = mpz_sizeinbase(t.man, 2) +- if shift + sbc - tbc > opts.prec+8: +- _add_perturbation(r, s, mpz_sgn(t.man), opts) +- return +- # |s| > |t| +- mpz_mul_2exp(tmp0.man, s.man, shift) +- mpz_add(r.man, tmp0.man, t.man) +- mpz_set(r.exp, t.exp) +- MPF_normalize(r, opts) +- elif shift < 0: +- shift = -shift +- # |s| << |t| +- if shift > 2*opts.prec and opts.prec: +- sbc = mpz_sizeinbase(s.man, 2) +- tbc = mpz_sizeinbase(t.man, 2) +- if shift + tbc - sbc > opts.prec+8: +- _add_perturbation(r, t, mpz_sgn(s.man), opts) +- return +- # |s| < |t| +- mpz_mul_2exp(tmp0.man, t.man, shift) +- mpz_add(r.man, tmp0.man, s.man) +- mpz_set(r.exp, s.exp) +- MPF_normalize(r, opts) +- else: +- if not opts.prec: +- raise OverflowError("the exact result does not fit in memory") +- # |s| >>> |t| +- if mpz_sgn(tmp_exponent) > 0: +- _add_perturbation(r, s, mpz_sgn(t.man), opts) +- # |s| <<< |t| +- else: +- _add_perturbation(r, t, mpz_sgn(s.man), opts) +- +-cdef MPF_sub(MPF *r, MPF *s, MPF *t, MPopts opts): +- """ +- Set r = s - t, with exact rounding. +- +- With prec = 0, the addition is performed exactly. Note that this +- may cause overflow if the exponents are huge. +- """ +- cdef long shift, sbc, tbc +- #assert (r is not s) and (r is not t) +- if s.special or t.special: +- _sub_special(r, s, t) +- return +- r.special = S_NORMAL +- # Difference between exponents +- mpz_sub(tmp_exponent, s.exp, t.exp) +- if mpz_reasonable_shift(tmp_exponent): +- shift = mpz_get_si(tmp_exponent) +- if shift >= 0: +- # |s| >> |t| +- if shift > 2*opts.prec and opts.prec: +- sbc = mpz_sizeinbase(s.man, 2) +- tbc = mpz_sizeinbase(t.man, 2) +- if shift + sbc - tbc > opts.prec+8: +- _add_perturbation(r, s, -mpz_sgn(t.man), opts) +- return +- # |s| > |t| +- mpz_mul_2exp(tmp0.man, s.man, shift) +- mpz_sub(r.man, tmp0.man, t.man) +- mpz_set(r.exp, t.exp) +- MPF_normalize(r, opts) +- elif shift < 0: +- shift = -shift +- # |s| << |t| +- if shift > 2*opts.prec and opts.prec: +- sbc = mpz_sizeinbase(s.man, 2) +- tbc = mpz_sizeinbase(t.man, 2) +- if shift + tbc - sbc > opts.prec+8: +- _add_perturbation(r, t, -mpz_sgn(s.man), opts) +- MPF_neg(r, r) +- return +- # |s| < |t| +- mpz_mul_2exp(tmp0.man, t.man, shift) +- mpz_sub(r.man, s.man, tmp0.man) +- mpz_set(r.exp, s.exp) +- MPF_normalize(r, opts) +- else: +- if not opts.prec: +- raise OverflowError("the exact result does not fit in memory") +- # |s| >>> |t| +- if mpz_sgn(tmp_exponent) > 0: +- _add_perturbation(r, s, -mpz_sgn(t.man), opts) +- # |s| <<< |t| +- else: +- _add_perturbation(r, t, -mpz_sgn(s.man), opts) +- MPF_neg(r, r) +- +-cdef bint MPF_eq(MPF *s, MPF *t) noexcept: +- """ +- Evaluates s == t. +- """ +- if s.special == S_NAN or t.special == S_NAN: +- return False +- if s.special == t.special: +- if s.special == S_NORMAL: +- return (mpz_cmp(s.man, t.man) == 0) and (mpz_cmp(s.exp, t.exp) == 0) +- else: +- return True +- return False +- +-cdef bint MPF_ne(MPF *s, MPF *t) noexcept: +- """ +- Evaluates s != t. +- """ +- if s.special == S_NAN or t.special == S_NAN: +- return True +- if s.special == S_NORMAL and t.special == S_NORMAL: +- return (mpz_cmp(s.man, t.man) != 0) or (mpz_cmp(s.exp, t.exp) != 0) +- return s.special != t.special +- +-cdef int MPF_cmp(MPF *s, MPF *t) noexcept: +- """ +- Evaluates cmp(s,t). Conventions for nan follow those +- of the mpmath.libmp function. +- """ +- cdef long sbc, tbc +- cdef int cm +- if MPF_eq(s, t): +- return 0 +- if s.special != S_NORMAL or t.special != S_NORMAL: +- if s.special == S_ZERO: return -MPF_sgn(t) +- if t.special == S_ZERO: return MPF_sgn(s) +- if t.special == S_NAN: return 1 +- if s.special == S_INF: return 1 +- if t.special == S_NINF: return 1 +- return -1 +- if mpz_sgn(s.man) != mpz_sgn(t.man): +- if mpz_sgn(s.man) < 0: +- return -1 +- else: +- return 1 +- if not mpz_cmp(s.exp, t.exp): +- return mpz_cmp(s.man, t.man) +- mpz_add_ui(tmp1.exp, s.exp, mpz_sizeinbase(s.man, 2)) +- mpz_add_ui(tmp2.exp, t.exp, mpz_sizeinbase(t.man, 2)) +- cm = mpz_cmp(tmp1.exp, tmp2.exp) +- if mpz_sgn(s.man) < 0: +- if cm < 0: return 1 +- if cm > 0: return -1 +- else: +- if cm < 0: return -1 +- if cm > 0: return 1 +- MPF_sub(&tmp1, s, t, opts_mini_prec) +- return MPF_sgn(&tmp1) +- +-cdef bint MPF_lt(MPF *s, MPF *t) noexcept: +- """ +- Evaluates s < t. +- """ +- if s.special == S_NAN or t.special == S_NAN: +- return False +- return MPF_cmp(s, t) < 0 +- +-cdef bint MPF_le(MPF *s, MPF *t) noexcept: +- """ +- Evaluates s <= t. +- """ +- if s.special == S_NAN or t.special == S_NAN: +- return False +- return MPF_cmp(s, t) <= 0 +- +-cdef bint MPF_gt(MPF *s, MPF *t) noexcept: +- """ +- Evaluates s > t. +- """ +- if s.special == S_NAN or t.special == S_NAN: +- return False +- return MPF_cmp(s, t) > 0 +- +-cdef bint MPF_ge(MPF *s, MPF *t) noexcept: +- """ +- Evaluates s >= t. +- """ +- if s.special == S_NAN or t.special == S_NAN: +- return False +- return MPF_cmp(s, t) >= 0 +- +-cdef MPF_mul(MPF *r, MPF *s, MPF *t, MPopts opts): +- """ +- Set r = s * t, with correct rounding. +- +- With prec = 0, the multiplication is performed exactly, +- i.e. no rounding is performed. +- """ +- if s.special or t.special: +- _mul_special(r, s, t) +- else: +- r.special = S_NORMAL +- mpz_mul(r.man, s.man, t.man) +- mpz_add(r.exp, s.exp, t.exp) +- if opts.prec: +- MPF_normalize(r, opts) +- +-cdef MPF_div(MPF *r, MPF *s, MPF *t, MPopts opts): +- """ +- Set r = s / t, with correct rounding. +- """ +- cdef int sign +- cdef long sbc, tbc, extra +- cdef mpz_t rem +- #assert (r is not s) and (r is not t) +- if s.special or t.special: +- _div_special(r, s, t) +- return +- r.special = S_NORMAL +- # Division by a power of two <=> shift exponents +- if mpz_cmp_si(t.man, 1) == 0: +- MPF_set(&tmp0, s) +- mpz_sub(tmp0.exp, tmp0.exp, t.exp) +- MPF_normalize(&tmp0, opts) +- MPF_set(r, &tmp0) +- return +- elif mpz_cmp_si(t.man, -1) == 0: +- MPF_neg(&tmp0, s) +- mpz_sub(tmp0.exp, tmp0.exp, t.exp) +- MPF_normalize(&tmp0, opts) +- MPF_set(r, &tmp0) +- return +- sign = mpz_sgn(s.man) != mpz_sgn(t.man) +- # Same strategy as for addition: if there is a remainder, perturb +- # the result a few bits outside the precision range before rounding +- extra = opts.prec - mpz_sizeinbase(s.man,2) + mpz_sizeinbase(t.man,2) + 5 +- if extra < 5: +- extra = 5 +- mpz_init(rem) +- mpz_mul_2exp(tmp0.man, s.man, extra) +- mpz_tdiv_qr(r.man, rem, tmp0.man, t.man) +- if mpz_sgn(rem): +- mpz_mul_2exp(r.man, r.man, 1) +- if sign: +- mpz_sub_ui(r.man, r.man, 1) +- else: +- mpz_add_ui(r.man, r.man, 1) +- extra += 1 +- mpz_clear(rem) +- mpz_sub(r.exp, s.exp, t.exp) +- mpz_sub_ui(r.exp, r.exp, extra) +- MPF_normalize(r, opts) +- +-cdef int MPF_sqrt(MPF *r, MPF *s, MPopts opts) noexcept: +- """ +- Set r = sqrt(s), with correct rounding. +- """ +- cdef long shift +- cdef mpz_t rem +- #assert r is not s +- if s.special: +- if s.special == S_ZERO or s.special == S_INF: +- MPF_set(r, s) +- else: +- MPF_set_nan(r) +- return 0 +- if mpz_sgn(s.man) < 0: +- MPF_set_nan(r) +- return 1 +- r.special = S_NORMAL +- if mpz_odd_p(s.exp): +- mpz_sub_ui(r.exp, s.exp, 1) +- mpz_mul_2exp(r.man, s.man, 1) +- elif mpz_cmp_ui(s.man, 1) == 0: +- # Square of a power of two +- mpz_set_ui(r.man, 1) +- mpz_tdiv_q_2exp(r.exp, s.exp, 1) +- MPF_normalize(r, opts) +- return 0 +- else: +- mpz_set(r.man, s.man) +- mpz_set(r.exp, s.exp) +- shift = 2*opts.prec - mpz_sizeinbase(r.man,2) + 4 +- if shift < 4: +- shift = 4 +- shift += shift & 1 +- mpz_mul_2exp(r.man, r.man, shift) +- if opts.rounding == ROUND_F or opts.rounding == ROUND_D: +- mpz_sqrt(r.man, r.man) +- else: +- mpz_init(rem) +- mpz_sqrtrem(r.man, rem, r.man) +- if mpz_sgn(rem): +- mpz_mul_2exp(r.man, r.man, 1) +- mpz_add_ui(r.man, r.man, 1) +- shift += 2 +- mpz_clear(rem) +- mpz_add_si(r.exp, r.exp, -shift) +- mpz_tdiv_q_2exp(r.exp, r.exp, 1) +- MPF_normalize(r, opts) +- return 0 +- +-cdef MPF_hypot(MPF *r, MPF *a, MPF *b, MPopts opts): +- """ +- Set r = sqrt(a^2 + b^2) +- """ +- cdef MPopts tmp_opts +- if a.special == S_ZERO: +- MPF_abs(r, b) +- MPF_normalize(r, opts) +- return +- if b.special == S_ZERO: +- MPF_abs(r, a) +- MPF_normalize(r, opts) +- return +- tmp_opts = opts +- tmp_opts.prec += 30 +- MPF_mul(&tmp1, a, a, opts_exact) +- MPF_mul(&tmp2, b, b, opts_exact) +- MPF_add(r, &tmp1, &tmp2, tmp_opts) +- MPF_sqrt(r, r, opts) +- +-cdef MPF_pow_int(MPF *r, MPF *x, mpz_t n, MPopts opts): +- """ +- Set r = x ** n. Currently falls back to mpmath.libmp +- unless n is tiny. +- """ +- cdef long m, absm +- cdef unsigned long bc +- cdef int nsign +- if x.special != S_NORMAL: +- nsign = mpz_sgn(n) +- if x.special == S_ZERO: +- if nsign < 0: +- raise ZeroDivisionError +- elif nsign == 0: +- MPF_set(r, &MPF_C_1) +- else: +- MPF_set_zero(r) +- elif x.special == S_INF: +- if nsign > 0: +- MPF_set(r, x) +- elif nsign == 0: +- MPF_set_nan(r) +- else: +- MPF_set_zero(r) +- elif x.special == S_NINF: +- if nsign > 0: +- if mpz_odd_p(n): +- MPF_set(r, x) +- else: +- MPF_neg(r, x) +- elif nsign == 0: +- MPF_set_nan(r) +- else: +- MPF_set_zero(r) +- else: +- MPF_set_nan(r) +- return +- bc = mpz_sizeinbase(r.man,2) +- r.special = S_NORMAL +- if mpz_reasonable_shift(n): +- m = mpz_get_si(n) +- if m == 0: +- MPF_set(r, &MPF_C_1) +- return +- if m == 1: +- MPF_set(r, x) +- MPF_normalize(r, opts) +- return +- if m == 2: +- MPF_mul(r, x, x, opts) +- return +- if m == -1: +- MPF_div(r, &MPF_C_1, x, opts) +- return +- if m == -2: +- MPF_mul(r, x, x, opts_exact) +- MPF_div(r, &MPF_C_1, r, opts) +- return +- absm = abs(m) +- if bc * absm < 10000: +- mpz_pow_ui(r.man, x.man, absm) +- mpz_mul_ui(r.exp, x.exp, absm) +- if m < 0: +- MPF_div(r, &MPF_C_1, r, opts) +- else: +- MPF_normalize(r, opts) +- return +- r.special = S_NORMAL +- # (2^p)^n +- if mpz_cmp_si(x.man, 1) == 0: +- mpz_set(r.man, x.man) +- mpz_mul(r.exp, x.exp, n) +- return +- # (-2^p)^n +- if mpz_cmp_si(x.man, -1) == 0: +- if mpz_odd_p(n): +- mpz_set(r.man, x.man) +- else: +- mpz_neg(r.man, x.man) +- mpz_mul(r.exp, x.exp, n) +- return +- # TODO: implement efficiently here +- import mpmath.libmp +- MPF_set_tuple(r, +- mpmath.libmp.mpf_pow_int(MPF_to_tuple(x), mpzi(n), +- opts.prec, rndmode_to_python(opts.rounding))) +- +-cdef mpz_t _pi_value +-cdef int _pi_prec = -1 +- +-cdef mpz_t _ln2_value +-cdef int _ln2_prec = -1 +- +-cdef mpz_set_pi(mpz_t x, int prec): +- """ +- Set x = pi as a fixed-point number. +- """ +- global _pi_value +- global _pi_prec +- if prec <= _pi_prec: +- mpz_tdiv_q_2exp(x, _pi_value, _pi_prec-prec) +- else: +- from mpmath.libmp import pi_fixed +- if _pi_prec < 0: +- mpz_init(_pi_value) +- mpz_set_integer(_pi_value, pi_fixed(prec)) +- mpz_set(x, _pi_value) +- _pi_prec = prec +- +-cdef mpz_set_ln2(mpz_t x, int prec): +- """ +- Set x = ln(2) as a fixed-point number. +- """ +- global _ln2_value +- global _ln2_prec +- if prec <= _ln2_prec: +- mpz_tdiv_q_2exp(x, _ln2_value, _ln2_prec-prec) +- else: +- from mpmath.libmp import ln2_fixed +- if _ln2_prec < 0: +- mpz_init(_ln2_value) +- mpz_set_integer(_ln2_value, ln2_fixed(prec)) +- mpz_set(x, _ln2_value) +- _ln2_prec = prec +- +-cdef void _cy_exp_mpfr(mpz_t y, mpz_t x, int prec) noexcept: +- """ +- Compute y = exp(x) for fixed-point numbers y and x using MPFR, +- assuming that no overflow will occur. +- """ +- cdef mpfr_t yf, xf +- mpfr_init2(xf, mpz_bitcount(x)+2) +- mpfr_init2(yf, prec+2) +- mpfr_set_z(xf, x, MPFR_RNDN) +- mpfr_div_2exp(xf, xf, prec, MPFR_RNDN) +- mpfr_exp(yf, xf, MPFR_RNDN) +- mpfr_mul_2exp(yf, yf, prec, MPFR_RNDN) +- mpfr_get_z(y, yf, MPFR_RNDN) +- mpfr_clear(yf) +- mpfr_clear(xf) +- +-cdef cy_exp_basecase(mpz_t y, mpz_t x, int prec): +- """ +- Compute y = exp(x) for fixed-point numbers y and x, assuming +- that x is small (|x| ~< 1). At small precisions, this function +- is equivalent to the exp_basecase function in +- mpmath.libmp.exp_fixed. +- """ +- cdef int k, r, u +- cdef mpz_t s0, s1, x2, a +- # TODO: could use custom implementation here; for now switch to MPFR +- if prec > 2000: +- _cy_exp_mpfr(y, x, prec) +- return +- mpz_init(s0) +- mpz_init(s1) +- mpz_init(x2) +- mpz_init(a) +- r = fsqrt(prec) +- prec += r +- mpz_set_ui(s0, 1) +- mpz_mul_2exp(s0, s0, prec) +- mpz_set(s1, s0) +- k = 2 +- mpz_mul(x2, x, x) +- mpz_fdiv_q_2exp(x2, x2, prec) +- mpz_set(a, x2) +- while mpz_sgn(a): +- sig_check() +- mpz_fdiv_q_ui(a, a, k) +- mpz_add(s0, s0, a) +- k += 1 +- mpz_fdiv_q_ui(a, a, k) +- mpz_add(s1, s1, a) +- k += 1 +- mpz_mul(a, a, x2) +- mpz_fdiv_q_2exp(a, a, prec) +- mpz_mul(s1, s1, x) +- mpz_fdiv_q_2exp(s1, s1, prec) +- mpz_add(s0, s0, s1) +- u = r +- while r: +- sig_check() +- mpz_mul(s0, s0, s0) +- mpz_fdiv_q_2exp(s0, s0, prec) +- r -= 1 +- mpz_fdiv_q_2exp(y, s0, u) +- mpz_clear(s0) +- mpz_clear(s1) +- mpz_clear(x2) +- mpz_clear(a) +- +- +-cdef MPF_exp(MPF *y, MPF *x, MPopts opts): +- """ +- Set y = exp(x). +- """ +- cdef bint sign, is_int +- cdef long wp, wpmod, offset, mag +- cdef mpz_t t, u +- cdef tuple w +- if x.special: +- if x.special == S_ZERO: +- MPF_set_si(y, 1) +- elif x.special == S_NINF: +- MPF_set_zero(y) +- elif x.special == S_INF: +- MPF_set_inf(y) +- else: +- MPF_set_nan(y) +- return +- wp = opts.prec + 14 +- sign = mpz_sgn(x.man) < 0 +- is_int = mpz_sgn(x.exp) >= 0 +- # note: bogus if not reasonable shift +- mag = mpz_bitcount(x.man) + mpz_get_si(x.exp) +- if (not mpz_reasonable_shift(x.exp)) or mag < -wp: +- if mpz_sgn(x.exp) <= 0: +- # perturb +- MPF_set_one(y) +- if opts.rounding != ROUND_N: +- mpz_mul_2exp(y.man, y.man, wp) +- if sign: +- mpz_sub_ui(y.man, y.man, 1) +- else: +- mpz_add_ui(y.man, y.man, 1) +- mpz_set_si(y.exp, -wp) +- MPF_normalize(y, opts) +- return +- else: +- raise OverflowError("exp of a huge number") +- #offset = mpz_get_si(x.exp) + wp +- mpz_init(t) +- if mag > 1: +- wpmod = wp + mag +- mpz_set_fixed(t, x, wpmod, False) +- mpz_init(u) +- mpz_set_ln2(u, wpmod) +- # y.exp, t = divmod(t, ln2) +- mpz_fdiv_qr(y.exp,t,t,u) +- mpz_clear(u) +- mpz_fdiv_q_2exp(t, t, mag) +- else: +- mpz_set_fixed(t, x, wp, False) +- mpz_set_ui(y.exp, 0) +- cy_exp_basecase(y.man, t, wp) +- mpz_add_si(y.exp, y.exp, -wp) +- y.special = S_NORMAL +- mpz_clear(t) +- MPF_normalize(y, opts) +- +- +-cdef MPF_complex_sqrt(MPF *c, MPF *d, MPF *a, MPF *b, MPopts opts): +- """ +- Set c+di = sqrt(a+bi). +- +- c, a and d, b may be the same objects. +- """ +- cdef int apos, bneg +- cdef MPF t, u, v +- cdef MPopts wpopts +- if b.special == S_ZERO: +- if a.special == S_ZERO: +- MPF_set_zero(c) +- MPF_set_zero(d) +- # a+bi, a < 0, b = 0 +- elif MPF_sgn(a) < 0: +- MPF_abs(d, a) +- MPF_sqrt(d, d, opts) +- MPF_set_zero(c) +- # a > 0 +- else: +- MPF_sqrt(c, a, opts) +- MPF_set_zero(d) +- return +- wpopts.prec = opts.prec + 20 +- wpopts.rounding = ROUND_D +- MPF_init(&t) +- MPF_init(&u) +- MPF_init(&v) +- apos = MPF_sgn(a) >= 0 +- bneg = MPF_sgn(b) <= 0 +- if apos: +- # real part +- MPF_hypot(&t, a, b, wpopts) # t = abs(a+bi) + a +- MPF_add(&t, &t, a, wpopts) +- MPF_set(&u, &t) +- mpz_sub_ui(u.exp, u.exp, 1) # u = t / 2 +- MPF_sqrt(c, &u, opts) # re = sqrt(u) +- # imag part +- mpz_add_ui(t.exp, t.exp, 1) # t = 2*t +- MPF_sqrt(&u, &t, wpopts) # u = sqrt(t) +- MPF_div(d, b, &u, opts) # im = b / u +- else: +- MPF_set(&v, b) +- MPF_hypot(&t, a, b, wpopts) # t = abs(a+bi) - a +- MPF_sub(&t, &t, a, wpopts) +- MPF_set(&u, &t) +- mpz_sub_ui(u.exp, u.exp, 1) # u = t / 2 +- MPF_sqrt(d, &u, opts) # im = sqrt(u) +- mpz_add_ui(t.exp, t.exp, 1) # t = 2*t +- MPF_sqrt(&u, &t, wpopts) # u = sqrt(t) +- MPF_div(c, &v, &u, opts) # re = b / u +- if bneg: +- MPF_neg(c, c) +- MPF_neg(d, d) +- MPF_clear(&t) +- MPF_clear(&u) +- MPF_clear(&v) +- +-cdef int MPF_get_mpfr_overflow(mpfr_t y, MPF *x) noexcept: +- """ +- Store the mpmath number x exactly in the MPFR variable y. The precision +- of y will be adjusted if necessary. If the exponent overflows, only +- the mantissa is stored and 1 is returned; if no overflow occurs, +- the function returns 0. +- """ +- cdef long prec, exp +- if x.special != S_NORMAL: +- if x.special == S_ZERO: +- mpfr_set_ui(y, 0, MPFR_RNDN) +- elif x.special == S_INF: +- mpfr_set_inf(y, 1) +- elif x.special == S_NINF: +- mpfr_set_inf(y, -1) +- else: +- mpfr_set_nan(y) +- return 0 +- prec = mpz_bitcount(x.man) +- # Minimum precision for MPFR +- if prec < 2: +- prec = 2 +- mpfr_set_prec(y, prec) +- mpfr_set_z(y, x.man, MPFR_RNDN) +- if mpz_reasonable_shift(x.exp): +- exp = mpz_get_si(x.exp) +- if exp >= 0: +- mpfr_mul_2exp(y, y, exp, MPFR_RNDN) +- else: +- mpfr_div_2exp(y, y, -exp, MPFR_RNDN) +- return 0 +- else: +- return 1 +- +-cdef MPF_set_mpfr(MPF *y, mpfr_t x, MPopts opts): +- """ +- Convert the MPFR number x to a normalized MPF y. +- inf/nan and zero are handled. +- """ +- cdef long exp +- # TODO: use mpfr_regular_p with MPFR 3 +- if mpfr_nan_p(x): +- MPF_set_nan(y) +- return +- if mpfr_inf_p(x): +- if mpfr_sgn(x) > 0: +- MPF_set_inf(y) +- else: +- MPF_set_ninf(y) +- return +- if mpfr_zero_p(x): +- MPF_set_zero(y) +- return +- exp = mpfr_get_z_exp(y.man, x) +- mpz_set_si(y.exp, exp) +- y.special = S_NORMAL +- MPF_normalize(y, opts) +- +-cdef int MPF_log(MPF *y, MPF *x, MPopts opts) noexcept: +- """ +- Set y = log(|x|). Returns 1 if x is negative. +- """ +- cdef MPF t +- cdef bint negative, overflow +- cdef mpfr_rnd_t rndmode +- cdef mpfr_t yy, xx +- if x.special != S_NORMAL: +- if x.special == S_ZERO: +- MPF_set_ninf(y) +- return 0 +- if x.special == S_INF: +- MPF_set_inf(y) +- return 0 +- if x.special == S_NAN: +- MPF_set_nan(y) +- return 0 +- if x.special == S_NINF: +- MPF_set_inf(y) +- return 1 +- +- negative = MPF_sgn(x) < 0 +- mpfr_init2(xx, opts.prec) +- mpfr_init2(yy, opts.prec) +- +- overflow = MPF_get_mpfr_overflow(xx, x) +- rndmode = rndmode_to_mpfr(opts.rounding) +- +- if overflow: +- MPF_init(&t) +- # Copy x exponent in case x and y are aliased +- mpz_set(t.exp, x.exp) +- +- # log(m * 2^e) = log(m) + e*log(2) +- mpfr_abs(xx, xx, MPFR_RNDN) +- mpfr_log(yy, xx, rndmode) +- MPF_set_mpfr(y, yy, opts) +- +- mpz_set_ln2(t.man, opts.prec+20) +- mpz_mul(t.man, t.man, t.exp) +- mpz_set_si(t.exp, -(opts.prec+20)) +- t.special = S_NORMAL +- +- MPF_add(y, y, &t, opts) +- MPF_clear(&t) +- else: +- mpfr_abs(xx, xx, MPFR_RNDN) +- mpfr_log(yy, xx, rndmode) +- MPF_set_mpfr(y, yy, opts) +- +- mpfr_clear(xx) +- mpfr_clear(yy) +- return negative +- +-cdef MPF_set_pi(MPF *x, MPopts opts): +- """ +- Set x = pi. +- """ +- x.special = S_NORMAL +- mpz_set_pi(x.man, (opts.prec+20)) +- mpz_set_si(x.exp, -(opts.prec+20)) +- MPF_normalize(x, opts) +- +-cdef MPF_set_ln2(MPF *x, MPopts opts): +- """ +- Set x = ln(2). +- """ +- x.special = S_NORMAL +- mpz_set_ln2(x.man, (opts.prec+20)) +- mpz_set_si(x.exp, -(opts.prec+20)) +- MPF_normalize(x, opts) +- +- +-def exp_fixed(Integer x, int prec, ln2=None): +- """ +- Return a fixed-point approximation of exp(x) where x is a fixed-point +- number. +- +- EXAMPLES:: +- +- sage: from sage.libs.mpmath.ext_impl import exp_fixed +- sage: y = exp_fixed(1<<53, 53) +- sage: float(y) / 2^53 +- 2.718281828459044 +- """ +- cdef Integer v +- cdef mpz_t n, t +- cdef long nn +- mpz_init(n) +- mpz_init(t) +- if ln2 is None: +- mpz_set_ln2(t, prec) +- mpz_fdiv_qr(n, t, x.value, t) +- else: +- mpz_fdiv_qr(n, t, x.value, (ln2).value) +- nn = mpz_get_si(n) +- v = PY_NEW(Integer) +- cy_exp_basecase(v.value, t, prec) +- if nn >= 0: +- mpz_mul_2exp(v.value, v.value, nn) +- else: +- mpz_fdiv_q_2exp(v.value, v.value, -nn) +- mpz_clear(t) +- mpz_clear(n) +- return v +- +- +-def cos_sin_fixed(Integer x, int prec, pi2=None): +- """ +- Return fixed-point approximations of cos(x), sin(x) where +- x is a fixed-point number. +- +- EXAMPLES:: +- +- sage: from sage.libs.mpmath.ext_impl import cos_sin_fixed +- sage: c, s = cos_sin_fixed(1<<53, 53) +- sage: float(c) / 2^53 +- 0.5403023058681398 +- sage: float(s) / 2^53 +- 0.8414709848078965 +- """ +- cdef Integer cv, sv +- cdef mpfr_t t, cf, sf +- mpfr_init2(t, mpz_bitcount(x.value)+2) +- mpfr_init2(cf, prec) +- mpfr_init2(sf, prec) +- mpfr_set_z(t, x.value, MPFR_RNDN) +- mpfr_div_2exp(t, t, prec, MPFR_RNDN) +- mpfr_sin_cos(sf, cf, t, MPFR_RNDN) +- mpfr_mul_2exp(cf, cf, prec, MPFR_RNDN) +- mpfr_mul_2exp(sf, sf, prec, MPFR_RNDN) +- cv = PY_NEW(Integer) +- sv = PY_NEW(Integer) +- mpfr_get_z(cv.value, cf, MPFR_RNDN) +- mpfr_get_z(sv.value, sf, MPFR_RNDN) +- mpfr_clear(t) +- mpfr_clear(cf) +- mpfr_clear(sf) +- return cv, sv +- +- +-DEF MAX_LOG_INT_CACHE = 2000 +- +-cdef mpz_t log_int_cache[MAX_LOG_INT_CACHE+1] +-cdef long log_int_cache_prec[MAX_LOG_INT_CACHE+1] +-cdef bint log_int_cache_initialized = 0 +- +-cdef mpz_log_int(mpz_t v, mpz_t n, int prec): +- """ +- Set v = log(n) where n is an integer and v is a fixed-point number +- with the specified precision. +- """ +- cdef mpfr_t f +- mpfr_init2(f, prec+15) +- mpfr_set_z(f, n, MPFR_RNDN) +- mpfr_log(f, f, MPFR_RNDN) +- mpfr_mul_2exp(f, f, prec, MPFR_RNDN) +- mpfr_get_z(v, f, MPFR_RNDN) +- mpfr_clear(f) +- +- +-def log_int_fixed(n, long prec, ln2=None): +- """ +- Return fixed-point approximation of log(n). +- +- EXAMPLES:: +- +- sage: from sage.libs.mpmath.ext_impl import log_int_fixed +- sage: float(log_int_fixed(5, 53)) / 2^53 +- 1.6094379124341003 +- sage: float(log_int_fixed(5, 53)) / 2^53 # exercise cache +- 1.6094379124341003 +- """ +- global log_int_cache_initialized +- cdef Integer t +- cdef int i +- t = PY_NEW(Integer) +- mpz_set_integer(t.value, n) +- if mpz_sgn(t.value) <= 0: +- mpz_set_ui(t.value, 0) +- elif mpz_cmp_ui(t.value, MAX_LOG_INT_CACHE) <= 0: +- if not log_int_cache_initialized: +- for i in range(MAX_LOG_INT_CACHE+1): +- mpz_init(log_int_cache[i]) +- log_int_cache_prec[i] = 0 +- log_int_cache_initialized = 1 +- i = mpz_get_si(t.value) +- if log_int_cache_prec[i] < prec: +- mpz_log_int(log_int_cache[i], t.value, prec+64) +- log_int_cache_prec[i] = prec+64 +- mpz_tdiv_q_2exp(t.value, log_int_cache[i], log_int_cache_prec[i]-prec) +- +- else: +- mpz_log_int(t.value, t.value, prec) +- return t +- +- +-cdef _MPF_cos_python(MPF *c, MPF *x, MPopts opts): +- """ +- Compute c = cos(x) by calling the mpmath.libmp Python implementation. +- """ +- from mpmath.libmp.libelefun import mpf_cos_sin +- ct = mpf_cos_sin(MPF_to_tuple(x), opts.prec, +- rndmode_to_python(opts.rounding), 1, False) +- MPF_set_tuple(c, ct) +- +-cdef _MPF_sin_python(MPF *s, MPF *x, MPopts opts): +- """ +- Compute s = sin(x) by calling the mpmath.libmp Python implementation. +- """ +- from mpmath.libmp.libelefun import mpf_cos_sin +- st = mpf_cos_sin(MPF_to_tuple(x), opts.prec, +- rndmode_to_python(opts.rounding), 2, False) +- MPF_set_tuple(s, st) +- +- +-cdef MPF_cos(MPF *c, MPF *x, MPopts opts): +- """ +- Set c = cos(x) +- """ +- cdef mpfr_t cf, xf +- cdef bint overflow +- if x.special != S_NORMAL: +- if x.special == S_ZERO: +- MPF_set_one(c) +- else: +- MPF_set_nan(c) +- return +- mpfr_init(xf) +- mpfr_init2(cf, opts.prec) +- overflow = MPF_get_mpfr_overflow(xf, x) +- if overflow or opts.rounding == ROUND_U: +- _MPF_cos_python(c, x, opts) +- else: +- mpfr_cos(cf, xf, rndmode_to_mpfr(opts.rounding)) +- MPF_set_mpfr(c, cf, opts) +- mpfr_clear(xf) +- mpfr_clear(cf) +- +-cdef MPF_sin(MPF *s, MPF *x, MPopts opts): +- """ +- Set s = sin(x) +- """ +- cdef mpfr_t sf, xf +- cdef bint overflow +- if x.special != S_NORMAL: +- if x.special == S_ZERO: +- MPF_set_zero(s) +- else: +- MPF_set_nan(s) +- return +- mpfr_init(xf) +- mpfr_init2(sf, opts.prec) +- overflow = MPF_get_mpfr_overflow(xf, x) +- if overflow or opts.rounding == ROUND_U: +- _MPF_sin_python(s, x, opts) +- else: +- mpfr_sin(sf, xf, rndmode_to_mpfr(opts.rounding)) +- MPF_set_mpfr(s, sf, opts) +- mpfr_clear(xf) +- mpfr_clear(sf) +- +-cdef MPF_cos_sin(MPF *c, MPF *s, MPF *x, MPopts opts): +- """ +- Set c = cos(x), s = sin(x) +- """ +- cdef mpfr_t cf, sf, xf +- cdef bint overflow +- if x.special != S_NORMAL: +- if x.special == S_ZERO: +- MPF_set_one(c) +- MPF_set_zero(s) +- else: +- MPF_set_nan(c) +- MPF_set_nan(s) +- return +- mpfr_init(xf) +- mpfr_init2(sf, opts.prec) +- mpfr_init2(cf, opts.prec) +- overflow = MPF_get_mpfr_overflow(xf, x) +- if overflow or opts.rounding == ROUND_U: +- _MPF_cos_python(c, x, opts) +- _MPF_sin_python(s, x, opts) +- else: +- mpfr_sin_cos(sf, cf, xf, rndmode_to_mpfr(opts.rounding)) +- MPF_set_mpfr(s, sf, opts) +- MPF_set_mpfr(c, cf, opts) +- mpfr_clear(xf) +- mpfr_clear(cf) +- mpfr_clear(sf) +- +- +-cdef MPF_complex_exp(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts): +- """ +- Set re+im*i = exp(a+bi) +- """ +- cdef MPF mag, c, s +- cdef MPopts wopts +- if a.special == S_ZERO: +- MPF_cos_sin(re, im, b, opts) +- return +- if b.special == S_ZERO: +- MPF_exp(re, a, opts) +- MPF_set_zero(im) +- return +- MPF_init(&mag) +- MPF_init(&c) +- MPF_init(&s) +- wopts = opts +- wopts.prec += 4 +- MPF_exp(&mag, a, wopts) +- MPF_cos_sin(&c, &s, b, wopts) +- MPF_mul(re, &mag, &c, opts) +- MPF_mul(im, &mag, &s, opts) +- MPF_clear(&mag) +- MPF_clear(&c) +- MPF_clear(&s) +- +-cdef int MPF_pow(MPF *z, MPF *x, MPF *y, MPopts opts) except -1: +- """ +- Set z = x^y for real x and y and returns 0 if the result is real-valued. +- If the result is complex, does nothing and returns 1. +- """ +- cdef MPopts wopts +- cdef mpz_t t +- cdef MPF w +- cdef int xsign, ysign +- cdef mpz_t tm +- +- # Integer exponentiation, if reasonable +- if y.special == S_NORMAL and mpz_sgn(y.exp) >= 0: +- mpz_init(tm) +- # check if size is reasonable +- mpz_add_ui(tm, y.exp, mpz_bitcount(y.man)) +- mpz_abs(tm, tm) +- if mpz_cmp_ui(tm, 10000) < 0: +- # man * 2^exp +- mpz_mul_2exp(tm, y.man, mpz_get_ui(y.exp)) +- MPF_pow_int(z, x, tm, opts) +- mpz_clear(tm) +- return 0 +- mpz_clear(tm) +- +- # x ^ 0 +- if y.special == S_ZERO: +- if x.special == S_NORMAL or x.special == S_ZERO: +- MPF_set_one(z) +- else: +- MPF_set_nan(z) +- return 0 +- +- xsign = MPF_sgn(x) +- ysign = MPF_sgn(y) +- +- if xsign < 0: +- return 1 +- +- # Square root or integer power thereof +- if y.special == S_NORMAL and mpz_cmp_si(y.exp, -1) == 0: +- # x^(1/2) +- if mpz_cmp_ui(y.man, 1) == 0: +- MPF_sqrt(z, x, opts) +- return 0 +- # x^(-1/2) +- if mpz_cmp_si(y.man, -1) == 0: +- wopts = opts +- wopts.prec += 10 +- wopts.rounding = reciprocal_rnd(wopts.rounding) +- MPF_sqrt(z, x, wopts) +- MPF_div(z, &MPF_C_1, z, opts) +- return 0 +- # x^(n/2) +- wopts = opts +- wopts.prec += 10 +- if mpz_sgn(y.man) < 0: +- wopts.rounding = reciprocal_rnd(wopts.rounding) +- mpz_init_set(t, y.man) +- MPF_sqrt(z, x, wopts) +- MPF_pow_int(z, z, t, opts) +- mpz_clear(t) +- return 0 +- +- if x.special != S_NORMAL or y.special != S_NORMAL: +- if x.special == S_NAN or y.special == S_NAN: +- MPF_set_nan(z) +- return 0 +- if y.special == S_ZERO: +- if x.special == S_NORMAL or x.special == S_ZERO: +- MPF_set_one(z) +- else: +- MPF_set_nan(z) +- return 0 +- if x.special == S_ZERO and y.special == S_NORMAL: +- if mpz_sgn(y.man) > 0: +- MPF_set_zero(z) +- return 0 +- +- wopts = opts +- wopts.prec += 10 +- MPF_init(&w) +- MPF_log(&w, x, wopts) +- MPF_mul(&w, &w, y, opts_exact) +- MPF_exp(z, &w, opts) +- MPF_clear(&w) +- return 0 +- +-cdef MPF_complex_square(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts): +- """ +- Set re+im*i = (a+bi)^2 = a^2-b^2, 2ab*i. +- """ +- cdef MPF t, u +- MPF_init(&t) +- MPF_init(&u) +- MPF_mul(&t,a,a,opts_exact) +- MPF_mul(&u,b,b,opts_exact) +- MPF_sub(re, &t, &u, opts) +- MPF_mul(im, a, b, opts) +- if im.special == S_NORMAL: +- mpz_add_ui(im.exp, im.exp, 1) +- MPF_clear(&t) +- MPF_clear(&u) +- +- +-cdef MPF_complex_reciprocal(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts): +- """ +- Set re+im*i = 1/(a+bi), i.e. compute the reciprocal of +- a complex number. +- """ +- cdef MPopts wopts +- cdef MPF t, u, m +- wopts = opts +- wopts.prec += 10 +- MPF_init(&t) +- MPF_init(&u) +- MPF_init(&m) +- MPF_mul(&t, a, a,opts_exact) +- MPF_mul(&u, b, b,opts_exact) +- MPF_add(&m, &t, &u,wopts) +- MPF_div(&t, a, &m, opts) +- MPF_div(&u, b, &m, opts) +- MPF_set(re, &t) +- MPF_neg(im, &u) +- MPF_clear(&t) +- MPF_clear(&u) +- MPF_clear(&m) +- +- +-cdef MPF_complex_pow_int(MPF *zre, MPF *zim, MPF *xre, MPF *xim, mpz_t n, MPopts opts): +- """ +- Set zre+zim*i = (xre+xim) ^ n, i.e. raise a complex number to an integer power. +- """ +- cdef MPopts wopts +- cdef long m +- +- if xim.special == S_ZERO: +- MPF_pow_int(zre, xre, n, opts) +- MPF_set_zero(zim) +- return +- +- if xre.special == S_ZERO: +- # n % 4 +- m = mpz_get_si(n) % 4 +- if m == 0: +- MPF_pow_int(zre, xim, n, opts) +- MPF_set_zero(zim) +- return +- if m == 1: +- MPF_set_zero(zre) +- MPF_pow_int(zim, xim, n, opts) +- return +- if m == 2: +- MPF_pow_int(zre, xim, n, opts) +- MPF_neg(zre, zre) +- MPF_set_zero(zim) +- return +- if m == 3: +- MPF_set_zero(zre) +- MPF_pow_int(zim, xim, n, opts) +- MPF_neg(zim, zim) +- return +- +- if mpz_reasonable_shift(n): +- m = mpz_get_si(n) +- if m == 0: +- MPF_set_one(zre) +- MPF_set_zero(zim) +- return +- if m == 1: +- MPF_pos(zre, xre, opts) +- MPF_pos(zim, xim, opts) +- return +- if m == 2: +- MPF_complex_square(zre, zim, xre, xim, opts) +- return +- if m == -1: +- MPF_complex_reciprocal(zre, zim, xre, xim, opts) +- return +- if m == -2: +- wopts = opts +- wopts.prec += 10 +- MPF_complex_square(zre, zim, xre, xim, wopts) +- MPF_complex_reciprocal(zre, zim, zre, zim, opts) +- return +- +- xret = MPF_to_tuple(xre) +- ximt = MPF_to_tuple(xim) +- from mpmath.libmp import mpc_pow_int +- vr, vi = mpc_pow_int((xret, ximt), mpzi(n), +- opts.prec, rndmode_to_python(opts.rounding)) +- MPF_set_tuple(zre, vr) +- MPF_set_tuple(zim, vi) +- +- +-cdef MPF_complex_pow_re(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *y, MPopts opts): +- """ +- Set (zre+zim*i) = (xre+xim*i) ^ y, i.e. raise a complex number +- to a real power. +- """ +- +- cdef mpz_t tm +- cdef MPopts wopts +- +- if y.special == S_ZERO: +- if xre.special == S_NORMAL and xim.special == S_NORMAL: +- # x ^ 0 +- MPF_set_one(zre) +- MPF_set_zero(zim) +- return +- +- wopts = opts +- wopts.prec += 10 +- +- if y.special == S_NORMAL: +- # Integer +- if mpz_cmp_ui(y.exp, 0) >= 0 and mpz_reasonable_shift(y.exp): +- mpz_init_set(tm, y.man) +- mpz_mul_2exp(tm, tm, mpz_get_ui(y.exp)) +- MPF_complex_pow_int(zre, zim, xre, xim, tm, opts) +- mpz_clear(tm) +- return +- # x ^ (n/2) +- if mpz_cmp_si(y.exp, -1) == 0: +- mpz_init_set(tm, y.man) +- MPF_complex_sqrt(zre, zim, xre, xim, wopts) +- MPF_complex_pow_int(zre, zim, zre, zim, tm, opts) +- mpz_clear(tm) +- return +- +- xret = MPF_to_tuple(xre) +- ximt = MPF_to_tuple(xim) +- yret = MPF_to_tuple(y) +- from mpmath.libmp import mpc_pow_mpf +- vr, vi = mpc_pow_mpf((xret, ximt), yret, +- opts.prec, rndmode_to_python(opts.rounding)) +- MPF_set_tuple(zre, vr) +- MPF_set_tuple(zim, vi) +- +- +-cdef MPF_complex_pow(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *yre, MPF *yim, MPopts opts): +- """ +- Set (zre + zim*i) = (xre+xim*i) ^ (yre+yim*i). +- """ +- if yim.special == S_ZERO: +- MPF_complex_pow_re(zre, zim, xre, xim, yre, opts) +- return +- xret = MPF_to_tuple(xre) +- ximt = MPF_to_tuple(xim) +- yret = MPF_to_tuple(yre) +- yimt = MPF_to_tuple(yim) +- from mpmath.libmp import mpc_pow +- vr, vi = mpc_pow((xret, ximt), (yret, yimt), +- opts.prec, rndmode_to_python(opts.rounding)) +- MPF_set_tuple(zre, vr) +- MPF_set_tuple(zim, vi) +- +- +-cdef mpz_set_tuple_fixed(mpz_t x, tuple t, long prec): +- """ +- Set the integer x to a fixed-point number with specified precision +- and the value of t = (sign,man,exp,bc). Truncating division is used +- if the value cannot be represented exactly. +- """ +- cdef long offset +- sign, man, exp, bc = t +- mpz_set_integer(x, man) +- if sign: +- mpz_neg(x, x) +- offset = exp + prec +- if offset >= 0: +- mpz_mul_2exp(x, x, offset) +- else: +- mpz_tdiv_q_2exp(x, x, -offset) +- +-cdef mpz_set_complex_tuple_fixed(mpz_t x, mpz_t y, tuple t, long prec): +- """ +- Set the integers (x,y) to fixed-point numbers with the values of +- the mpf pair t = ((xsign,xman,xexp,xbc), (ysign,yman,yexp,ybc)). +- """ +- mpz_set_tuple_fixed(x, t[0], prec) +- mpz_set_tuple_fixed(y, t[1], prec) +- +-cdef MPF_set_fixed(MPF *x, mpz_t man, long wp, long prec, int rnd): +- """ +- Set value of an MPF given a fixed-point mantissa of precision wp, +- rounding to the given precision and rounding mode. +- """ +- cdef MPopts opts +- opts.prec = prec +- opts.rounding = rnd +- x.special = S_NORMAL +- mpz_set(x.man, man) +- mpz_set_si(x.exp, -wp) +- MPF_normalize(x, opts) +- +-# TODO: we should allocate these dynamically +-DEF MAX_PARAMS = 128 +-cdef mpz_t AINT[MAX_PARAMS] +-cdef mpz_t BINT[MAX_PARAMS] +-cdef mpz_t AP[MAX_PARAMS] +-cdef mpz_t AQ[MAX_PARAMS] +-cdef mpz_t BP[MAX_PARAMS] +-cdef mpz_t BQ[MAX_PARAMS] +-cdef mpz_t AREAL[MAX_PARAMS] +-cdef mpz_t BREAL[MAX_PARAMS] +-cdef mpz_t ACRE[MAX_PARAMS] +-cdef mpz_t ACIM[MAX_PARAMS] +-cdef mpz_t BCRE[MAX_PARAMS] +-cdef mpz_t BCIM[MAX_PARAMS] +- +- +-cdef MPF_hypsum(MPF *a, MPF *b, int p, int q, param_types, str ztype, coeffs, z, +- long prec, long wp, long epsshift, dict magnitude_check, kwargs): +- """ +- Evaluates a+bi = pFq(..., z) by summing the hypergeometric +- series in fixed-point arithmetic. +- +- This basically a Cython version of +- mpmath.libmp.libhyper.make_hyp_summator(). It should produce identical +- results (the calculations are exactly the same, and the same rounding +- is used for divisions). +- +- This function is not intended to be called directly; it is wrapped +- by the hypsum_internal function in ext_main.pyx. +- """ +- cdef long i, j, k, n, p_mag, cancellable_real, MAX, magn +- cdef int have_complex_param, have_complex_arg, have_complex +- +- cdef mpz_t SRE, SIM, PRE, PIM, ZRE, ZIM, TRE, TIM, URE, UIM, MUL, DIV, HIGH, LOW, one +- # Count number of parameters +- cdef int aint, bint, arat, brat, areal, breal, acomplex, bcomplex +- cdef int have_multiplier +- +- if p >= MAX_PARAMS or q >= MAX_PARAMS: +- raise NotImplementedError("too many hypergeometric function parameters") +- +- have_complex_param = 'C' in param_types +- have_complex_arg = ztype == 'C' +- have_complex = have_complex_param or have_complex_arg +- +- mpz_init(one) +- mpz_init(SRE) +- mpz_init(SIM) +- mpz_init(PRE) +- mpz_init(PIM) +- mpz_init(ZRE) +- mpz_init(ZIM) +- mpz_init(MUL) +- mpz_init(DIV) +- mpz_init(HIGH) +- mpz_init(LOW) +- mpz_init(TRE) +- mpz_init(TIM) +- mpz_init(URE) +- mpz_init(UIM) +- +- aint = bint = arat = brat = areal = breal = acomplex = bcomplex = 0 +- +- MAX = kwargs.get('maxterms', wp*100) +- mpz_set_ui(HIGH, 1) +- mpz_mul_2exp(HIGH, HIGH, epsshift) +- mpz_neg(LOW, HIGH) +- +- mpz_set_ui(one, 1) +- mpz_mul_2exp(one, one, wp) +- mpz_set(SRE, one) +- mpz_set(PRE, one) +- +- # Copy input data to mpzs +- if have_complex_arg: +- mpz_set_complex_tuple_fixed(ZRE, ZIM, z, wp) +- else: +- mpz_set_tuple_fixed(ZRE, z, wp) +- for i in range(p): +- sig_check() +- if param_types[i] == 'Z': +- mpz_init(AINT[aint]) +- mpz_set_integer(AINT[aint], coeffs[i]) +- aint += 1 +- elif param_types[i] == 'Q': +- mpz_init(AP[arat]) +- mpz_init(AQ[arat]) +- __p, __q = coeffs[i]._mpq_ +- mpz_set_integer(AP[arat], __p) +- mpz_set_integer(AQ[arat], __q) +- arat += 1 +- elif param_types[i] == 'R': +- mpz_init(AREAL[areal]) +- mpz_set_tuple_fixed(AREAL[areal], coeffs[i]._mpf_, wp) +- areal += 1 +- elif param_types[i] == 'C': +- mpz_init(ACRE[acomplex]) +- mpz_init(ACIM[acomplex]) +- mpz_set_complex_tuple_fixed(ACRE[acomplex], ACIM[acomplex], coeffs[i]._mpc_, wp) +- acomplex += 1 +- else: +- raise ValueError +- for i in range(p,p+q): +- sig_check() +- if param_types[i] == 'Z': +- mpz_init(BINT[bint]) +- mpz_set_integer(BINT[bint], coeffs[i]) +- bint += 1 +- elif param_types[i] == 'Q': +- mpz_init(BP[brat]) +- mpz_init(BQ[brat]) +- __p, __q = coeffs[i]._mpq_ +- mpz_set_integer(BP[brat], __p) +- mpz_set_integer(BQ[brat], __q) +- brat += 1 +- elif param_types[i] == 'R': +- mpz_init(BREAL[breal]) +- mpz_set_tuple_fixed(BREAL[breal], coeffs[i]._mpf_, wp) +- breal += 1 +- elif param_types[i] == 'C': +- mpz_init(BCRE[bcomplex]) +- mpz_init(BCIM[bcomplex]) +- mpz_set_complex_tuple_fixed(BCRE[bcomplex], BCIM[bcomplex], coeffs[i]._mpc_, wp) +- bcomplex += 1 +- else: +- raise ValueError +- +- cancellable_real = min(areal, breal) +- +- # Main loop +- for n in range(1, 10**8): +- +- if n in magnitude_check: +- p_mag = mpz_bitcount(PRE) +- if have_complex: +- p_mag = max(p_mag, mpz_bitcount(PIM)) +- magnitude_check[n] = wp - p_mag +- +- # Update rational part of product +- mpz_set_ui(MUL, 1) +- mpz_set_ui(DIV, n) +- +- for i in range(aint): mpz_mul(MUL, MUL, AINT[i]) +- for i in range(arat): mpz_mul(MUL, MUL, AP[i]) +- for i in range(brat): mpz_mul(MUL, MUL, BQ[i]) +- for i in range(bint): mpz_mul(DIV, DIV, BINT[i]) +- for i in range(brat): mpz_mul(DIV, DIV, BP[i]) +- for i in range(arat): mpz_mul(DIV, DIV, AQ[i]) +- +- # Check for singular terms +- if mpz_sgn(DIV) == 0: +- if mpz_sgn(MUL) == 0: +- break +- raise ZeroDivisionError +- +- # Multiply real factors +- for k in range(cancellable_real): +- sig_check() +- mpz_mul(PRE, PRE, AREAL[k]) +- mpz_fdiv_q(PRE, PRE, BREAL[k]) +- for k in range(cancellable_real, areal): +- sig_check() +- mpz_mul(PRE, PRE, AREAL[k]) +- mpz_fdiv_q_2exp(PRE, PRE, wp) +- for k in range(cancellable_real, breal): +- sig_check() +- mpz_mul_2exp(PRE, PRE, wp) +- mpz_fdiv_q(PRE, PRE, BREAL[k]) +- if have_complex: +- for k in range(cancellable_real): +- sig_check() +- mpz_mul(PIM, PIM, AREAL[k]) +- mpz_fdiv_q(PIM, PIM, BREAL[k]) +- for k in range(cancellable_real, areal): +- sig_check() +- mpz_mul(PIM, PIM, AREAL[k]) +- mpz_fdiv_q_2exp(PIM, PIM, wp) +- for k in range(cancellable_real, breal): +- sig_check() +- mpz_mul_2exp(PIM, PIM, wp) +- mpz_fdiv_q(PIM, PIM, BREAL[k]) +- +- # Update product +- if have_complex: +- if have_complex_arg: +- # PRE = ((mul*(PRE*ZRE-PIM*ZIM))//div)>>wp +- # PIM = ((mul*(PIM*ZRE+PRE*ZIM))//div)>>wp +- mpz_mul(TRE, PRE, ZRE) +- mpz_submul(TRE, PIM, ZIM) +- mpz_mul(TRE, TRE, MUL) +- +- mpz_mul(TIM, PIM, ZRE) +- mpz_addmul(TIM, PRE, ZIM) +- mpz_mul(TIM, TIM, MUL) +- +- mpz_fdiv_q(PRE, TRE, DIV) +- mpz_fdiv_q_2exp(PRE, PRE, wp) +- +- mpz_fdiv_q(PIM, TIM, DIV) +- mpz_fdiv_q_2exp(PIM, PIM, wp) +- else: +- mpz_mul(PRE, PRE, MUL) +- mpz_mul(PRE, PRE, ZRE) +- mpz_fdiv_q_2exp(PRE, PRE, wp) +- mpz_fdiv_q(PRE, PRE, DIV) +- +- mpz_mul(PIM, PIM, MUL) +- mpz_mul(PIM, PIM, ZRE) +- mpz_fdiv_q_2exp(PIM, PIM, wp) +- mpz_fdiv_q(PIM, PIM, DIV) +- +- for i in range(acomplex): +- sig_check() +- mpz_mul(TRE, PRE, ACRE[i]) +- mpz_submul(TRE, PIM, ACIM[i]) +- mpz_mul(TIM, PIM, ACRE[i]) +- mpz_addmul(TIM, PRE, ACIM[i]) +- mpz_fdiv_q_2exp(PRE, TRE, wp) +- mpz_fdiv_q_2exp(PIM, TIM, wp) +- +- for i in range(bcomplex): +- sig_check() +- mpz_mul(URE, BCRE[i], BCRE[i]) +- mpz_addmul(URE, BCIM[i], BCIM[i]) +- mpz_mul(TRE, PRE, BCRE[i]) +- mpz_addmul(TRE, PIM, BCIM[i]) +- mpz_mul(TIM, PIM, BCRE[i]) +- mpz_submul(TIM, PRE, BCIM[i]) +- mpz_mul_2exp(PRE, TRE, wp) +- mpz_fdiv_q(PRE, PRE, URE) +- mpz_mul_2exp(PIM, TIM, wp) +- mpz_fdiv_q(PIM, PIM, URE) +- else: +- mpz_mul(PRE, PRE, MUL) +- mpz_mul(PRE, PRE, ZRE) +- mpz_fdiv_q_2exp(PRE, PRE, wp) +- mpz_fdiv_q(PRE, PRE, DIV) +- +- # Add product to sum +- if have_complex: +- mpz_add(SRE, SRE, PRE) +- mpz_add(SIM, SIM, PIM) +- if mpz_cmpabs(PRE, HIGH) < 0 and mpz_cmpabs(PIM, HIGH) < 0: +- break +- else: +- mpz_add(SRE, SRE, PRE) +- if mpz_cmpabs(PRE, HIGH) < 0: +- break +- +- if n > MAX: +- from mpmath.libmp import NoConvergence +- raise NoConvergence('Hypergeometric series converges too slowly. Try increasing maxterms.') +- +- # +1 all parameters for next iteration +- for i in range(aint): mpz_add_ui(AINT[i], AINT[i], 1) +- for i in range(bint): mpz_add_ui(BINT[i], BINT[i], 1) +- for i in range(arat): mpz_add(AP[i], AP[i], AQ[i]) +- for i in range(brat): mpz_add(BP[i], BP[i], BQ[i]) +- for i in range(areal): mpz_add(AREAL[i], AREAL[i], one) +- for i in range(breal): mpz_add(BREAL[i], BREAL[i], one) +- for i in range(acomplex): mpz_add(ACRE[i], ACRE[i], one) +- for i in range(bcomplex): mpz_add(BCRE[i], BCRE[i], one) +- +- # Done +- if have_complex: +- MPF_set_fixed(a, SRE, wp, prec, ROUND_N) +- MPF_set_fixed(b, SIM, wp, prec, ROUND_N) +- if mpz_sgn(SRE): +- if mpz_sgn(SIM): +- magn = max(mpz_get_si(a.exp) + mpz_bitcount(a.man), +- mpz_get_si(b.exp) + mpz_bitcount(b.man)) +- else: +- magn = mpz_get_si(a.exp) + mpz_bitcount(a.man) +- elif mpz_sgn(SIM): +- magn = mpz_get_si(b.exp) + mpz_bitcount(b.man) +- else: +- magn = -wp +- else: +- MPF_set_fixed(a, SRE, wp, prec, ROUND_N) +- if mpz_sgn(SRE): +- magn = mpz_get_si(a.exp) + mpz_bitcount(a.man) +- else: +- magn = -wp +- +- mpz_clear(one) +- mpz_clear(SRE) +- mpz_clear(SIM) +- mpz_clear(PRE) +- mpz_clear(PIM) +- mpz_clear(ZRE) +- mpz_clear(ZIM) +- mpz_clear(MUL) +- mpz_clear(DIV) +- mpz_clear(HIGH) +- mpz_clear(LOW) +- mpz_clear(TRE) +- mpz_clear(TIM) +- mpz_clear(URE) +- mpz_clear(UIM) +- +- for i in range(aint): mpz_clear(AINT[i]) +- for i in range(bint): mpz_clear(BINT[i]) +- for i in range(arat): +- mpz_clear(AP[i]) +- mpz_clear(AQ[i]) +- for i in range(brat): +- mpz_clear(BP[i]) +- mpz_clear(BQ[i]) +- for i in range(areal): mpz_clear(AREAL[i]) +- for i in range(breal): mpz_clear(BREAL[i]) +- for i in range(acomplex): +- mpz_clear(ACRE[i]) +- mpz_clear(ACIM[i]) +- for i in range(bcomplex): +- mpz_clear(BCRE[i]) +- mpz_clear(BCIM[i]) +- +- return have_complex, magn +diff --git a/src/sage/libs/mpmath/ext_libmp.pyx b/src/sage/libs/mpmath/ext_libmp.pyx +deleted file mode 100644 +index 487a12d45bc..00000000000 +--- a/src/sage/libs/mpmath/ext_libmp.pyx ++++ /dev/null +@@ -1,230 +0,0 @@ +-""" +-Faster versions of some key functions in mpmath.libmp +-""" +-from sage.libs.mpmath.ext_impl cimport * +-from sage.libs.gmp.all cimport * +- +-# the next line is used by mpmath +-from sage.libs.mpmath.ext_impl import exp_fixed, cos_sin_fixed, log_int_fixed +- +-# Note: not thread-safe +-cdef MPF tmp1 +-cdef MPF tmp2 +-MPF_init(&tmp1) +-MPF_init(&tmp2) +- +- +-def mpf_add(tuple x, tuple y, int prec=0, str rnd='d'): +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- MPF_set_tuple(&tmp2, y) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_add(&tmp1, &tmp1, &tmp2, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_sub(tuple x, tuple y, int prec=0, str rnd='d'): +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- MPF_set_tuple(&tmp2, y) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_sub(&tmp1, &tmp1, &tmp2, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_mul(tuple x, tuple y, int prec=0, str rnd='d'): +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- MPF_set_tuple(&tmp2, y) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_mul(&tmp1, &tmp1, &tmp2, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_div(tuple x, tuple y, int prec, str rnd='d'): +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- MPF_set_tuple(&tmp2, y) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_div(&tmp1, &tmp1, &tmp2, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_sqrt(tuple x, int prec, str rnd='d'): +- """ +- Compute sqrt(x) with mpf value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpf_sqrt, from_float, to_float +- sage: x = from_float(2) +- sage: y = mpf_sqrt(x, 53, 'n') +- sage: to_float(y) +- 1.4142135623730951 +- """ +- if x[0]: +- import mpmath.libmp as libmp +- raise libmp.ComplexResult("square root of a negative number") +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_sqrt(&tmp1, &tmp1, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_log(tuple x, int prec, str rnd='d'): +- """ +- Compute log(x) with mpf value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpf_log, from_float, to_float +- sage: x = from_float(2) +- sage: y = mpf_log(x, 53, 'n') +- sage: to_float(y) +- 0.6931471805599453 +- """ +- if x[0]: +- import mpmath.libmp as libmp +- raise libmp.ComplexResult("logarithm of a negative number") +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_log(&tmp1, &tmp1, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_exp(tuple x, int prec, str rnd='d'): +- """ +- Compute exp(x) with mpf value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpf_exp, from_float, to_float +- sage: x = from_float(2) +- sage: z = mpf_exp(x, 53, 'n') +- sage: to_float(z) +- 7.38905609893065 +- """ +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_exp(&tmp1, &tmp1, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_cos(tuple x, int prec, str rnd='d'): +- """ +- Compute cos(x) with mpf value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpf_cos, from_float, to_float +- sage: x = from_float(1) +- sage: y = mpf_cos(x, 53, 'n') +- sage: to_float(y) +- 0.5403023058681398 +- """ +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_cos(&tmp1, &tmp1, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpf_sin(tuple x, int prec, str rnd='d'): +- """ +- Compute sin(x) with mpf value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpf_sin, from_float, to_float +- sage: x = from_float(1) +- sage: y = mpf_sin(x, 53, 'n') +- sage: to_float(y) +- 0.8414709848078965 +- """ +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_sin(&tmp1, &tmp1, opts) +- return MPF_to_tuple(&tmp1) +- +- +-def mpc_sqrt(tuple z, int prec, str rnd='d'): +- """ +- Compute sqrt(z) with mpc value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpc_sqrt, from_float, to_float +- sage: z = from_float(-2), from_float(0) +- sage: re, im = mpc_sqrt(z, 53, 'n') +- sage: to_float(re), to_float(im) +- (0.0, 1.4142135623730951) +- """ +- cdef tuple a, b +- cdef MPopts opts +- a, b = z +- MPF_set_tuple(&tmp1, a) +- MPF_set_tuple(&tmp2, b) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_complex_sqrt(&tmp1, &tmp2, &tmp1, &tmp2, opts) +- return MPF_to_tuple(&tmp1), MPF_to_tuple(&tmp2) +- +- +-def mpc_exp(tuple z, int prec, str rnd='d'): +- """ +- Compute exp(z) with mpc value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpc_exp, from_float, to_float +- sage: z = from_float(0), from_float(1) +- sage: re, im = mpc_exp(z, 53, 'n') +- sage: to_float(re), to_float(im) +- (0.5403023058681398, 0.8414709848078965) +- """ +- cdef tuple a, b +- cdef MPopts opts +- a, b = z +- MPF_set_tuple(&tmp1, a) +- MPF_set_tuple(&tmp2, b) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- MPF_complex_exp(&tmp1, &tmp2, &tmp1, &tmp2, opts) +- return MPF_to_tuple(&tmp1), MPF_to_tuple(&tmp2) +- +- +-def mpf_pow(tuple x, tuple y, int prec, str rnd='d'): +- """ +- Compute x ^ y with mpf value tuples. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import mpf_pow, from_float, to_float +- sage: x = from_float(2) +- sage: y = from_float(3) +- sage: z = mpf_pow(x, y, 53, 'n') +- sage: to_float(z) +- 8.0 +- """ +- cdef MPopts opts +- MPF_set_tuple(&tmp1, x) +- MPF_set_tuple(&tmp2, y) +- opts.rounding = rndmode_from_python(rnd) +- opts.prec = prec +- if MPF_pow(&tmp1, &tmp1, &tmp2, opts): +- import mpmath.libmp as libmp +- raise libmp.ComplexResult("negative number raised to a fractional power") +- return MPF_to_tuple(&tmp1) +diff --git a/src/sage/libs/mpmath/ext_main.pxd b/src/sage/libs/mpmath/ext_main.pxd +deleted file mode 100644 +index 8a3bf740b0e..00000000000 +--- a/src/sage/libs/mpmath/ext_main.pxd ++++ /dev/null +@@ -1 +0,0 @@ +-from sage.libs.mpmath.ext_impl cimport * +diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx +deleted file mode 100644 +index f8c4420f2f4..00000000000 +--- a/src/sage/libs/mpmath/ext_main.pyx ++++ /dev/null +@@ -1,2638 +0,0 @@ +-""" +-mpmath floating-point numbers +- +-Implements mpf and mpc types, with binary operations and support +-for interaction with other types. Also implements the main +-context class, and related utilities. +-""" +- +-#***************************************************************************** +-# 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 2 of the License, or +-# (at your option) any later version. +-# http://www.gnu.org/licenses/ +-#***************************************************************************** +- +-from cpython.long cimport * +-from cpython.float cimport * +-from cpython.complex cimport * +-from cpython.number cimport * +- +-from cysignals.signals cimport sig_check +- +-from sage.ext.stdsage cimport PY_NEW +- +-from sage.libs.gmp.all cimport * +-from sage.rings.integer cimport Integer +- +-DEF ROUND_N = 0 +-DEF ROUND_F = 1 +-DEF ROUND_C = 2 +-DEF ROUND_D = 3 +-DEF ROUND_U = 4 +-DEF S_NORMAL = 0 +-DEF S_ZERO = 1 +-DEF S_NZERO = 2 +-DEF S_INF = 3 +-DEF S_NINF = 4 +-DEF S_NAN = 5 +- +-from sage.libs.mpmath.ext_impl cimport * +- +-import mpmath.rational as rationallib +-import mpmath.libmp as libmp +-import mpmath.function_docs as function_docs +-from mpmath.libmp import to_str +-from mpmath.libmp import repr_dps, prec_to_dps, dps_to_prec +- +-DEF OP_ADD = 0 +-DEF OP_SUB = 1 +-DEF OP_MUL = 2 +-DEF OP_DIV = 3 +-DEF OP_POW = 4 +-DEF OP_MOD = 5 +-DEF OP_RICHCMP = 6 +-DEF OP_EQ = (OP_RICHCMP + 2) +-DEF OP_NE = (OP_RICHCMP + 3) +-DEF OP_LT = (OP_RICHCMP + 0) +-DEF OP_GT = (OP_RICHCMP + 4) +-DEF OP_LE = (OP_RICHCMP + 1) +-DEF OP_GE = (OP_RICHCMP + 5) +- +-cdef MPopts opts_exact +-cdef MPopts opts_double_precision +-cdef MPopts opts_mini_prec +- +-opts_exact.prec = 0 +-opts_exact.rounding = ROUND_N +-opts_double_precision.prec = 53 +-opts_double_precision.rounding = ROUND_N +-opts_mini_prec.prec = 5 +-opts_mini_prec.rounding = ROUND_D +- +-cdef MPF MPF_C_0 +-cdef MPF MPF_C_1 +-cdef MPF MPF_C_2 +- +-MPF_init(&MPF_C_0) +-MPF_set_zero(&MPF_C_0) +-MPF_init(&MPF_C_1) +-MPF_set_si(&MPF_C_1, 1) +-MPF_init(&MPF_C_2) +-MPF_set_si(&MPF_C_2, 2) +- +-# Temporaries used for operands in binary operations +-cdef mpz_t tmp_mpz +-mpz_init(tmp_mpz) +- +-cdef MPF tmp1 +-cdef MPF tmp2 +-cdef MPF tmp_opx_re +-cdef MPF tmp_opx_im +-cdef MPF tmp_opy_re +-cdef MPF tmp_opy_im +- +-MPF_init(&tmp1) +-MPF_init(&tmp2) +-MPF_init(&tmp_opx_re) +-MPF_init(&tmp_opx_im) +-MPF_init(&tmp_opy_re) +-MPF_init(&tmp_opy_im) +- +-cdef class Context +-cdef class mpnumber +-cdef class mpf_base +-cdef class mpf +-cdef class mpc +-cdef class constant +-cdef class wrapped_libmp_function +-cdef class wrapped_specfun +- +-cdef __isint(MPF *v): +- return v.special == S_ZERO or (v.special == S_NORMAL and mpz_sgn(v.exp) >= 0) +- +-cdef int MPF_set_any(MPF *re, MPF *im, x, MPopts opts, bint str_tuple_ok) except -1: +- """ +- Set re + im*i = x, where x is any Python number. +- +- Returns 0 if unable to coerce x; 1 if x is real and re was set; +- 2 if x is complex and both re and im were set. +- +- If str_tuple_ok=True, strings and tuples are accepted and converted +- (useful for parsing arguments, but not for arithmetic operands). +- """ +- if isinstance(x, mpf): +- MPF_set(re, &(x).value) +- return 1 +- if isinstance(x, mpc): +- MPF_set(re, &(x).re) +- MPF_set(im, &(x).im) +- return 2 +- if isinstance(x, (int, Integer)): +- MPF_set_int(re, x) +- return 1 +- if isinstance(x, float): +- MPF_set_double(re, x) +- return 1 +- if isinstance(x, complex): +- MPF_set_double(re, x.real) +- MPF_set_double(im, x.imag) +- return 2 +- if isinstance(x, constant): +- MPF_set_tuple(re, x.func(opts.prec, rndmode_to_python(opts.rounding))) +- return 1 +- if hasattr(x, "_mpf_"): +- MPF_set_tuple(re, x._mpf_) +- return 1 +- if hasattr(x, "_mpc_"): +- r, i = x._mpc_ +- MPF_set_tuple(re, r) +- MPF_set_tuple(im, i) +- return 2 +- if hasattr(x, "_mpmath_"): +- return MPF_set_any(re, im, x._mpmath_(opts.prec, +- rndmode_to_python(opts.rounding)), opts, False) +- if isinstance(x, rationallib.mpq): +- p, q = x._mpq_ +- MPF_set_int(re, p) +- MPF_set_int(im, q) +- MPF_div(re, re, im, opts) +- #MPF_set_tuple(re, libmp.from_rational(p, q, opts.prec, +- # rndmode_to_python(opts.rounding))) +- return 1 +- if hasattr(x, '_mpi_'): +- a, b = x._mpi_ +- if a == b: +- MPF_set_tuple(re, a) +- return 1 +- raise ValueError("can only create mpf from zero-width interval") +- if str_tuple_ok: +- if isinstance(x, tuple): +- if len(x) == 2: +- MPF_set_man_exp(re, x[0], x[1]) +- return 1 +- elif len(x) == 4: +- MPF_set_tuple(re, x) +- return 1 +- if isinstance(x, str): +- try: +- st = libmp.from_str(x, opts.prec, +- rndmode_to_python(opts.rounding)) +- except ValueError: +- return 0 +- MPF_set_tuple(re, st) +- return 1 +- return 0 +- +-cdef binop(int op, x, y, MPopts opts): +- cdef int typx +- cdef int typy +- cdef MPF xre, xim, yre, yim +- cdef mpf rr +- cdef mpc rc +- cdef MPopts altopts +- +- if isinstance(x, mpf): +- xre = (x).value +- typx = 1 +- elif isinstance(x, mpc): +- xre = (x).re +- xim = (x).im +- typx = 2 +- else: +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, False) +- if typx == 0: +- return NotImplemented +- xre = tmp_opx_re +- xim = tmp_opx_im +- +- if isinstance(y, mpf): +- yre = (y).value +- typy = 1 +- elif isinstance(y, mpc): +- yre = (y).re +- yim = (y).im +- typy = 2 +- else: +- typy = MPF_set_any(&tmp_opy_re, &tmp_opy_im, y, opts, False) +- if typy == 0: +- return NotImplemented +- yre = tmp_opy_re +- yim = tmp_opy_im +- +- if op == OP_ADD: +- if typx == 1 and typy == 1: +- # Real result +- rr = mpf.__new__(mpf) +- MPF_add(&rr.value, &xre, &yre, opts) +- return rr +- else: +- # Complex result +- rc = mpc.__new__(mpc) +- MPF_add(&rc.re, &xre, &yre, opts) +- if typx == 1: +- MPF_set(&rc.im, &yim) +- #MPF_normalize(&rc.im, opts) +- elif typy == 1: +- MPF_set(&rc.im, &xim) +- #MPF_normalize(&rc.im, opts) +- else: +- MPF_add(&rc.im, &xim, &yim, opts) +- return rc +- +- elif op == OP_SUB: +- if typx == 1 and typy == 1: +- # Real result +- rr = mpf.__new__(mpf) +- MPF_sub(&rr.value, &xre, &yre, opts) +- return rr +- else: +- # Complex result +- rc = mpc.__new__(mpc) +- MPF_sub(&rc.re, &xre, &yre, opts) +- if typx == 1: +- MPF_neg(&rc.im, &yim) +- MPF_normalize(&rc.im, opts) +- elif typy == 1: +- MPF_set(&rc.im, &xim) +- MPF_normalize(&rc.im, opts) +- else: +- MPF_sub(&rc.im, &xim, &yim, opts) +- return rc +- +- elif op == OP_MUL: +- if typx == 1 and typy == 1: +- # Real result +- rr = mpf.__new__(mpf) +- MPF_mul(&rr.value, &xre, &yre, opts) +- return rr +- else: +- # Complex result +- rc = mpc.__new__(mpc) +- if typx == 1: +- MPF_mul(&rc.re, &yre, &xre, opts) +- MPF_mul(&rc.im, &yim, &xre, opts) +- elif typy == 1: +- MPF_mul(&rc.re, &xre, &yre, opts) +- MPF_mul(&rc.im, &xim, &yre, opts) +- else: +- # a*c - b*d +- MPF_mul(&rc.re, &xre, &yre, opts_exact) +- MPF_mul(&tmp1, &xim, &yim, opts_exact) +- MPF_sub(&rc.re, &rc.re, &tmp1, opts) +- # a*d + b*c +- MPF_mul(&rc.im, &xre, &yim, opts_exact) +- MPF_mul(&tmp1, &xim, &yre, opts_exact) +- MPF_add(&rc.im, &rc.im, &tmp1, opts) +- return rc +- +- elif op == OP_DIV: +- if typx == 1 and typy == 1: +- # Real result +- rr = mpf.__new__(mpf) +- MPF_div(&rr.value, &xre, &yre, opts) +- return rr +- else: +- rc = mpc.__new__(mpc) +- if typy == 1: +- MPF_div(&rc.re, &xre, &yre, opts) +- MPF_div(&rc.im, &xim, &yre, opts) +- else: +- if typx == 1: +- xim = MPF_C_0 +- altopts = opts +- altopts.prec += 10 +- # m = c*c + d*d +- MPF_mul(&tmp1, &yre, &yre, opts_exact) +- MPF_mul(&tmp2, &yim, &yim, opts_exact) +- MPF_add(&tmp1, &tmp1, &tmp2, altopts) +- # (a*c+b*d)/m +- MPF_mul(&rc.re, &xre, &yre, opts_exact) +- MPF_mul(&tmp2, &xim, &yim, opts_exact) +- MPF_add(&rc.re, &rc.re, &tmp2, altopts) +- MPF_div(&rc.re, &rc.re, &tmp1, opts) +- # (b*c-a*d)/m +- MPF_mul(&rc.im, &xim, &yre, opts_exact) +- MPF_mul(&tmp2, &xre, &yim, opts_exact) +- MPF_sub(&rc.im, &rc.im, &tmp2, altopts) +- MPF_div(&rc.im, &rc.im, &tmp1, opts) +- return rc +- +- elif op == OP_POW: +- if typx == 1 and typy == 1: +- rr = mpf.__new__(mpf) +- if not MPF_pow(&rr.value, &xre, &yre, opts): +- return rr +- if typx == 1: xim = MPF_C_0 +- if typy == 1: yim = MPF_C_0 +- rc = mpc.__new__(mpc) +- MPF_complex_pow(&rc.re, &rc.im, &xre, &xim, &yre, &yim, opts) +- return rc +- +- elif op == OP_MOD: +- if typx != 1 or typx != 1: +- raise TypeError("mod for complex numbers") +- xret = MPF_to_tuple(&xre) +- yret = MPF_to_tuple(&yre) +- v = libmp.mpf_mod(xret, yret, opts.prec, rndmode_to_python(opts.rounding)) +- rr = mpf.__new__(mpf) +- MPF_set_tuple(&rr.value, v) +- return rr +- +- elif op == OP_EQ: +- if typx == 1 and typy == 1: +- return MPF_eq(&xre, &yre) +- if typx == 1: +- return MPF_eq(&xre, &yre) and MPF_eq(&yim, &MPF_C_0) +- if typy == 1: +- return MPF_eq(&xre, &yre) and MPF_eq(&xim, &MPF_C_0) +- return MPF_eq(&xre, &yre) and MPF_eq(&xim, &yim) +- +- elif op == OP_NE: +- if typx == 1 and typy == 1: +- return MPF_ne(&xre, &yre) +- if typx == 1: +- return MPF_ne(&xre, &yre) or MPF_ne(&yim, &MPF_C_0) +- if typy == 1: +- return MPF_ne(&xre, &yre) or MPF_ne(&xim, &MPF_C_0) +- return MPF_ne(&xre, &yre) or MPF_ne(&xim, &yim) +- +- elif op == OP_LT: +- if typx != 1 or typy != 1: +- raise ValueError("cannot compare complex numbers") +- return MPF_lt(&xre, &yre) +- +- elif op == OP_GT: +- if typx != 1 or typy != 1: +- raise ValueError("cannot compare complex numbers") +- return MPF_gt(&xre, &yre) +- +- elif op == OP_LE: +- if typx != 1 or typy != 1: +- raise ValueError("cannot compare complex numbers") +- return MPF_le(&xre, &yre) +- +- elif op == OP_GE: +- if typx != 1 or typy != 1: +- raise ValueError("cannot compare complex numbers") +- return MPF_ge(&xre, &yre) +- +- return NotImplemented +- +- +-cdef MPopts global_opts +- +-global_context = None +- +-cdef class Context: +- cdef public mpf, mpc, constant # , def_mp_function +- cdef public trap_complex +- cdef public pretty +- +- def __cinit__(ctx): +- """ +- At present, only a single global context should exist:: +- +- sage: from mpmath import mp +- sage: type(mp) +- +- """ +- global global_opts, global_context +- global_opts = opts_double_precision +- global_context = ctx +- ctx.mpf = mpf +- ctx.mpc = mpc +- ctx.constant = constant +- #ctx.def_mp_function = def_mp_function +- ctx._mpq = rationallib.mpq +- +- def default(ctx): +- """ +- Set defaults. +- +- TESTS:: +- +- sage: import mpmath +- sage: mpmath.mp.prec = 100 +- sage: mpmath.mp.default() +- sage: mpmath.mp.prec +- 53 +- """ +- global global_opts +- global_opts = opts_double_precision +- ctx.trap_complex = False +- ctx.pretty = False +- +- def _get_prec(ctx): +- """ +- Controls the working precision in bits:: +- +- sage: from mpmath import mp +- sage: mp.prec = 100 +- sage: mp.prec +- 100 +- sage: mp.dps +- 29 +- sage: mp.prec = 53 +- """ +- return global_opts.prec +- +- def _set_prec(ctx, prec): +- """ +- Controls the working precision in bits:: +- +- sage: from mpmath import mp +- sage: mp.prec = 100 +- sage: mp.prec +- 100 +- sage: mp.dps +- 29 +- sage: mp.prec = 53 +- """ +- global_opts.prec = prec +- +- def _set_dps(ctx, n): +- """ +- Controls the working precision in decimal digits:: +- +- sage: from mpmath import mp +- sage: mp.dps = 100 +- sage: mp.prec +- 336 +- sage: mp.dps +- 100 +- sage: mp.prec = 53 +- """ +- global_opts.prec = dps_to_prec(int(n)) +- +- def _get_dps(ctx): +- """ +- Controls the working precision in decimal digits:: +- +- sage: from mpmath import mp +- sage: mp.dps = 100 +- sage: mp.prec +- 336 +- sage: mp.dps +- 100 +- sage: mp.prec = 53 +- """ +- return prec_to_dps(global_opts.prec) +- +- dps = property(_get_dps, _set_dps, doc=_get_dps.__doc__) +- prec = property(_get_prec, _set_prec, doc=_get_dps.__doc__) +- _dps = property(_get_dps, _set_dps, doc=_get_dps.__doc__) +- _prec = property(_get_prec, _set_prec, doc=_get_dps.__doc__) +- +- def _get_prec_rounding(ctx): +- """ +- Return the precision and rounding mode:: +- +- sage: from mpmath import mp +- sage: mp._get_prec_rounding() +- (53, 'n') +- """ +- return global_opts.prec, rndmode_to_python(global_opts.rounding) +- +- _prec_rounding = property(_get_prec_rounding) +- +- cpdef mpf make_mpf(ctx, tuple v): +- """ +- Create an mpf from tuple data:: +- +- sage: import mpmath +- sage: float(mpmath.mp.make_mpf((0,1,-1,1))) +- 0.5 +- """ +- cdef mpf x +- x = mpf.__new__(mpf) +- MPF_set_tuple(&x.value, v) +- return x +- +- cpdef mpc make_mpc(ctx, tuple v): +- """ +- Create an mpc from tuple data:: +- +- sage: import mpmath +- sage: complex(mpmath.mp.make_mpc(((0,1,-1,1), (1,1,-2,1)))) +- (0.5-0.25j) +- """ +- cdef mpc x +- x = mpc.__new__(mpc) +- MPF_set_tuple(&x.re, v[0]) +- MPF_set_tuple(&x.im, v[1]) +- return x +- +- def convert(ctx, x, strings=True): +- """ +- Convert *x* to an ``mpf``, ``mpc`` or ``mpi``. If *x* is of type ``mpf``, +- ``mpc``, ``int``, ``float``, ``complex``, the conversion +- will be performed losslessly. +- +- If *x* is a string, the result will be rounded to the present +- working precision. Strings representing fractions or complex +- numbers are permitted. +- +- TESTS:: +- +- sage: from mpmath import mp, convert +- sage: mp.dps = 15; mp.pretty = False +- sage: convert(3.5) +- mpf('3.5') +- sage: convert('2.1') +- mpf('2.1000000000000001') +- sage: convert('3/4') +- mpf('0.75') +- sage: convert('2+3j') +- mpc(real='2.0', imag='3.0') +- """ +- cdef mpf rr +- cdef mpc rc +- if isinstance(x, mpnumber): +- return x +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, strings) +- if typx == 1: +- rr = mpf.__new__(mpf) +- MPF_set(&rr.value, &tmp_opx_re) +- return rr +- if typx == 2: +- rc = mpc.__new__(mpc) +- MPF_set(&rc.re, &tmp_opx_re) +- MPF_set(&rc.im, &tmp_opx_im) +- return rc +- return ctx._convert_fallback(x, strings) +- +- def isnan(ctx, x): +- """ +- For an ``mpf`` *x*, determines whether *x* is not-a-number (nan). +- +- TESTS:: +- +- sage: from mpmath import isnan, nan +- sage: isnan(nan), isnan(3) +- (True, False) +- """ +- cdef int s, t, typ +- if isinstance(x, mpf): +- return (x).value.special == S_NAN +- if isinstance(x, mpc): +- s = (x).re.special +- t = (x).im.special +- return s == S_NAN or t == S_NAN +- if isinstance(x, (int, Integer, rationallib.mpq)): +- return False +- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0) +- if typ == 1: +- s = tmp_opx_re.special +- return s == S_NAN +- if typ == 2: +- s = tmp_opx_re.special +- t = tmp_opx_im.special +- return s == S_NAN or t == S_NAN +- raise TypeError("isnan() needs a number as input") +- +- def isinf(ctx, x): +- """ +- Return *True* if the absolute value of *x* is infinite; +- otherwise return *False*. +- +- TESTS:: +- +- sage: from mpmath import isinf, inf, mpc +- sage: isinf(inf) +- True +- sage: isinf(-inf) +- True +- sage: isinf(3) +- False +- sage: isinf(3+4j) +- False +- sage: isinf(mpc(3,inf)) +- True +- sage: isinf(mpc(inf,3)) +- True +- """ +- cdef int s, t, typ +- if isinstance(x, mpf): +- s = (x).value.special +- return s == S_INF or s == S_NINF +- if isinstance(x, mpc): +- s = (x).re.special +- t = (x).im.special +- return s == S_INF or s == S_NINF or t == S_INF or t == S_NINF +- if isinstance(x, (int, Integer, rationallib.mpq)): +- return False +- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0) +- if typ == 1: +- s = tmp_opx_re.special +- return s == S_INF or s == S_NINF +- if typ == 2: +- s = tmp_opx_re.special +- t = tmp_opx_im.special +- return s == S_INF or s == S_NINF or t == S_INF or t == S_NINF +- raise TypeError("isinf() needs a number as input") +- +- def isnormal(ctx, x): +- """ +- Determine whether *x* is "normal" in the sense of floating-point +- representation; that is, return *False* if *x* is zero, an +- infinity or NaN; otherwise return *True*. By extension, a +- complex number *x* is considered "normal" if its magnitude is +- normal. +- +- TESTS:: +- +- sage: from mpmath import isnormal, inf, nan, mpc +- sage: isnormal(3) +- True +- sage: isnormal(0) +- False +- sage: isnormal(inf); isnormal(-inf); isnormal(nan) +- False +- False +- False +- sage: isnormal(0+0j) +- False +- sage: isnormal(0+3j) +- True +- sage: isnormal(mpc(2,nan)) +- False +- """ +- # TODO: optimize this +- if hasattr(x, "_mpf_"): +- return bool(x._mpf_[1]) +- if hasattr(x, "_mpc_"): +- re, im = x._mpc_ +- re_normal = bool(re[1]) +- im_normal = bool(im[1]) +- if re == libmp.fzero: return im_normal +- if im == libmp.fzero: return re_normal +- return re_normal and im_normal +- if isinstance(x, (int, Integer, rationallib.mpq)): +- return bool(x) +- x = ctx.convert(x) +- if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'): +- return ctx.isnormal(x) +- raise TypeError("isnormal() needs a number as input") +- +- def isint(ctx, x, gaussian=False): +- """ +- Return *True* if *x* is integer-valued; otherwise return +- *False*. +- +- TESTS:: +- +- sage: from mpmath import isint, mpf, inf +- sage: isint(3) +- True +- sage: isint(mpf(3)) +- True +- sage: isint(3.2) +- False +- sage: isint(inf) +- False +- +- Optionally, Gaussian integers can be checked for:: +- +- sage: isint(3+0j) +- True +- sage: isint(3+2j) +- False +- sage: isint(3+2j, gaussian=True) +- True +- """ +- cdef MPF v +- cdef MPF w +- cdef int typ +- if isinstance(x, (int, Integer)): +- return True +- if isinstance(x, mpf): +- v = (x).value +- return __isint(&v) +- if isinstance(x, mpc): +- v = (x).re +- w = (x).im +- if gaussian: +- return __isint(&v) and __isint(&w) +- return (w.special == S_ZERO) and __isint(&v) +- if isinstance(x, rationallib.mpq): +- p, q = x._mpq_ +- return not (p % q) +- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0) +- if typ == 1: +- return __isint(&tmp_opx_re) +- if typ == 2: +- v = tmp_opx_re +- w = tmp_opx_im +- if gaussian: +- return __isint(&v) and __isint(&w) +- return (w.special == S_ZERO) and __isint(&v) +- raise TypeError("isint() needs a number as input") +- +- def fsum(ctx, terms, bint absolute=False, bint squared=False): +- """ +- Calculate a sum containing a finite number of terms (for infinite +- series, see :func:`nsum`). The terms will be converted to +- mpmath numbers. For len(terms) > 2, this function is generally +- faster and produces more accurate results than the builtin +- Python function :func:`sum`. +- +- With ``squared=True`` each term is squared, and with ``absolute=True`` +- the absolute value of each term is used. +- +- TESTS:: +- +- sage: from mpmath import mp, fsum +- sage: mp.dps = 15; mp.pretty = False +- sage: fsum([1, 2, 0.5, 7]) +- mpf('10.5') +- +- Check that the regression from `mpmath/issues/723 `__ +- has been fixed:: +- +- sage: from mpmath import * +- sage: mp.dps=16 +- sage: zeta(-0.01 + 1000j) +- mpc(real='-8.9714595...', imag='8.7321793...') +- """ +- cdef MPF sre, sim, tre, tim, tmp +- cdef mpf rr +- cdef mpc rc +- cdef MPopts workopts +- cdef int styp, ttyp +- workopts = global_opts +- workopts.prec = workopts.prec * 2 + 50 +- workopts.rounding = ROUND_D +- unknown = global_context.zero +- try: +- sig_check() +- MPF_init(&sre) +- MPF_init(&sim) +- MPF_init(&tre) +- MPF_init(&tim) +- MPF_init(&tmp) +- styp = 1 +- for term in terms: +- ttyp = MPF_set_any(&tre, &tim, term, workopts, 0) +- if ttyp == 0: +- if absolute: term = ctx.absmax(term) +- if squared: term = term**2 +- unknown += term +- continue +- if absolute: +- if squared: +- if ttyp == 1: +- MPF_mul(&tre, &tre, &tre, opts_exact) +- MPF_add(&sre, &sre, &tre, workopts) +- elif ttyp == 2: +- # |(a+bi)^2| = a^2+b^2 +- MPF_mul(&tre, &tre, &tre, opts_exact) +- MPF_add(&sre, &sre, &tre, workopts) +- MPF_mul(&tim, &tim, &tim, opts_exact) +- MPF_add(&sre, &sre, &tim, workopts) +- else: +- if ttyp == 1: +- MPF_abs(&tre, &tre) +- MPF_add(&sre, &sre, &tre, workopts) +- elif ttyp == 2: +- # |a+bi| = sqrt(a^2+b^2) +- MPF_mul(&tre, &tre, &tre, opts_exact) +- MPF_mul(&tim, &tim, &tim, opts_exact) +- MPF_add(&tre, &tre, &tim, workopts) +- MPF_sqrt(&tre, &tre, workopts) +- MPF_add(&sre, &sre, &tre, workopts) +- elif squared: +- if ttyp == 1: +- MPF_mul(&tre, &tre, &tre, opts_exact) +- MPF_add(&sre, &sre, &tre, workopts) +- elif ttyp == 2: +- # (a+bi)^2 = a^2-b^2 + 2i*ab +- MPF_mul(&tmp, &tre, &tim, opts_exact) +- MPF_mul(&tmp, &tmp, &MPF_C_2, opts_exact) +- MPF_add(&sim, &sim, &tmp, workopts) +- MPF_mul(&tre, &tre, &tre, opts_exact) +- MPF_add(&sre, &sre, &tre, workopts) +- MPF_mul(&tim, &tim, &tim, opts_exact) +- MPF_sub(&sre, &sre, &tim, workopts) +- styp = 2 +- else: +- if ttyp == 1: +- MPF_add(&sre, &sre, &tre, workopts) +- elif ttyp == 2: +- MPF_add(&sre, &sre, &tre, workopts) +- MPF_add(&sim, &sim, &tim, workopts) +- styp = 2 +- MPF_clear(&tre) +- MPF_clear(&tim) +- if styp == 1: +- rr = mpf.__new__(mpf) +- MPF_set(&rr.value, &sre) +- MPF_clear(&sre) +- MPF_clear(&sim) +- MPF_normalize(&rr.value, global_opts) +- if unknown is not global_context.zero: +- return ctx._stupid_add(rr, unknown) +- return rr +- elif styp == 2: +- rc = mpc.__new__(mpc) +- MPF_set(&rc.re, &sre) +- MPF_set(&rc.im, &sim) +- MPF_clear(&sre) +- MPF_clear(&sim) +- MPF_normalize(&rc.re, global_opts) +- MPF_normalize(&rc.im, global_opts) +- if unknown is not global_context.zero: +- return ctx._stupid_add(rc, unknown) +- return rc +- else: +- MPF_clear(&sre) +- MPF_clear(&sim) +- return +unknown +- except KeyboardInterrupt: +- raise KeyboardInterrupt('Ctrl-C pressed while running fsum') +- +- def fdot(ctx, A, B=None, bint conjugate=False): +- r""" +- Compute the dot product of the iterables `A` and `B`. +- +- .. MATH:: +- +- \sum_{k=0} A_k B_k. +- +- Alternatively, :func:`fdot` accepts a single iterable of pairs. +- In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent. +- +- The elements are automatically converted to mpmath numbers. +- +- TESTS:: +- +- sage: from mpmath import mp, fdot +- sage: mp.dps = 15; mp.pretty = False +- sage: A = [2, 1.5r, 3] +- sage: B = [1, -1, 2] +- sage: fdot(A, B) +- mpf('6.5') +- sage: list(zip(A, B)) +- [(2, 1), (1.5, -1), (3, 2)] +- sage: fdot(_) +- mpf('6.5') +- """ +- if B: +- A = zip(A, B) +- cdef MPF sre, sim, tre, tim, ure, uim, tmp +- cdef mpf rr +- cdef mpc rc +- cdef MPopts workopts +- cdef int styp, ttyp, utyp +- MPF_init(&sre) +- MPF_init(&sim) +- MPF_init(&tre) +- MPF_init(&tim) +- MPF_init(&ure) +- MPF_init(&uim) +- MPF_init(&tmp) +- workopts = global_opts +- workopts.prec = workopts.prec * 2 + 50 +- workopts.rounding = ROUND_D +- unknown = global_context.zero +- styp = 1 +- for a, b in A: +- ttyp = MPF_set_any(&tre, &tim, a, workopts, 0) +- utyp = MPF_set_any(&ure, &uim, b, workopts, 0) +- if utyp == 2 and conjugate: +- MPF_neg(&uim, &uim) +- if ttyp == 0 or utyp == 0: +- if conjugate: +- b = b.conj() +- unknown += a * b +- continue +- styp = max(styp, ttyp) +- styp = max(styp, utyp) +- if ttyp == 1: +- if utyp == 1: +- MPF_mul(&tre, &tre, &ure, opts_exact) +- MPF_add(&sre, &sre, &tre, workopts) +- elif utyp == 2: +- MPF_mul(&ure, &ure, &tre, opts_exact) +- MPF_mul(&uim, &uim, &tre, opts_exact) +- MPF_add(&sre, &sre, &ure, workopts) +- MPF_add(&sim, &sim, &uim, workopts) +- styp = 2 +- elif ttyp == 2: +- styp = 2 +- if utyp == 1: +- MPF_mul(&tre, &tre, &ure, opts_exact) +- MPF_mul(&tim, &tim, &ure, opts_exact) +- MPF_add(&sre, &sre, &tre, workopts) +- MPF_add(&sim, &sim, &tim, workopts) +- elif utyp == 2: +- MPF_mul(&tmp, &tre, &ure, opts_exact) +- MPF_add(&sre, &sre, &tmp, workopts) +- MPF_mul(&tmp, &tim, &uim, opts_exact) +- MPF_sub(&sre, &sre, &tmp, workopts) +- MPF_mul(&tmp, &tim, &ure, opts_exact) +- MPF_add(&sim, &sim, &tmp, workopts) +- MPF_mul(&tmp, &tre, &uim, opts_exact) +- MPF_add(&sim, &sim, &tmp, workopts) +- MPF_clear(&tre) +- MPF_clear(&tim) +- MPF_clear(&ure) +- MPF_clear(&uim) +- MPF_clear(&tmp) +- if styp == 1: +- rr = mpf.__new__(mpf) +- MPF_set(&rr.value, &sre) +- MPF_clear(&sre) +- MPF_clear(&sim) +- MPF_normalize(&rr.value, global_opts) +- if unknown is not global_context.zero: +- return ctx._stupid_add(rr, unknown) +- return rr +- elif styp == 2: +- rc = mpc.__new__(mpc) +- MPF_set(&rc.re, &sre) +- MPF_set(&rc.im, &sim) +- MPF_clear(&sre) +- MPF_clear(&sim) +- MPF_normalize(&rc.re, global_opts) +- MPF_normalize(&rc.im, global_opts) +- if unknown is not global_context.zero: +- return ctx._stupid_add(rc, unknown) +- return rc +- else: +- MPF_clear(&sre) +- MPF_clear(&sim) +- return +unknown +- +- # Doing a+b directly doesn't work with mpi, presumably due to +- # Cython trying to be clever with the operation resolution +- cdef _stupid_add(ctx, a, b): +- return a + b +- +- def _convert_param(ctx, x): +- """ +- Internal function for parsing a hypergeometric function parameter. +- +- This returns (T, x) where T = 'Z', 'Q', 'R', 'C' depending on the +- type of the parameter, and with x converted to the canonical +- mpmath type. +- +- TESTS:: +- +- sage: from mpmath import mp +- sage: x, T = mp._convert_param(3) +- sage: (x, type(x).__name__, T) +- (3, 'int', 'Z') +- sage: x, T = mp._convert_param(2.5) +- sage: (x, type(x).__name__, T) +- (mpq(5,2), 'mpq', 'Q') +- sage: x, T = mp._convert_param(2.3) +- sage: (str(x), type(x).__name__, T) +- ('2.3', 'mpf', 'R') +- sage: x, T = mp._convert_param(2+3j) +- sage: (x, type(x).__name__, T) +- (mpc(real='2.0', imag='3.0'), 'mpc', 'C') +- sage: mp.pretty = False +- """ +- cdef MPF v +- cdef bint ismpf, ismpc +- if isinstance(x, (int, Integer)): +- return int(x), 'Z' +- if isinstance(x, tuple): +- p, q = x +- p = int(p) +- q = int(q) +- if not p % q: +- return p // q, 'Z' +- return rationallib.mpq((p,q)), 'Q' +- if isinstance(x, str) and '/' in x: +- p, q = x.split('/') +- p = int(p) +- q = int(q) +- if not p % q: +- return p // q, 'Z' +- return rationallib.mpq((p,q)), 'Q' +- if isinstance(x, constant): +- return x, 'R' +- ismpf = isinstance(x, mpf) +- ismpc = isinstance(x, mpc) +- if not (ismpf or ismpc): +- x = global_context.convert(x) +- ismpf = isinstance(x, mpf) +- ismpc = isinstance(x, mpc) +- if not (ismpf or ismpc): +- return x, 'U' +- if ismpf: +- v = (x).value +- elif ismpc: +- if (x).im.special != S_ZERO: +- return x, 'C' +- x = (x).real +- v = (x).re +- # A real number +- if v.special == S_ZERO: +- return 0, 'Z' +- if v.special != S_NORMAL: +- return x, 'U' +- if mpz_sgn(v.exp) >= 0: +- return (mpzi(v.man) << mpzi(v.exp)), 'Z' +- if mpz_cmp_si(v.exp, -4) > 0: +- p = mpzi(v.man) +- q = 1 << (-mpzi(v.exp)) +- return rationallib.mpq((p,q)), 'Q' +- return x, 'R' +- +- def mag(ctx, x): +- """ +- Quick logarithmic magnitude estimate of a number. Returns an +- integer or infinity `m` such that `|x| <= 2^m`. It is not +- guaranteed that `m` is an optimal bound, but it will never +- be too large by more than 2 (and probably not more than 1). +- +- TESTS:: +- +- sage: from mpmath import * +- sage: mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2))) +- (4, 4, 4, 4) +- sage: mag(10j), mag(10+10j) +- (4, 5) +- sage: mag(0.01), int(ceil(log(0.01,2))) +- (-6, -6) +- sage: mag(0), mag(inf), mag(-inf), mag(nan) +- (mpf('-inf'), mpf('+inf'), mpf('+inf'), mpf('nan')) +- +- :: +- +- sage: class MyInt(int): +- ....: pass +- sage: class MyFloat(float): +- ....: pass +- sage: mag(MyInt(10)) +- 4 +- """ +- cdef int typ +- if isinstance(x, (int, Integer)): +- mpz_set_integer(tmp_opx_re.man, x) +- if mpz_sgn(tmp_opx_re.man) == 0: +- return global_context.ninf +- else: +- return mpz_sizeinbase(tmp_opx_re.man,2) +- if isinstance(x, rationallib.mpq): +- p, q = x._mpq_ +- mpz_set_integer(tmp_opx_re.man, int(p)) +- if mpz_sgn(tmp_opx_re.man) == 0: +- return global_context.ninf +- mpz_set_integer(tmp_opx_re.exp, int(q)) +- return 1 + mpz_sizeinbase(tmp_opx_re.man,2) + mpz_sizeinbase(tmp_opx_re.exp,2) +- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, False) +- if typ == 1: +- if tmp_opx_re.special == S_ZERO: +- return global_context.ninf +- if tmp_opx_re.special == S_INF or tmp_opx_re.special == S_NINF: +- return global_context.inf +- if tmp_opx_re.special != S_NORMAL: +- return global_context.nan +- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2)) +- return mpzi(tmp_opx_re.exp) +- if typ == 2: +- if tmp_opx_re.special == S_NAN or tmp_opx_im.special == S_NAN: +- return global_context.nan +- if tmp_opx_re.special == S_INF or tmp_opx_im.special == S_NINF or \ +- tmp_opx_im.special == S_INF or tmp_opx_im.special == S_NINF: +- return global_context.inf +- if tmp_opx_re.special == S_ZERO: +- if tmp_opx_im.special == S_ZERO: +- return global_context.ninf +- else: +- mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, mpz_sizeinbase(tmp_opx_im.man, 2)) +- return mpzi(tmp_opx_im.exp) +- elif tmp_opx_im.special == S_ZERO: +- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2)) +- return mpzi(tmp_opx_re.exp) +- mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, mpz_sizeinbase(tmp_opx_im.man, 2)) +- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2)) +- if mpz_cmp(tmp_opx_re.exp, tmp_opx_im.exp) >= 0: +- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, 1) +- return mpzi(tmp_opx_re.exp) +- else: +- mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, 1) +- return mpzi(tmp_opx_im.exp) +- raise TypeError("requires an mpf/mpc") +- +- def _wrap_libmp_function(ctx, mpf_f, mpc_f=None, mpi_f=None, doc=""): +- """ +- Create a high-level mpmath function from base functions working +- on mpf, mpc and mpi tuple data. +- +- TESTS:: +- +- sage: from mpmath import mp +- sage: mp.pretty = False +- sage: f = lambda x, prec, rnd: x +- sage: g = mp._wrap_libmp_function(f) +- sage: g(mp.mpf(2)) +- mpf('2.0') +- """ +- name = mpf_f.__name__[4:] +- doc = function_docs.__dict__.get(name, "Computes the %s of x" % doc) +- # workaround lack of closures in Cython +- f_cls = type(name, (wrapped_libmp_function,), {'__doc__':doc}) +- f = f_cls(mpf_f, mpc_f, mpi_f, doc) +- return f +- +- @classmethod +- def _wrap_specfun(cls, name, f, wrap): +- """ +- Add the given function as a method to the context object, +- optionally wrapping it to do automatic conversions and +- allocating a small number of guard bits to suppress +- typical roundoff error. +- +- TESTS:: +- +- sage: from mpmath import mp +- sage: mp._wrap_specfun("foo", lambda ctx, x: ctx.prec + x, True) +- sage: mp.pretty = False; mp.prec = 53 +- sage: mp.foo(5) # 53 + 10 guard bits + 5 +- mpf('68.0') +- """ +- doc = function_docs.__dict__.get(name, getattr(f, '__doc__', '')) +- if wrap: +- # workaround lack of closures in Cython +- f_wrapped_cls = type(name, (wrapped_specfun,), {'__doc__':doc}) +- f_wrapped = f_wrapped_cls(name, f) +- else: +- f_wrapped = f +- f_wrapped.__doc__ = doc +- setattr(cls, name, f_wrapped) +- +- cdef MPopts _fun_get_opts(ctx, kwargs) noexcept: +- """ +- Helper function that extracts precision and rounding information +- from kwargs, or returns the global working precision and rounding +- if no options are specified. +- """ +- cdef MPopts opts +- opts.prec = global_opts.prec +- opts.rounding = global_opts.rounding +- if kwargs: +- if 'prec' in kwargs: +- opts.prec = int(kwargs['prec']) +- if 'dps' in kwargs: +- opts.prec = libmp.dps_to_prec(int(kwargs['dps'])) +- if 'rounding' in kwargs: +- opts.rounding = rndmode_from_python(kwargs['rounding']) +- return opts +- +- def _sage_sqrt(ctx, x, **kwargs): +- """ +- Square root of an mpmath number x, using the Sage mpmath backend. +- +- TESTS:: +- +- sage: from mpmath import mp +- sage: mp.dps = 15 +- sage: print(mp.sqrt(2)) # indirect doctest +- 1.4142135623731 +- sage: print(mp.sqrt(-2)) +- (0.0 + 1.4142135623731j) +- sage: print(mp.sqrt(2+2j)) +- (1.55377397403004 + 0.643594252905583j) +- """ +- cdef MPopts opts +- cdef int typx +- cdef mpf rr +- cdef mpc rc +- cdef tuple rev, imv +- opts = ctx._fun_get_opts(kwargs) +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1) +- if typx == 1: +- rr = mpf.__new__(mpf) +- if MPF_sqrt(&rr.value, &tmp_opx_re, opts): +- rc = mpc.__new__(mpc) +- MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &MPF_C_0, opts) +- return rc +- return rr +- elif typx == 2: +- rc = mpc.__new__(mpc) +- MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) +- return rc +- else: +- raise NotImplementedError("unknown argument") +- +- def _sage_exp(ctx, x, **kwargs): +- """ +- Exponential function of an mpmath number x, using the Sage +- mpmath backend. +- +- EXAMPLES:: +- +- sage: from mpmath import mp +- sage: mp.dps = 15 +- sage: print(mp.exp(2)) # indirect doctest +- 7.38905609893065 +- sage: print(mp.exp(2+2j)) +- (-3.07493232063936 + 6.71884969742825j) +- """ +- cdef MPopts opts +- cdef int typx +- cdef mpf rr +- cdef mpc rc +- cdef tuple rev, imv +- opts = ctx._fun_get_opts(kwargs) +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1) +- if typx == 1: +- rr = mpf.__new__(mpf) +- MPF_exp(&rr.value, &tmp_opx_re, opts) +- return rr +- elif typx == 2: +- rc = mpc.__new__(mpc) +- MPF_complex_exp(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) +- return rc +- else: +- raise NotImplementedError("unknown argument") +- +- def _sage_cos(ctx, x, **kwargs): +- """ +- Cosine of an mpmath number x, using the Sage mpmath backend. +- +- EXAMPLES:: +- +- sage: from mpmath import mp +- sage: mp.dps = 15 +- sage: print(mp.cos(2)) # indirect doctest +- -0.416146836547142 +- sage: print(mp.cos(2+2j)) +- (-1.56562583531574 - 3.29789483631124j) +- """ +- cdef MPopts opts +- cdef int typx +- cdef mpf rr +- cdef mpc rc +- cdef tuple rev, imv +- opts = ctx._fun_get_opts(kwargs) +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) +- if typx == 1: +- rr = mpf.__new__(mpf) +- MPF_cos(&rr.value, &tmp_opx_re, opts) +- return rr +- elif typx == 2: +- rev = MPF_to_tuple(&tmp_opx_re) +- imv = MPF_to_tuple(&tmp_opx_im) +- cxu = libmp.mpc_cos((rev, imv), opts.prec, +- rndmode_to_python(opts.rounding)) +- rc = mpc.__new__(mpc) +- MPF_set_tuple(&rc.re, cxu[0]) +- MPF_set_tuple(&rc.im, cxu[1]) +- return rc +- else: +- raise NotImplementedError("unknown argument") +- +- def _sage_sin(ctx, x, **kwargs): +- """ +- Sine of an mpmath number x, using the Sage mpmath backend. +- +- EXAMPLES:: +- +- sage: from mpmath import mp +- sage: mp.dps = 15 +- sage: print(mp.sin(2)) # indirect doctest +- 0.909297426825682 +- sage: print(mp.sin(2+2j)) +- (3.42095486111701 - 1.50930648532362j) +- """ +- cdef MPopts opts +- cdef int typx +- cdef mpf rr +- cdef mpc rc +- cdef tuple rev, imv +- opts = ctx._fun_get_opts(kwargs) +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) +- if typx == 1: +- rr = mpf.__new__(mpf) +- MPF_sin(&rr.value, &tmp_opx_re, opts) +- return rr +- elif typx == 2: +- rev = MPF_to_tuple(&tmp_opx_re) +- imv = MPF_to_tuple(&tmp_opx_im) +- cxu = libmp.mpc_sin((rev, imv), opts.prec, +- rndmode_to_python(opts.rounding)) +- rc = mpc.__new__(mpc) +- MPF_set_tuple(&rc.re, cxu[0]) +- MPF_set_tuple(&rc.im, cxu[1]) +- return rc +- else: +- raise NotImplementedError("unknown argument") +- +- def _sage_ln(ctx, x, **kwargs): +- """ +- Natural logarithm of an mpmath number x, using the Sage mpmath backend. +- +- EXAMPLES:: +- +- sage: from mpmath import mp +- sage: print(mp.ln(2)) # indirect doctest +- 0.693147180559945 +- sage: print(mp.ln(-2)) +- (0.693147180559945 + 3.14159265358979j) +- sage: print(mp.ln(2+2j)) +- (1.03972077083992 + 0.785398163397448j) +- """ +- cdef MPopts opts +- cdef int typx +- cdef mpf rr +- cdef mpc rc +- cdef tuple rev, imv +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) +- prec = global_opts.prec +- rounding = rndmode_to_python(global_opts.rounding) +- opts.prec = global_opts.prec +- opts.rounding = global_opts.rounding +- if kwargs: +- if 'prec' in kwargs: opts.prec = int(kwargs['prec']) +- if 'dps' in kwargs: opts.prec = libmp.dps_to_prec(int(kwargs['dps'])) +- if 'rounding' in kwargs: opts.rounding = rndmode_from_python(kwargs['rounding']) +- if typx == 1: +- if MPF_sgn(&tmp_opx_re) < 0: +- rc = mpc.__new__(mpc) +- MPF_log(&rc.re, &tmp_opx_re, opts) +- MPF_set_pi(&rc.im, opts) +- return rc +- else: +- rr = mpf.__new__(mpf) +- MPF_log(&rr.value, &tmp_opx_re, opts) +- return rr +- elif typx == 2: +- rev = MPF_to_tuple(&tmp_opx_re) +- imv = MPF_to_tuple(&tmp_opx_im) +- cxu = libmp.mpc_log((rev, imv), opts.prec, rndmode_to_python(opts.rounding)) +- rc = mpc.__new__(mpc) +- MPF_set_tuple(&rc.re, cxu[0]) +- MPF_set_tuple(&rc.im, cxu[1]) +- return rc +- +- #rc = mpc.__new__(mpc) +- #MPF_complex_log(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) +- #return rc +- else: +- raise NotImplementedError("unknown argument") +- +- +-cdef class wrapped_libmp_function: +- +- cdef public mpf_f, mpc_f, mpi_f, name, __name__, __doc__ +- +- def __init__(self, mpf_f, mpc_f=None, mpi_f=None, doc=""): +- """ +- Create a high-level mpmath function from base functions working +- on mpf, mpc and mpi tuple data. +- +- TESTS:: +- +- sage: from sage.libs.mpmath.ext_main import wrapped_libmp_function +- sage: from mpmath import mp +- sage: from mpmath.libmp import mpf_exp, mpf_sqrt +- sage: f = lambda x, prec, rnd: mpf_exp(mpf_sqrt(x, prec, rnd), prec, rnd) +- sage: g = wrapped_libmp_function(f) +- sage: g(mp.mpf(3)) +- mpf('5.6522336740340915') +- sage: mp.exp(mp.sqrt(3)) +- mpf('5.6522336740340915') +- sage: g(mp.mpf(3), prec=10) +- mpf('5.65625') +- sage: g(mp.mpf(3), prec=10, rounding='u') +- mpf('5.65625') +- sage: g(mp.mpf(3), prec=10, rounding='d') +- mpf('5.640625') +- """ +- self.mpf_f = mpf_f +- self.mpc_f = mpc_f +- self.mpi_f = mpi_f +- self.name = self.__name__ = mpf_f.__name__[4:] +- self.__doc__ = function_docs.__dict__.get(self.name, "Computes the %s of x" % doc) +- +- def __call__(self, x, **kwargs): +- """ +- A wrapped mpmath library function performs automatic +- conversions and uses the default working precision +- unless overridden:: +- +- sage: from mpmath import mp +- sage: mp.sinh(2) +- mpf('3.6268604078470186') +- sage: mp.sinh(2, prec=10) +- mpf('3.625') +- sage: mp.sinh(2, prec=10, rounding='d') +- mpf('3.625') +- sage: mp.sinh(2, prec=10, rounding='u') +- mpf('3.62890625') +- """ +- cdef int typx +- cdef tuple rev, imv, reu, cxu +- cdef mpf rr +- cdef mpc rc +- prec = global_opts.prec +- rounding = rndmode_to_python(global_opts.rounding) +- if kwargs: +- if 'prec' in kwargs: prec = int(kwargs['prec']) +- if 'dps' in kwargs: prec = libmp.dps_to_prec(int(kwargs['dps'])) +- if 'rounding' in kwargs: rounding = kwargs['rounding'] +- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) +- if typx == 1: +- rev = MPF_to_tuple(&tmp_opx_re) +- try: +- reu = self.mpf_f(rev, prec, rounding) +- rr = mpf.__new__(mpf) +- MPF_set_tuple(&rr.value, reu) +- return rr +- except libmp.ComplexResult: +- if global_context.trap_complex: +- raise +- cxu = self.mpc_f((rev, libmp.fzero), prec, rounding) +- rc = mpc.__new__(mpc) +- MPF_set_tuple(&rc.re, cxu[0]) +- MPF_set_tuple(&rc.im, cxu[1]) +- return rc +- if typx == 2: +- rev = MPF_to_tuple(&tmp_opx_re) +- imv = MPF_to_tuple(&tmp_opx_im) +- cxu = self.mpc_f((rev, imv), prec, rounding) +- rc = mpc.__new__(mpc) +- MPF_set_tuple(&rc.re, cxu[0]) +- MPF_set_tuple(&rc.im, cxu[1]) +- return rc +- x = global_context.convert(x) +- if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): +- return self(x, **kwargs) +- #if hasattr(x, "_mpi_"): +- # if self.mpi_f: +- # return global_context.make_mpi(self.mpi_f(x._mpi_, prec)) +- raise NotImplementedError("%s of a %s" % (self.name, type(x))) +- +- +-cdef class wrapped_specfun: +- cdef public f, name, __name__, __doc__ +- +- def __init__(self, name, f): +- """ +- Create an object holding a wrapped mpmath function +- along with metadata (name and documentation). +- +- TESTS:: +- +- sage: import mpmath +- sage: from sage.libs.mpmath.ext_main import wrapped_specfun +- sage: f = wrapped_specfun("f", lambda ctx, x: x) +- sage: f.name +- 'f' +- """ +- self.name = self.__name__ = name +- self.f = f +- self.__doc__ = function_docs.__dict__.get(name, "") +- +- def __call__(self, *args, **kwargs): +- """ +- Call wrapped mpmath function. Arguments are automatically converted +- to mpmath number, and the internal working precision is increased +- by a few bits to suppress typical rounding errors:: +- +- sage: from mpmath import mp +- sage: from sage.libs.mpmath.ext_main import wrapped_specfun +- sage: f = wrapped_specfun("f", lambda ctx, x: x + ctx.prec) +- sage: f("1") # 53 + 10 guard bits + 1 +- mpf('64.0') +- """ +- cdef int origprec +- args = [global_context.convert(a) for a in args] +- origprec = global_opts.prec +- global_opts.prec += 10 +- try: +- retval = self.f(global_context, *args, **kwargs) +- finally: +- global_opts.prec = origprec +- return +retval +- +- +-cdef class mpnumber: +- +- def __richcmp__(self, other, int op): +- """ +- Comparison of mpmath numbers. Compatible numerical types +- are automatically converted to mpmath numbers:: +- +- sage: from mpmath import mpf, mpc +- sage: mpf(3) == mpc(3) +- True +- sage: mpf(3) == mpc(4) +- False +- sage: mpf(3) == float(3) +- True +- sage: mpf(3) < float(2.5) +- False +- sage: mpc(3) < mpc(4) +- Traceback (most recent call last): +- ... +- ValueError: cannot compare complex numbers +- """ +- return binop(OP_RICHCMP+op, self, other, global_opts) +- +- def __add__(self, other): +- """ +- Addition of mpmath numbers. Compatible numerical types +- are automatically converted to mpmath numbers:: +- +- sage: from mpmath import mpf, mpc +- sage: mpf(3) + mpc(3) +- mpc(real='6.0', imag='0.0') +- sage: float(4) + mpf(3) +- mpf('7.0') +- """ +- return binop(OP_ADD, self, other, global_opts) +- +- def __sub__(self, other): +- """ +- Subtraction of mpmath numbers. Compatible numerical types +- are automatically converted to mpmath numbers:: +- +- sage: from mpmath import mpf, mpc +- sage: mpf(5) - mpc(3) +- mpc(real='2.0', imag='0.0') +- sage: float(4) - mpf(3) +- mpf('1.0') +- """ +- return binop(OP_SUB, self, other, global_opts) +- +- def __mul__(self, other): +- """ +- Multiplication of mpmath numbers. Compatible numerical types +- are automatically converted to mpmath numbers:: +- +- sage: from mpmath import mpf, mpc +- sage: mpf(5) * mpc(3) +- mpc(real='15.0', imag='0.0') +- sage: float(4) * mpf(3) +- mpf('12.0') +- """ +- return binop(OP_MUL, self, other, global_opts) +- +- def __truediv__(self, other): +- """ +- Division of mpmath numbers. Compatible numerical types +- are automatically converted to mpmath numbers:: +- +- sage: from mpmath import mpf, mpc +- sage: mpf(10) / mpc(5) +- mpc(real='2.0', imag='0.0') +- sage: float(9) / mpf(3) +- mpf('3.0') +- """ +- return binop(OP_DIV, self, other, global_opts) +- +- def __mod__(self, other): +- """ +- Remainder of mpmath numbers. Compatible numerical types +- are automatically converted to mpmath numbers:: +- +- sage: from mpmath import mpf +- sage: mpf(12) % float(7) +- mpf('5.0') +- """ +- return binop(OP_MOD, self, other, global_opts) +- +- def __pow__(self, other, mod): +- """ +- Exponentiation of mpmath numbers. Compatible numerical types +- are automatically converted to mpmath numbers:: +- +- sage: from mpmath import mpf, mpc +- sage: mpf(10) ** mpc(3) +- mpc(real='1000.0', imag='0.0') +- sage: mpf(3) ** float(2) +- mpf('9.0') +- """ +- if mod is not None: +- raise ValueError("three-argument pow not supported") +- return binop(OP_POW, self, other, global_opts) +- +- def ae(s, t, rel_eps=None, abs_eps=None): +- """ +- Check if two numbers are approximately equal to within the specified +- tolerance (see mp.almosteq for documentation):: +- +- sage: from mpmath import mpf, mpc +- sage: mpf(3).ae(mpc(3,1e-10)) +- False +- sage: mpf(3).ae(mpc(3,1e-10), rel_eps=1e-5) +- True +- """ +- return global_context.almosteq(s, t, rel_eps, abs_eps) +- +- +-cdef class mpf_base(mpnumber): +- +- # Shared methods for mpf, constant. However, somehow some methods +- # (hash?, __richcmp__?) are not inherited, so they have to +- # be defined multiple times. TODO: fix this. +- +- def __hash__(self): +- """ +- Support hashing of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: hash(X()) == hash(float(X())) +- True +- """ +- return libmp.mpf_hash(self._mpf_) +- +- def __repr__(self): +- """ +- Support repr() of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: repr(X()) +- "mpf('3.25')" +- """ +- if global_context.pretty: +- return str(self) +- n = repr_dps(global_opts.prec) +- return "mpf('%s')" % to_str(self._mpf_, n) +- +- def __str__(self): +- """ +- Support str() of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: str(X()) +- '3.25' +- """ +- return to_str(self._mpf_, global_context._str_digits) +- +- @property +- def real(self): +- """ +- Support real part of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: X().real +- mpf('3.25') +- """ +- return self +- +- @property +- def imag(self): +- """ +- Support imaginary part of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: X().imag +- mpf('0.0') +- """ +- return global_context.zero +- +- def conjugate(self): +- """ +- Support complex conjugate of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: X().conjugate() +- mpf('3.25') +- """ +- return self +- +- @property +- def man(self): +- """ +- Support mantissa extraction of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: X().man +- 13 +- """ +- return self._mpf_[1] +- +- @property +- def exp(self): +- """ +- Support exponent extraction of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: X().exp +- -2 +- """ +- return self._mpf_[2] +- +- @property +- def bc(self): +- """ +- Support bitcount extraction of derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: X().bc +- 4 +- """ +- return self._mpf_[3] +- +- # XXX: optimize +- def __int__(self): +- """ +- Support integer conversion for derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: int(X()) +- 3 +- """ +- return int(libmp.to_int(self._mpf_)) +- +- def __float__(self): +- """ +- Support float conversion for derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: float(X()) +- 3.25 +- """ +- return libmp.to_float(self._mpf_) +- +- def __complex__(self): +- """ +- Support complex conversion for derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: complex(X()) +- (3.25+0j) +- """ +- return complex(float(self)) +- +- def to_fixed(self, prec): +- """ +- Support conversion to a fixed-point integer for derived classes:: +- +- sage: from mpmath import mpf +- sage: from sage.libs.mpmath.ext_main import mpf_base +- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ +- sage: X().to_fixed(30) +- 3489660928 +- """ +- return libmp.to_fixed(self._mpf_, prec) +- +- def __getstate__(self): +- return libmp.to_pickable(self._mpf_) +- +- def __setstate__(self, val): +- self._mpf_ = libmp.from_pickable(val) +- +- +-cdef class mpf(mpf_base): +- """ +- An mpf instance holds a real-valued floating-point number. mpf:s +- work analogously to Python floats, but support arbitrary-precision +- arithmetic. +- """ +- +- cdef MPF value +- +- def __init__(self, x=0, **kwargs): +- """ +- Create an mpf from a recognized type, optionally rounding +- to a precision and in a direction different from the default. +- +- TESTS:: +- +- sage: from mpmath import mpf +- sage: mpf() +- mpf('0.0') +- sage: mpf(5) +- mpf('5.0') +- sage: mpf('inf') +- mpf('+inf') +- sage: mpf('nan') +- mpf('nan') +- sage: mpf(float(2.5)) +- mpf('2.5') +- sage: mpf("2.5") +- mpf('2.5') +- sage: mpf("0.3") +- mpf('0.29999999999999999') +- sage: mpf("0.3", prec=10) +- mpf('0.2998046875') +- sage: mpf("0.3", prec=10, rounding='u') +- mpf('0.30029296875') +- """ +- cdef MPopts opts +- opts = global_opts +- if kwargs: +- if 'prec' in kwargs: opts.prec = int(kwargs['prec']) +- if 'dps' in kwargs: opts.prec = libmp.dps_to_prec(int(kwargs['dps'])) +- if 'rounding' in kwargs: opts.rounding = rndmode_from_python(kwargs['rounding']) +- if MPF_set_any(&self.value, &self.value, x, opts, 1) != 1: +- raise TypeError +- +- def __reduce__(self): +- """ +- Support pickling:: +- +- sage: from mpmath import mpf +- sage: loads(dumps(mpf(0.5))) == mpf(0.5) +- True +- """ +- return (mpf, (), self._mpf_) +- +- def _get_mpf(self): +- """ +- Return internal representation of ``self`` as a tuple +- of (sign bit, mantissa, exponent, bitcount):: +- +- sage: from mpmath import mp +- sage: mp.mpf(-3)._mpf_ +- (1, 3, 0, 2) +- """ +- return MPF_to_tuple(&self.value) +- +- def _set_mpf(self, v): +- """ +- Set tuple value of ``self`` (warning: unsafe):: +- +- sage: from mpmath import mp +- sage: x = mp.mpf(-3) +- sage: x._mpf_ = (1, 3, -1, 2) +- sage: x +- mpf('-1.5') +- """ +- MPF_set_tuple(&self.value, v) +- +- _mpf_ = property(_get_mpf, _set_mpf, doc=_get_mpf.__doc__) +- +- def __bool__(self): +- """ +- Return whether the number is nonzero:: +- +- sage: from mpmath import mpf +- sage: bool(mpf(3.5)) +- True +- sage: bool(mpf(0.0)) +- False +- """ +- return self.value.special != S_ZERO +- +- def __hash__(self): +- """ +- Hash values are compatible with builtin Python floats +- when the precision is small enough:: +- +- sage: from mpmath import mpf +- sage: hash(mpf(2.5)) == hash(float(2.5)) +- True +- sage: hash(mpf('inf')) == hash(float(Infinity)) +- True +- """ +- return libmp.mpf_hash(self._mpf_) +- +- @property +- def real(self): +- """ +- Real part, leaves ``self`` unchanged:: +- +- sage: from mpmath import mpf +- sage: mpf(2.5).real +- mpf('2.5') +- """ +- return self +- +- @property +- def imag(self): +- """ +- Imaginary part, equal to zero:: +- +- sage: from mpmath import mpf +- sage: mpf(2.5).imag +- mpf('0.0') +- """ +- return global_context.zero +- +- def conjugate(self): +- """ +- Complex conjugate, leaves ``self`` unchanged:: +- +- sage: from mpmath import mpf +- sage: mpf(2.5).conjugate() +- mpf('2.5') +- """ +- return self +- +- @property +- def man(self): +- """ +- Return the binary mantissa of ``self``. The result is a Sage +- integer:: +- +- sage: from mpmath import mpf +- sage: mpf(-500.5).man +- 1001 +- sage: type(_) +- +- """ +- return self._mpf_[1] +- +- @property +- def exp(self): +- """ +- Return the binary exponent of ``self``:: +- +- sage: from mpmath import mpf +- sage: mpf(1/64.).exp +- -6 +- """ +- return self._mpf_[2] +- +- @property +- def bc(self): +- """ +- Return the number of bits in the mantissa of ``self``:: +- +- sage: from mpmath import mpf +- sage: mpf(-256).bc +- 1 +- sage: mpf(-255).bc +- 8 +- """ +- return self._mpf_[3] +- +- def to_fixed(self, long prec): +- """ +- Convert to a fixed-point integer of the given precision:: +- +- sage: from mpmath import mpf +- sage: mpf(7.25).to_fixed(30) +- 7784628224 +- sage: ZZ(7.25 * 2**30) +- 7784628224 +- """ +- # return libmp.to_fixed(self._mpf_, prec) +- MPF_to_fixed(tmp_mpz, &self.value, prec, False) +- cdef Integer r +- r = PY_NEW(Integer) +- mpz_set(r.value, tmp_mpz) +- return r +- +- def __int__(self): +- """ +- Convert to a Python integer (truncating if necessary):: +- +- sage: from mpmath import mpf +- sage: int(mpf(2.5)) +- 2 +- sage: type(_) +- <... 'int'> +- """ +- MPF_to_fixed(tmp_mpz, &self.value, 0, True) +- return mpzi(tmp_mpz) +- +- def __float__(self): +- """ +- Convert to a double-precision Python float:: +- +- sage: from mpmath import mpf +- sage: float(mpf(2.5)) +- 2.5 +- sage: type(_) +- <... 'float'> +- """ +- return MPF_to_double(&self.value, False) +- +- def __getstate__(self): +- """ +- Support pickling:: +- +- sage: from mpmath import mpf +- sage: loads(dumps(mpf(3))) == mpf(3) +- True +- """ +- return libmp.to_pickable(self._mpf_) +- +- def __setstate__(self, val): +- """ +- Support pickling:: +- +- sage: from mpmath import mpf +- sage: loads(dumps(mpf(3))) == mpf(3) +- True +- """ +- self._mpf_ = libmp.from_pickable(val) +- +- def __cinit__(self): +- """ +- Create a new mpf:: +- +- sage: from mpmath import mpf +- sage: x = mpf() +- """ +- MPF_init(&self.value) +- +- def __dealloc__(self): +- MPF_clear(&self.value) +- +- def __neg__(s): +- """ +- Negate ``self``, rounded to the current working precision:: +- +- sage: from mpmath import mpf +- sage: -mpf(2) +- mpf('-2.0') +- """ +- cdef mpf r = mpf.__new__(mpf) +- MPF_neg(&r.value, &s.value) +- MPF_normalize(&r.value, global_opts) +- return r +- +- def __pos__(s): +- """ +- Round the number to the current working precision:: +- +- sage: from mpmath import mp, mpf +- sage: mp.prec = 200 +- sage: x = mpf(1) / 3 +- sage: x.man +- 1071292029505993517027974728227441735014801995855195223534251 +- sage: mp.prec = 53 +- sage: (+x).man +- 6004799503160661 +- sage: print(+x) +- 0.333333333333333 +- """ +- cdef mpf r = mpf.__new__(mpf) +- MPF_set(&r.value, &s.value) +- MPF_normalize(&r.value, global_opts) +- return r +- +- def __abs__(s): +- """ +- Compute the absolute value, rounded to the current +- working precision:: +- +- sage: from mpmath import mpf +- sage: abs(mpf(-2)) +- mpf('2.0') +- """ +- cdef mpf r = mpf.__new__(mpf) +- MPF_abs(&r.value, &s.value) +- MPF_normalize(&r.value, global_opts) +- return r +- +- def sqrt(s): +- """ +- Compute the square root, rounded to the current +- working precision:: +- +- sage: from mpmath import mpf +- sage: mpf(2).sqrt() +- mpf('1.4142135623730951') +- """ +- cdef mpf r = mpf.__new__(mpf) +- MPF_sqrt(&r.value, &s.value, global_opts) +- return r +- +- def __round__(self, *args): +- return round(float(self), *args) +- +- def __richcmp__(self, other, int op): +- """ +- Compare numbers:: +- +- sage: from mpmath import mpf +- sage: mpf(3) > 2 +- True +- sage: mpf(3) == 3 +- True +- sage: mpf(3) == 4 +- False +- """ +- return binop(OP_RICHCMP+op, self, other, global_opts) +- +- def _mpfr_(self, RR): +- """ +- Return a Sage ``RealNumber``. +- +- EXAMPLES:: +- +- sage: from mpmath import mpf +- sage: mpf(3)._mpfr_(RealField(53)) +- 3.00000000000000 +- sage: RR(mpf(3)) # indirect doctest +- 3.00000000000000 +- """ +- signbit, man, exp, bc = self._mpf_ +- result = RR(man) << exp +- if signbit: +- result = -result +- return result +- +- +-cdef class constant(mpf_base): +- """ +- Represent a mathematical constant with dynamic precision. +- When printed or used in an arithmetic operation, a constant +- is converted to a regular mpf at the working precision. A +- regular mpf can also be obtained using the operation +x. +- """ +- +- cdef public name, func, __doc__ +- +- def __init__(self, func, name, docname=''): +- """ +- Create a constant from a function computing an mpf +- tuple value:: +- +- sage: from mpmath import mp, mpf +- sage: q = mp.constant(lambda prec, rnd: mpf(0.25)._mpf_, "quarter", "q") +- sage: q +- +- sage: q + 1 +- mpf('1.25') +- """ +- self.name = name +- self.func = func +- self.__doc__ = getattr(function_docs, docname, '') +- +- def __call__(self, prec=None, dps=None, rounding=None): +- """ +- Calling a constant is equivalent to rounding it. A +- custom precision and rounding direction can also be passed:: +- +- sage: from mpmath import pi +- sage: print(pi(dps=5, rounding='d')) +- 3.1415901184082 +- sage: print(pi(dps=5, rounding='u')) +- 3.14159393310547 +- """ +- prec2 = global_opts.prec +- rounding2 = rndmode_to_python(global_opts.rounding) +- if not prec: prec = prec2 +- if not rounding: rounding = rounding2 +- if dps: prec = dps_to_prec(dps) +- return global_context.make_mpf(self.func(prec, rounding)) +- +- @property +- def _mpf_(self): +- """ +- Return the tuple value of the constant as if rounded +- to an mpf at the present working precision:: +- +- sage: from mpmath import pi +- sage: pi._mpf_ +- (0, 884279719003555, -48, 50) +- sage: 884279719003555 / 2.0**48 +- 3.14159265358979 +- """ +- prec = global_opts.prec +- rounding = rndmode_to_python(global_opts.rounding) +- return self.func(prec, rounding) +- +- def __repr__(self): +- """ +- Represent ``self`` as a string. With mp.pretty=False, the +- representation differs from that of an ordinary mpf:: +- +- sage: from mpmath import mp +- sage: mp2 = mp.clone() +- sage: mp2.pretty = True +- sage: repr(mp2.pi) +- '3.14159265358979' +- sage: mp2.pretty = False +- sage: repr(mp2.pi) +- '' +- """ +- if global_context.pretty: +- return str(self) +- return "<%s: %s~>" % (self.name, global_context.nstr(self)) +- +- def __bool__(self): +- """ +- Return whether the constant is nonzero:: +- +- sage: from mpmath import pi +- sage: bool(pi) +- True +- """ +- return self._mpf_ != libmp.fzero +- +- def __neg__(self): +- """ +- Negate the constant:: +- +- sage: from mpmath import pi +- sage: -pi +- mpf('-3.1415926535897931') +- """ +- return -mpf(self) +- +- def __pos__(self): +- """ +- Instantiate the constant as an mpf:: +- +- sage: from mpmath import pi +- sage: +pi +- mpf('3.1415926535897931') +- """ +- return mpf(self) +- +- def __abs__(self): +- """ +- Compute the absolute value of the constant:: +- +- sage: from mpmath import pi +- sage: abs(pi) +- mpf('3.1415926535897931') +- """ +- return abs(mpf(self)) +- +- def sqrt(self): +- """ +- Compute the square root of the constant:: +- +- sage: from mpmath import pi +- sage: print(pi.sqrt()) +- 1.77245385090552 +- """ +- return mpf(self).sqrt() +- +- # XXX: optimize +- def to_fixed(self, prec): +- """ +- Convert to a fixed-point integer:: +- +- sage: from mpmath import pi +- sage: float(pi.to_fixed(10) / 2.0**10) +- 3.140625 +- """ +- return libmp.to_fixed(self._mpf_, prec) +- +- def __getstate__(self): +- return libmp.to_pickable(self._mpf_) +- +- def __setstate__(self, val): +- self._mpf_ = libmp.from_pickable(val) +- +- # WHY is this method not inherited from the base class by Cython? +- def __hash__(self): +- """ +- A constant hashes as if instantiated to a number:: +- +- sage: from mpmath import pi +- sage: hash(pi) == hash(+pi) +- True +- """ +- return libmp.mpf_hash(self._mpf_) +- +- def __richcmp__(self, other, int op): +- """ +- A constant hashes as if instantiated to a number:: +- +- sage: from mpmath import pi +- sage: pi == pi +- True +- sage: pi > 3.14 +- True +- sage: pi < 3.14 +- False +- """ +- return binop(OP_RICHCMP+op, self, other, global_opts) +- +- +-cdef class mpc(mpnumber): +- """ +- An mpc represents a complex number using a pair of mpf:s (one +- for the real part and another for the imaginary part.) The mpc +- class behaves fairly similarly to Python's complex type. +- """ +- +- cdef MPF re +- cdef MPF im +- +- def __init__(self, real=0, imag=0): +- """ +- Create a new mpc:: +- +- sage: from mpmath import mpc +- sage: mpc() == mpc(0,0) == mpc(1,0)-1 == 0 +- True +- """ +- cdef int typx, typy +- typx = MPF_set_any(&self.re, &self.im, real, global_opts, 1) +- if typx == 2: +- typy = 1 +- else: +- typy = MPF_set_any(&self.im, &self.im, imag, global_opts, 1) +- if typx == 0 or typy != 1: +- raise TypeError +- +- def __cinit__(self): +- """ +- Create a new mpc:: +- +- sage: from mpmath import mpc +- sage: x = mpc() +- """ +- MPF_init(&self.re) +- MPF_init(&self.im) +- +- def __dealloc__(self): +- MPF_clear(&self.re) +- MPF_clear(&self.im) +- +- def __reduce__(self): +- """ +- Support pickling:: +- +- sage: from mpmath import mpc +- sage: loads(dumps(mpc(1,3))) == mpc(1,3) +- True +- """ +- return (mpc, (), self._mpc_) +- +- def __setstate__(self, val): +- """ +- Support pickling:: +- +- sage: from mpmath import mpc +- sage: loads(dumps(mpc(1,3))) == mpc(1,3) +- True +- """ +- self._mpc_ = val[0], val[1] +- +- def __repr__(self): +- """ +- TESTS:: +- +- sage: from mpmath import mp +- sage: mp2 = mp.clone() +- sage: mp2.pretty = True +- sage: repr(mp2.mpc(2,3)) +- '(2.0 + 3.0j)' +- sage: mp2.pretty = False +- sage: repr(mp2.mpc(2,3)) +- "mpc(real='2.0', imag='3.0')" +- """ +- if global_context.pretty: +- return str(self) +- re, im = self._mpc_ +- n = repr_dps(global_opts.prec) +- return "mpc(real='%s', imag='%s')" % (to_str(re, n), to_str(im, n)) +- +- def __str__(s): +- """ +- TESTS:: +- +- sage: from mpmath import mp +- sage: str(mp.mpc(2,3)) +- '(2.0 + 3.0j)' +- """ +- return "(%s)" % libmp.mpc_to_str(s._mpc_, global_context._str_digits) +- +- def __bool__(self): +- """ +- TESTS:: +- +- sage: from mpmath import mp +- sage: bool(mp.mpc(0,1)) +- True +- sage: bool(mp.mpc(1,0)) +- True +- sage: bool(mp.mpc(0,0)) +- False +- """ +- return self.re.special != S_ZERO or self.im.special != S_ZERO +- +- #def __complex__(self): +- # a, b = self._mpc_ +- # return complex(libmp.to_float(a), libmp.to_float(b)) +- +- def __complex__(self): +- """ +- TESTS:: +- +- sage: from mpmath import mp +- sage: complex(mp.mpc(1,2)) == complex(1,2) +- True +- """ +- return complex(MPF_to_double(&self.re, False), MPF_to_double(&self.im, False)) +- +- def _get_mpc(self): +- """ +- Return tuple value of ``self``:: +- +- sage: from mpmath import mp +- sage: mp.mpc(2,3)._mpc_ +- ((0, 1, 1, 1), (0, 3, 0, 2)) +- """ +- return MPF_to_tuple(&self.re), MPF_to_tuple(&self.im) +- +- def _set_mpc(self, tuple v): +- """ +- Set tuple value of ``self`` (warning: unsafe):: +- +- sage: from mpmath import mp +- sage: x = mp.mpc(2,3) +- sage: x._mpc_ = (x._mpc_[1], x._mpc_[0]) +- sage: x +- mpc(real='3.0', imag='2.0') +- """ +- MPF_set_tuple(&self.re, v[0]) +- MPF_set_tuple(&self.im, v[1]) +- +- _mpc_ = property(_get_mpc, _set_mpc, doc=_get_mpc.__doc__) +- +- @property +- def real(self): +- """ +- Return the real part of ``self`` as an mpf:: +- +- sage: from mpmath import mp +- sage: mp.mpc(1,2).real +- mpf('1.0') +- """ +- cdef mpf r = mpf.__new__(mpf) +- MPF_set(&r.value, &self.re) +- return r +- +- @property +- def imag(self): +- """ +- Return the imaginary part of ``self`` as an mpf:: +- +- sage: from mpmath import mp +- sage: mp.mpc(1,2).imag +- mpf('2.0') +- """ +- cdef mpf r = mpf.__new__(mpf) +- MPF_set(&r.value, &self.im) +- return r +- +- def __hash__(self): +- """ +- Return the hash value of ``self``:: +- +- EXAMPLES:: +- +- sage: from mpmath import mp +- sage: hash(mp.mpc(2,3)) == hash(complex(2,3)) +- True +- +- TESTS: +- +- Check that :issue:`31676` is fixed:: +- +- sage: from mpmath import mpc +- sage: hash(mpc(1, -1)) == hash(mpc(-1, -1)) # should not return OverflowError: Python int too large to convert to C ssize_t +- False +- """ +- return hash(libmp.mpc_hash(self._mpc_)) +- +- def __neg__(s): +- """ +- Negate the number:: +- +- sage: from mpmath import mpc +- sage: -mpc(1,2) +- mpc(real='-1.0', imag='-2.0') +- """ +- cdef mpc r = mpc.__new__(mpc) +- MPF_neg(&r.re, &s.re) +- MPF_neg(&r.im, &s.im) +- MPF_normalize(&r.re, global_opts) +- MPF_normalize(&r.im, global_opts) +- return r +- +- def conjugate(s): +- """ +- Return the complex conjugate:: +- +- sage: from mpmath import mpc +- sage: mpc(1,2).conjugate() +- mpc(real='1.0', imag='-2.0') +- """ +- cdef mpc r = mpc.__new__(mpc) +- MPF_set(&r.re, &s.re) +- MPF_neg(&r.im, &s.im) +- MPF_normalize(&r.re, global_opts) +- MPF_normalize(&r.im, global_opts) +- return r +- +- def __pos__(s): +- """ +- Round the number to the current working precision:: +- +- sage: from mpmath import mp +- sage: mp.prec = 200 +- sage: x = mp.mpc(1) / 3 +- sage: x.real.man +- 1071292029505993517027974728227441735014801995855195223534251 +- sage: mp.prec = 53 +- sage: +x +- mpc(real='0.33333333333333331', imag='0.0') +- sage: (+x).real.man +- 6004799503160661 +- """ +- cdef mpc r = mpc.__new__(mpc) +- MPF_set(&r.re, &s.re) +- MPF_set(&r.im, &s.im) +- MPF_normalize(&r.re, global_opts) +- MPF_normalize(&r.im, global_opts) +- return r +- +- def __abs__(s): +- """ +- Return the absolute value of ``self``:: +- +- sage: from mpmath import mpc +- sage: abs(mpc(3,4)) +- mpf('5.0') +- """ +- cdef mpf r = mpf.__new__(mpf) +- MPF_hypot(&r.value, &s.re, &s.im, global_opts) +- return r +- +- def __richcmp__(self, other, int op): +- """ +- Complex numbers can be compared for equality:: +- +- sage: from mpmath import mpc +- sage: mpc(2,3) == complex(2,3) +- True +- sage: mpc(-2,3) == complex(2,3) +- False +- sage: mpc(-2,3) != complex(2,3) +- True +- """ +- return binop(OP_RICHCMP+op, self, other, global_opts) +- +- def _complex_mpfr_field_(self, CC): +- """ +- Return a Sage complex number. +- +- EXAMPLES:: +- +- sage: from mpmath import mpc +- sage: CC(mpc(1,2)) # indirect doctest +- 1.00000000000000 + 2.00000000000000*I +- sage: mpc(1,2)._complex_mpfr_field_(CC) +- 1.00000000000000 + 2.00000000000000*I +- """ +- RR = CC._real_field() +- return CC((self.real._mpfr_(RR), self.imag._mpfr_(RR))) +- +- +-def hypsum_internal(int p, int q, param_types, str ztype, coeffs, z, +- long prec, long wp, long epsshift, dict magnitude_check, kwargs): +- """ +- Internal summation routine for hypergeometric series (wraps +- extension function MPF_hypsum to handle mpf/mpc types). +- +- EXAMPLES:: +- +- sage: from mpmath import mp # indirect doctest +- sage: mp.dps = 15 +- sage: print(mp.hyp1f1(1,2,3)) +- 6.36184564106256 +- +- .. TODO:: +- +- convert mpf/mpc parameters to fixed-point numbers here +- instead of converting to tuples within MPF_hypsum. +- """ +- cdef mpf f +- cdef mpc c +- c = mpc.__new__(mpc) +- have_complex, magn = MPF_hypsum(&c.re, &c.im, p, q, param_types, +- ztype, coeffs, z, prec, wp, epsshift, magnitude_check, kwargs) +- if have_complex: +- v = c +- else: +- f = mpf.__new__(mpf) +- MPF_set(&f.value, &c.re) +- v = f +- return v, have_complex, magn +diff --git a/src/sage/libs/mpmath/meson.build b/src/sage/libs/mpmath/meson.build +index cc8cdc84e98..e1d76c0c130 100644 +--- a/src/sage/libs/mpmath/meson.build ++++ b/src/sage/libs/mpmath/meson.build +@@ -1,20 +1,12 @@ + py.install_sources( + '__init__.py', + 'all.py', +- 'ext_impl.pxd', +- 'ext_impl.pyx', +- 'ext_libmp.pyx', +- 'ext_main.pxd', +- 'ext_main.pyx', + 'utils.pxd', + 'utils.pyx', + subdir: 'sage/libs/mpmath', + ) + + extension_data = { +- 'ext_impl': files('ext_impl.pyx'), +- 'ext_libmp': files('ext_libmp.pyx'), +- 'ext_main': files('ext_main.pyx'), + 'utils': files('utils.pyx'), + } + +@@ -25,7 +17,7 @@ foreach name, pyx : extension_data + subdir: 'sage/libs/mpmath', + install: true, + include_directories: [inc_cpython, inc_ext, inc_rings], +- dependencies: [py_dep, cysignals, gmp, mpfr], ++ dependencies: [py_dep, cysignals, gmp, gmpy2, mpfr], + ) + endforeach + +diff --git a/src/sage/libs/mpmath/utils.pyx b/src/sage/libs/mpmath/utils.pyx +index 1acf14ea540..a88884d148e 100644 +--- a/src/sage/libs/mpmath/utils.pyx ++++ b/src/sage/libs/mpmath/utils.pyx +@@ -1,9 +1,9 @@ + """ + Utilities for Sage-mpmath interaction +- +-Also patches some mpmath functions for speed + """ + ++cimport gmpy2 ++ + from sage.ext.stdsage cimport PY_NEW + + from sage.rings.integer cimport Integer +@@ -16,145 +16,7 @@ from sage.libs.gmp.all cimport * + + from sage.rings.real_mpfr cimport RealField + +-cpdef int bitcount(n) noexcept: +- """ +- Bitcount of a Sage Integer or Python int/long. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import bitcount +- sage: bitcount(0) +- 0 +- sage: bitcount(1) +- 1 +- sage: bitcount(100) +- 7 +- sage: bitcount(-100) +- 7 +- sage: bitcount(2r) +- 2 +- sage: bitcount(2L) +- 2 +- """ +- cdef Integer m +- if isinstance(n, Integer): +- m = n +- else: +- m = Integer(n) +- if mpz_sgn(m.value) == 0: +- return 0 +- return mpz_sizeinbase(m.value, 2) +- +-cpdef isqrt(n): +- """ +- Square root (rounded to floor) of a Sage Integer or Python int/long. +- The result is a Sage Integer. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import isqrt +- sage: isqrt(0) +- 0 +- sage: isqrt(100) +- 10 +- sage: isqrt(10) +- 3 +- sage: isqrt(10r) +- 3 +- sage: isqrt(10L) +- 3 +- """ +- cdef Integer m, y +- if isinstance(n, Integer): +- m = n +- else: +- m = Integer(n) +- if mpz_sgn(m.value) < 0: +- raise ValueError("square root of negative integer not defined.") +- y = PY_NEW(Integer) +- mpz_sqrt(y.value, m.value) +- return y +- +-cpdef from_man_exp(man, exp, long prec=0, str rnd='d'): +- """ +- Create normalized mpf value tuple from mantissa and exponent. +- +- With prec > 0, rounds the result in the desired direction +- if necessary. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import from_man_exp +- sage: from_man_exp(-6, -1) +- (1, 3, 0, 2) +- sage: from_man_exp(-6, -1, 1, 'd') +- (1, 1, 1, 1) +- sage: from_man_exp(-6, -1, 1, 'u') +- (1, 1, 2, 1) +- """ +- cdef Integer res +- cdef long bc +- res = Integer(man) +- bc = mpz_sizeinbase(res.value, 2) +- if not prec: +- prec = bc +- if mpz_sgn(res.value) < 0: +- mpz_neg(res.value, res.value) +- return normalize(1, res, exp, bc, prec, rnd) +- else: +- return normalize(0, res, exp, bc, prec, rnd) +- +-cpdef normalize(long sign, Integer man, exp, long bc, long prec, str rnd): +- """ +- Create normalized mpf value tuple from full list of components. +- +- EXAMPLES:: +- +- sage: from mpmath.libmp import normalize +- sage: normalize(0, 4, 5, 3, 53, 'n') +- (0, 1, 7, 1) +- """ +- cdef long shift +- cdef Integer res +- cdef unsigned long trail +- if mpz_sgn(man.value) == 0: +- from mpmath.libmp import fzero +- return fzero +- if bc <= prec and mpz_odd_p(man.value): +- return (sign, man, exp, bc) +- shift = bc - prec +- res = PY_NEW(Integer) +- if shift > 0: +- if rnd == 'n': +- if mpz_tstbit(man.value, shift-1) and (mpz_tstbit(man.value, shift) +- or (mpz_scan1(man.value, 0) < (shift-1))): +- mpz_cdiv_q_2exp(res.value, man.value, shift) +- else: +- mpz_fdiv_q_2exp(res.value, man.value, shift) +- elif rnd == 'd': +- mpz_fdiv_q_2exp(res.value, man.value, shift) +- elif rnd == 'f': +- if sign: +- mpz_cdiv_q_2exp(res.value, man.value, shift) +- else: +- mpz_fdiv_q_2exp(res.value, man.value, shift) +- elif rnd == 'c': +- if sign: +- mpz_fdiv_q_2exp(res.value, man.value, shift) +- else: +- mpz_cdiv_q_2exp(res.value, man.value, shift) +- elif rnd == 'u': +- mpz_cdiv_q_2exp(res.value, man.value, shift) +- exp += shift +- else: +- mpz_set(res.value, man.value) +- # Strip trailing bits +- trail = mpz_scan1(res.value, 0) +- if 0 < trail < bc: +- mpz_tdiv_q_2exp(res.value, res.value, trail) +- exp += trail +- bc = mpz_sizeinbase(res.value, 2) +- return (sign, res, int(exp), bc) ++gmpy2.import_gmpy2() + + cdef mpfr_from_mpfval(mpfr_t res, tuple x): + """ +@@ -162,11 +24,11 @@ cdef mpfr_from_mpfval(mpfr_t res, tuple x): + data tuple. + """ + cdef int sign +- cdef Integer man ++ cdef gmpy2.mpz man + cdef long exp + sign, man, exp, _ = x + if man: +- mpfr_set_z(res, man.value, MPFR_RNDZ) ++ mpfr_set_z(res, man.z, MPFR_RNDZ) + if sign: + mpfr_neg(res, res, MPFR_RNDZ) + mpfr_mul_2si(res, res, exp, MPFR_RNDZ) +@@ -210,7 +72,7 @@ cdef mpfr_to_mpfval(mpfr_t value): + mpz_tdiv_q_2exp(man.value, man.value, trailing) + exp += trailing + bc = mpz_sizeinbase(man.value, 2) +- return (sign, man, int(exp), bc) ++ return (sign, man.__mpz__(), int(exp), bc) + + + def mpmath_to_sage(x, prec): +@@ -305,7 +167,7 @@ def sage_to_mpmath(x, prec): + sage: print(a.sage_to_mpmath(1+pi, 53)) + 4.14159265358979 + sage: a.sage_to_mpmath(infinity, 53) +- mpf('+inf') ++ mpf('...inf') + sage: a.sage_to_mpmath(-infinity, 53) + mpf('-inf') + sage: a.sage_to_mpmath(NaN, 53) +@@ -414,7 +276,7 @@ def call(func, *args, **kwargs): + Check that :issue:`11885` is fixed:: + + sage: a.call(a.ei, 1.0r, parent=float) +- 1.8951178163559366 ++ 1.8951178163559368 + + Check that :issue:`14984` is fixed:: + +diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx +index 11f58008fcf..ba26d194b1f 100644 +--- a/src/sage/rings/complex_mpfr.pyx ++++ b/src/sage/rings/complex_mpfr.pyx +@@ -54,6 +54,7 @@ from sage.rings.integer_ring import ZZ + + cimport gmpy2 + gmpy2.import_gmpy2() ++from mpmath import mp + + try: + from cypari2.gen import Gen as pari_gen +@@ -984,7 +985,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): + real, imag = real + elif isinstance(real, complex): + real, imag = real.real, real.imag +- elif type(real) is gmpy2.mpc: ++ elif isinstance(real, (gmpy2.mpc, mp.mpc)): + real, imag = (real).real, (real).imag + else: + imag = 0 +diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx +index f0b5b713fe1..1ed67bfb906 100644 +--- a/src/sage/rings/real_mpfr.pyx ++++ b/src/sage/rings/real_mpfr.pyx +@@ -152,8 +152,6 @@ from sage.structure.richcmp cimport rich_to_bool_sgn + cdef bin_op + from sage.structure.element import bin_op + +-from sage.libs.mpmath.utils cimport mpfr_to_mpfval +- + from sage.rings.integer cimport Integer + from sage.rings.rational cimport Rational + from sage.rings.real_double cimport RealDoubleElement +diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx +index 98ffac46406..0450eeccbaf 100644 +--- a/src/sage/structure/coerce.pyx ++++ b/src/sage/structure/coerce.pyx +@@ -143,6 +143,12 @@ cpdef py_scalar_parent(py_type): + Real Double Field + sage: py_scalar_parent(gmpy2.mpc) # needs sage.rings.complex_double + Complex Double Field ++ ++ sage: import mpmath ++ sage: py_scalar_parent(mpmath.mpf) ++ Real Double Field ++ sage: py_scalar_parent(mpmath.mpc) # needs sage.rings.complex_double ++ Complex Double Field + """ + if issubclass(py_type, int): + import sage.rings.integer_ring +@@ -150,39 +156,46 @@ cpdef py_scalar_parent(py_type): + if py_type is FractionType: + import sage.rings.rational_field + return sage.rings.rational_field.QQ +- elif issubclass(py_type, float): ++ if issubclass(py_type, float): + import sage.rings.real_double + return sage.rings.real_double.RDF +- elif issubclass(py_type, complex): ++ if issubclass(py_type, complex): + import sage.rings.complex_double + return sage.rings.complex_double.CDF +- elif is_numpy_type(py_type): ++ if is_numpy_type(py_type): + import numpy + if issubclass(py_type, numpy.integer): + import sage.rings.integer_ring + return sage.rings.integer_ring.ZZ +- elif issubclass(py_type, numpy.floating): ++ if issubclass(py_type, numpy.floating): + import sage.rings.real_double + return sage.rings.real_double.RDF +- elif issubclass(py_type, numpy.complexfloating): ++ if issubclass(py_type, numpy.complexfloating): + import sage.rings.complex_double + return sage.rings.complex_double.CDF +- else: +- return None +- elif issubclass(py_type, gmpy2.mpz): ++ return None ++ if issubclass(py_type, gmpy2.mpz): + import sage.rings.integer_ring + return sage.rings.integer_ring.ZZ +- elif issubclass(py_type, gmpy2.mpq): ++ if issubclass(py_type, gmpy2.mpq): + import sage.rings.rational_field + return sage.rings.rational_field.QQ +- elif issubclass(py_type, gmpy2.mpfr): ++ if issubclass(py_type, gmpy2.mpfr): + import sage.rings.real_double + return sage.rings.real_double.RDF +- elif issubclass(py_type, gmpy2.mpc): ++ if issubclass(py_type, gmpy2.mpc): + import sage.rings.complex_double + return sage.rings.complex_double.CDF +- else: ++ if is_mpmath_type(py_type): ++ import mpmath ++ if issubclass(py_type, mpmath.mpf): ++ from sage.rings.real_double import RDF ++ return RDF ++ if issubclass(py_type, mpmath.mpc): ++ from sage.rings.complex_double import CDF ++ return CDF + return None ++ return None + + cpdef py_scalar_to_element(x): + """ +@@ -468,14 +481,13 @@ cpdef bint is_numpy_type(t) noexcept: + return True + return False + ++ + cpdef bint is_mpmath_type(t) noexcept: + r""" +- Check whether the type ``t`` is a type whose name starts with either +- ``mpmath.`` or ``sage.libs.mpmath.``. ++ Check whether the type ``t`` is a type whose name starts with ``mpmath.`` + + EXAMPLES:: + +- sage: # needs mpmath + sage: from sage.structure.coerce import is_mpmath_type + sage: is_mpmath_type(int) + False +@@ -488,7 +500,7 @@ cpdef bint is_mpmath_type(t) noexcept: + True + """ + return isinstance(t, type) and \ +- strncmp((t).tp_name, "sage.libs.mpmath.", 17) == 0 ++ t.__module__.startswith("mpmath.") + + + cdef class CoercionModel: +diff --git a/src/sage/tests/books/computational_mathematics_with_sagemath/integration_doctest.py b/src/sage/tests/books/computational_mathematics_with_sagemath/integration_doctest.py +index cdb0aceb956..02d01cc8305 100644 +--- a/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py ++++ b/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py +@@ -154,7 +154,7 @@ + sage: mpmath.quad(f, [0, 1]) + Traceback (most recent call last): + ... +- TypeError: no canonical coercion from to ... ++ TypeError: no canonical coercion from to ... + + Sage example in ./integration.tex, line 866:: + diff --git a/srcpkgs/sagemath/patches/get_patches b/srcpkgs/sagemath/patches/get_patches index e7f3d188f71eb2..b3684d832c48ce 100755 --- a/srcpkgs/sagemath/patches/get_patches +++ b/srcpkgs/sagemath/patches/get_patches @@ -41,3 +41,4 @@ get_pr 41394 "Fix doctest failure with python 3.14" get_pr 41433 "Fix test failures with scipy 1.17" get_pr 41469 "Prevent leaking file descriptors" get_pr 40679 "Update to maxima 5.49" +get_pr 41728 "Patch for mpmath 1.4" From 65656165f5ddaf4eeeb38182b5c11fdd80f0c52a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Thu, 7 May 2026 16:40:27 -0300 Subject: [PATCH 17/18] libmpc: update to 1.4.1. --- srcpkgs/libmpc/template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpkgs/libmpc/template b/srcpkgs/libmpc/template index ed35e345c3a051..c97a690c1be05e 100644 --- a/srcpkgs/libmpc/template +++ b/srcpkgs/libmpc/template @@ -1,6 +1,6 @@ # Template file for 'libmpc' pkgname=libmpc -version=1.4.0 +version=1.4.1 revision=1 bootstrap=yes build_style=gnu-configure @@ -11,7 +11,7 @@ license="LGPL-3.0-or-later" homepage="https://www.multiprecision.org/mpc/" changelog="https://gitlab.inria.fr/mpc/mpc/-/raw/master/NEWS" distfiles="${GNU_SITE}/mpc/mpc-${version}.tar.xz" -checksum=3210b3a546b1cb00c296ca360891d7740ee6ff06deb02a27a35b20cd3c0bb1a5 +checksum=91204cd32f164bd3b7c992d4a6a8ce6519511aadab30f78b6982d0bf8d73e931 if [ -z "$CHROOT_READY" ]; then CFLAGS="-I${XBPS_MASTERDIR}/usr/include" From c792bbf9e3d97946b89b89894193028dbc76f623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Thu, 7 May 2026 16:59:54 -0300 Subject: [PATCH 18/18] sagemath: update to 10.9. --- ...20-Use_accelerate_for_Conda_on_macos.patch | 2003 ------ .../patches/40679-Update_to_maxima_5.49.patch | 4 +- ...Meson:_Build_docs_for_Maxima_as_well.patch | 113 - ...42-Fix_a_test_failure_with_numpy_2.4.patch | 13 - ...tion_count_for_newer_ipython_version.patch | 13 - ...Fix_doctest_failure_with_python_3.14.patch | 14 - ...Fix_test_failures_with_pyparsing_3.3.patch | 22 - ...33-Fix_test_failures_with_scipy_1.17.patch | 22 - ...469-Prevent_leaking_file_descriptors.patch | 98 - .../patches/41728-Patch_for_mpmath_1.4.patch | 5691 ----------------- .../patches/fix-doctest-ipython-9.10.patch | 12 - .../patches/fix-doctest-maxima-5.49.patch | 11 - srcpkgs/sagemath/patches/sphinx.patch | 11 - .../patches/workaround-embed-positions.patch | 4 +- srcpkgs/sagemath/template | 10 +- 15 files changed, 11 insertions(+), 8030 deletions(-) delete mode 100644 srcpkgs/sagemath/patches/40520-Use_accelerate_for_Conda_on_macos.patch delete mode 100644 srcpkgs/sagemath/patches/40816-Meson:_Build_docs_for_Maxima_as_well.patch delete mode 100644 srcpkgs/sagemath/patches/41342-Fix_a_test_failure_with_numpy_2.4.patch delete mode 100644 srcpkgs/sagemath/patches/41346-Fix_execution_count_for_newer_ipython_version.patch delete mode 100644 srcpkgs/sagemath/patches/41394-Fix_doctest_failure_with_python_3.14.patch delete mode 100644 srcpkgs/sagemath/patches/41395-Fix_test_failures_with_pyparsing_3.3.patch delete mode 100644 srcpkgs/sagemath/patches/41433-Fix_test_failures_with_scipy_1.17.patch delete mode 100644 srcpkgs/sagemath/patches/41469-Prevent_leaking_file_descriptors.patch delete mode 100644 srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch delete mode 100644 srcpkgs/sagemath/patches/fix-doctest-ipython-9.10.patch delete mode 100644 srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch delete mode 100644 srcpkgs/sagemath/patches/sphinx.patch diff --git a/srcpkgs/sagemath/patches/40520-Use_accelerate_for_Conda_on_macos.patch b/srcpkgs/sagemath/patches/40520-Use_accelerate_for_Conda_on_macos.patch deleted file mode 100644 index 43d0dc9938bb7d..00000000000000 --- a/srcpkgs/sagemath/patches/40520-Use_accelerate_for_Conda_on_macos.patch +++ /dev/null @@ -1,2003 +0,0 @@ -diff --git a/src/sage/algebras/finite_dimensional_algebras/meson.build b/src/sage/algebras/finite_dimensional_algebras/meson.build -index 5cf644da91b..7f13ad17471 100644 ---- a/src/sage/algebras/finite_dimensional_algebras/meson.build -+++ b/src/sage/algebras/finite_dimensional_algebras/meson.build -@@ -10,7 +10,7 @@ py.install_sources( - ) - - extension_data = { -- 'finite_dimensional_algebra_element' : files( -+ 'finite_dimensional_algebra_element': files( - 'finite_dimensional_algebra_element.pyx', - ), - } -diff --git a/src/sage/algebras/fusion_rings/meson.build b/src/sage/algebras/fusion_rings/meson.build -index 4dec6963a36..ca204c31ec0 100644 ---- a/src/sage/algebras/fusion_rings/meson.build -+++ b/src/sage/algebras/fusion_rings/meson.build -@@ -16,7 +16,7 @@ py.install_sources( - ) - - extension_data = { -- 'fast_parallel_fusion_ring_braid_repn' : files( -+ 'fast_parallel_fusion_ring_braid_repn': files( - 'fast_parallel_fusion_ring_braid_repn.pyx', - ), - } -diff --git a/src/sage/algebras/lie_algebras/meson.build b/src/sage/algebras/lie_algebras/meson.build -index b08b21eaf80..f4df322b84b 100644 ---- a/src/sage/algebras/lie_algebras/meson.build -+++ b/src/sage/algebras/lie_algebras/meson.build -@@ -29,7 +29,7 @@ py.install_sources( - subdir: 'sage/algebras/lie_algebras', - ) - --extension_data = {'lie_algebra_element' : files('lie_algebra_element.pyx')} -+extension_data = {'lie_algebra_element': files('lie_algebra_element.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/algebras/meson.build b/src/sage/algebras/meson.build -index 59262513251..3ea2e21c30f 100644 ---- a/src/sage/algebras/meson.build -+++ b/src/sage/algebras/meson.build -@@ -48,9 +48,9 @@ py.install_sources( - ) - - extension_data = { -- 'clifford_algebra_element' : files('clifford_algebra_element.pyx'), -- 'exterior_algebra_groebner' : files('exterior_algebra_groebner.pyx'), -- 'octonion_algebra' : files('octonion_algebra.pyx'), -+ 'clifford_algebra_element': files('clifford_algebra_element.pyx'), -+ 'exterior_algebra_groebner': files('exterior_algebra_groebner.pyx'), -+ 'octonion_algebra': files('octonion_algebra.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/arith/meson.build b/src/sage/arith/meson.build -index b11957b8743..335ac643b80 100644 ---- a/src/sage/arith/meson.build -+++ b/src/sage/arith/meson.build -@@ -19,12 +19,12 @@ py.install_sources( - ) - - extension_data = { -- 'functions' : files('functions.pyx'), -- 'multi_modular' : files('multi_modular.pyx'), -- 'numerical_approx' : files('numerical_approx.pyx'), -- 'power' : files('power.pyx'), -- 'rational_reconstruction' : files('rational_reconstruction.pyx'), -- 'srange' : files('srange.pyx'), -+ 'functions': files('functions.pyx'), -+ 'multi_modular': files('multi_modular.pyx'), -+ 'numerical_approx': files('numerical_approx.pyx'), -+ 'power': files('power.pyx'), -+ 'rational_reconstruction': files('rational_reconstruction.pyx'), -+ 'srange': files('srange.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/calculus/meson.build b/src/sage/calculus/meson.build -index 60f5cac8614..a90345327d8 100644 ---- a/src/sage/calculus/meson.build -+++ b/src/sage/calculus/meson.build -@@ -22,12 +22,12 @@ py.install_sources( - ) - - extension_data = { -- 'integration' : files('integration.pyx'), -- 'interpolation' : files('interpolation.pyx'), -- 'interpolators' : files('interpolators.pyx'), -- 'ode' : files('ode.pyx'), -- 'riemann' : files('riemann.pyx'), -- 'var' : files('var.pyx'), -+ 'integration': files('integration.pyx'), -+ 'interpolation': files('interpolation.pyx'), -+ 'interpolators': files('interpolators.pyx'), -+ 'ode': files('ode.pyx'), -+ 'riemann': files('riemann.pyx'), -+ 'var': files('var.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/calculus/transforms/meson.build b/src/sage/calculus/transforms/meson.build -index 3876840f7cc..568602ac5d5 100644 ---- a/src/sage/calculus/transforms/meson.build -+++ b/src/sage/calculus/transforms/meson.build -@@ -9,7 +9,7 @@ py.install_sources( - subdir: 'sage/calculus/transforms', - ) - --extension_data = {'dwt' : files('dwt.pyx'), 'fft' : files('fft.pyx')} -+extension_data = {'dwt': files('dwt.pyx'), 'fft': files('fft.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/categories/examples/meson.build b/src/sage/categories/examples/meson.build -index 41580a11cca..b249a5d9be9 100644 ---- a/src/sage/categories/examples/meson.build -+++ b/src/sage/categories/examples/meson.build -@@ -37,7 +37,7 @@ py.install_sources( - subdir: 'sage/categories/examples', - ) - --extension_data = {'semigroups_cython' : files('semigroups_cython.pyx')} -+extension_data = {'semigroups_cython': files('semigroups_cython.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/categories/meson.build b/src/sage/categories/meson.build -index 984e8d50d99..ae9f9072852 100644 ---- a/src/sage/categories/meson.build -+++ b/src/sage/categories/meson.build -@@ -210,13 +210,13 @@ py.install_sources( - ) - - extension_data = { -- 'action' : files('action.pyx'), -- 'category_cy_helper' : files('category_cy_helper.pyx'), -- 'category_singleton' : files('category_singleton.pyx'), -- 'coercion_methods' : files('coercion_methods.pyx'), -- 'functor' : files('functor.pyx'), -- 'map' : files('map.pyx'), -- 'morphism' : files('morphism.pyx'), -+ 'action': files('action.pyx'), -+ 'category_cy_helper': files('category_cy_helper.pyx'), -+ 'category_singleton': files('category_singleton.pyx'), -+ 'coercion_methods': files('coercion_methods.pyx'), -+ 'functor': files('functor.pyx'), -+ 'map': files('map.pyx'), -+ 'morphism': files('morphism.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/coding/codecan/meson.build b/src/sage/coding/codecan/meson.build -index 67e74deea79..e88c99dccaf 100644 ---- a/src/sage/coding/codecan/meson.build -+++ b/src/sage/coding/codecan/meson.build -@@ -8,8 +8,8 @@ py.install_sources( - ) - - extension_data = { -- 'autgroup_can_label' : files('autgroup_can_label.pyx'), -- 'codecan' : files('codecan.pyx'), -+ 'autgroup_can_label': files('autgroup_can_label.pyx'), -+ 'codecan': files('codecan.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/coding/meson.build b/src/sage/coding/meson.build -index 8e042ee0a5a..f22db3d34a5 100644 ---- a/src/sage/coding/meson.build -+++ b/src/sage/coding/meson.build -@@ -42,9 +42,9 @@ py.install_sources( - ) - - extension_data = { -- 'ag_code_decoders' : files('ag_code_decoders.pyx'), -- 'binary_code' : files('binary_code.pyx'), -- 'kasami_codes' : files('kasami_codes.pyx'), -+ 'ag_code_decoders': files('ag_code_decoders.pyx'), -+ 'binary_code': files('binary_code.pyx'), -+ 'kasami_codes': files('kasami_codes.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/combinat/crystals/meson.build b/src/sage/combinat/crystals/meson.build -index ee8da89b536..7353b581a7c 100644 ---- a/src/sage/combinat/crystals/meson.build -+++ b/src/sage/combinat/crystals/meson.build -@@ -44,10 +44,10 @@ py.install_sources( - ) - - extension_data = { -- 'letters' : files('letters.pyx'), -- 'pbw_datum' : files('pbw_datum.pyx'), -- 'spins' : files('spins.pyx'), -- 'tensor_product_element' : files('tensor_product_element.pyx'), -+ 'letters': files('letters.pyx'), -+ 'pbw_datum': files('pbw_datum.pyx'), -+ 'spins': files('spins.pyx'), -+ 'tensor_product_element': files('tensor_product_element.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/combinat/designs/meson.build b/src/sage/combinat/designs/meson.build -index 6f835bac5d1..1553c59f2e8 100644 ---- a/src/sage/combinat/designs/meson.build -+++ b/src/sage/combinat/designs/meson.build -@@ -29,13 +29,13 @@ py.install_sources( - ) - - extension_data = { -- 'designs_pyx' : files('designs_pyx.pyx'), -- 'evenly_distributed_sets' : files('evenly_distributed_sets.pyx'), -- 'gen_quadrangles_with_spread' : files('gen_quadrangles_with_spread.pyx'), -- 'orthogonal_arrays_find_recursive' : files( -+ 'designs_pyx': files('designs_pyx.pyx'), -+ 'evenly_distributed_sets': files('evenly_distributed_sets.pyx'), -+ 'gen_quadrangles_with_spread': files('gen_quadrangles_with_spread.pyx'), -+ 'orthogonal_arrays_find_recursive': files( - 'orthogonal_arrays_find_recursive.pyx', - ), -- 'subhypergraph_search' : files('subhypergraph_search.pyx'), -+ 'subhypergraph_search': files('subhypergraph_search.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/combinat/integer_lists/meson.build b/src/sage/combinat/integer_lists/meson.build -index cf3521f832c..3008fe329dc 100644 ---- a/src/sage/combinat/integer_lists/meson.build -+++ b/src/sage/combinat/integer_lists/meson.build -@@ -9,7 +9,7 @@ py.install_sources( - subdir: 'sage/combinat/integer_lists', - ) - --extension_data = {'base' : files('base.pyx'), 'invlex' : files('invlex.pyx')} -+extension_data = {'base': files('base.pyx'), 'invlex': files('invlex.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/combinat/meson.build b/src/sage/combinat/meson.build -index 9ee037678c8..bcd9d93a801 100644 ---- a/src/sage/combinat/meson.build -+++ b/src/sage/combinat/meson.build -@@ -145,17 +145,17 @@ py.install_sources( - ) - - extension_data = { -- 'combinat_cython' : files('combinat_cython.pyx'), -- 'debruijn_sequence' : files('debruijn_sequence.pyx'), -- 'degree_sequences' : files('degree_sequences.pyx'), -- 'enumeration_mod_permgroup' : files('enumeration_mod_permgroup.pyx'), -- 'expnums' : files('expnums.pyx'), -- 'fast_vector_partitions' : files('fast_vector_partitions.pyx'), -- 'partitions' : files('partitions.pyx'), -- 'permutation_cython' : files('permutation_cython.pyx'), -- 'q_bernoulli' : files('q_bernoulli.pyx'), -- 'set_partition_iterator' : files('set_partition_iterator.pyx'), -- 'subword_complex_c' : files('subword_complex_c.pyx'), -+ 'combinat_cython': files('combinat_cython.pyx'), -+ 'debruijn_sequence': files('debruijn_sequence.pyx'), -+ 'degree_sequences': files('degree_sequences.pyx'), -+ 'enumeration_mod_permgroup': files('enumeration_mod_permgroup.pyx'), -+ 'expnums': files('expnums.pyx'), -+ 'fast_vector_partitions': files('fast_vector_partitions.pyx'), -+ 'partitions': files('partitions.pyx'), -+ 'permutation_cython': files('permutation_cython.pyx'), -+ 'q_bernoulli': files('q_bernoulli.pyx'), -+ 'set_partition_iterator': files('set_partition_iterator.pyx'), -+ 'subword_complex_c': files('subword_complex_c.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/combinat/posets/meson.build b/src/sage/combinat/posets/meson.build -index 32c323c9dd0..ef7555d8465 100644 ---- a/src/sage/combinat/posets/meson.build -+++ b/src/sage/combinat/posets/meson.build -@@ -22,9 +22,9 @@ py.install_sources( - ) - - extension_data = { -- 'hasse_cython' : files('hasse_cython.pyx'), -- 'hasse_cython_flint' : files('hasse_cython_flint.pyx'), -- 'linear_extension_iterator' : files('linear_extension_iterator.pyx'), -+ 'hasse_cython': files('hasse_cython.pyx'), -+ 'hasse_cython_flint': files('hasse_cython_flint.pyx'), -+ 'linear_extension_iterator': files('linear_extension_iterator.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/combinat/rigged_configurations/meson.build b/src/sage/combinat/rigged_configurations/meson.build -index 549150d8ea6..c4422d13c7b 100644 ---- a/src/sage/combinat/rigged_configurations/meson.build -+++ b/src/sage/combinat/rigged_configurations/meson.build -@@ -27,7 +27,7 @@ py.install_sources( - subdir: 'sage/combinat/rigged_configurations', - ) - --extension_data = {'rigged_partition' : files('rigged_partition.pyx')} -+extension_data = {'rigged_partition': files('rigged_partition.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/combinat/root_system/meson.build b/src/sage/combinat/root_system/meson.build -index 66c596818b9..c79fedc2f4d 100644 ---- a/src/sage/combinat/root_system/meson.build -+++ b/src/sage/combinat/root_system/meson.build -@@ -62,9 +62,9 @@ py.install_sources( - ) - - extension_data = { -- 'braid_orbit' : files('braid_orbit.pyx'), -- 'reflection_group_c' : files('reflection_group_c.pyx'), -- 'reflection_group_element' : files('reflection_group_element.pyx'), -+ 'braid_orbit': files('braid_orbit.pyx'), -+ 'reflection_group_c': files('reflection_group_c.pyx'), -+ 'reflection_group_element': files('reflection_group_element.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/combinat/words/meson.build b/src/sage/combinat/words/meson.build -index 943528e2fa1..1fa9bf3baee 100644 ---- a/src/sage/combinat/words/meson.build -+++ b/src/sage/combinat/words/meson.build -@@ -23,8 +23,8 @@ py.install_sources( - ) - - extension_data = { -- 'word_char' : files('word_char.pyx'), -- 'word_datatypes' : files('word_datatypes.pyx'), -+ 'word_char': files('word_char.pyx'), -+ 'word_datatypes': files('word_datatypes.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/cpython/meson.build b/src/sage/cpython/meson.build -index 850d414b24f..e675ca84dad 100644 ---- a/src/sage/cpython/meson.build -+++ b/src/sage/cpython/meson.build -@@ -28,14 +28,14 @@ py.install_sources( - ) - - extension_data = { -- 'atexit' : files('atexit.pyx'), -- 'builtin_types' : files('builtin_types.pyx'), -- 'cython_metaclass' : files('cython_metaclass.pyx'), -- 'debug' : files('debug.pyx'), -- 'dict_del_by_value' : files('dict_del_by_value.pyx'), -- 'getattr' : files('getattr.pyx'), -- 'string' : files('string.pyx'), -- 'type' : files('type.pyx'), -+ 'atexit': files('atexit.pyx'), -+ 'builtin_types': files('builtin_types.pyx'), -+ 'cython_metaclass': files('cython_metaclass.pyx'), -+ 'debug': files('debug.pyx'), -+ 'dict_del_by_value': files('dict_del_by_value.pyx'), -+ 'getattr': files('getattr.pyx'), -+ 'string': files('string.pyx'), -+ 'type': files('type.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/crypto/meson.build b/src/sage/crypto/meson.build -index 62d6f49faa5..102a606c32b 100644 ---- a/src/sage/crypto/meson.build -+++ b/src/sage/crypto/meson.build -@@ -19,8 +19,8 @@ py.install_sources( - ) - - extension_data = { -- 'boolean_function' : files('boolean_function.pyx'), -- 'sbox' : files('sbox.pyx'), -+ 'boolean_function': files('boolean_function.pyx'), -+ 'sbox': files('sbox.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/data_structures/meson.build b/src/sage/data_structures/meson.build -index f0f33d885cb..0cc6d13bf83 100644 ---- a/src/sage/data_structures/meson.build -+++ b/src/sage/data_structures/meson.build -@@ -25,12 +25,12 @@ py.install_sources( - ) - - extension_data = { -- 'binary_search' : files('binary_search.pyx'), -- 'bitset' : files('bitset.pyx'), -- 'bitset_base' : files('bitset_base.pyx'), -- 'blas_dict' : files('blas_dict.pyx'), -- 'bounded_integer_sequences' : files('bounded_integer_sequences.pyx'), -- 'list_of_pairs' : files('list_of_pairs.pyx'), -+ 'binary_search': files('binary_search.pyx'), -+ 'bitset': files('bitset.pyx'), -+ 'bitset_base': files('bitset_base.pyx'), -+ 'blas_dict': files('blas_dict.pyx'), -+ 'bounded_integer_sequences': files('bounded_integer_sequences.pyx'), -+ 'list_of_pairs': files('list_of_pairs.pyx'), - } - - foreach name, pyx : extension_data -@@ -49,7 +49,7 @@ foreach name, pyx : extension_data - ) - endforeach - --extension_data_cpp = {'pairing_heap' : files('pairing_heap.pyx')} -+extension_data_cpp = {'pairing_heap': files('pairing_heap.pyx')} - - foreach name, pyx : extension_data_cpp - py.extension_module( -diff --git a/src/sage/dynamics/arithmetic_dynamics/meson.build b/src/sage/dynamics/arithmetic_dynamics/meson.build -index 6f56eb5d8cd..ca46499c713 100644 ---- a/src/sage/dynamics/arithmetic_dynamics/meson.build -+++ b/src/sage/dynamics/arithmetic_dynamics/meson.build -@@ -14,7 +14,7 @@ py.install_sources( - subdir: 'sage/dynamics/arithmetic_dynamics', - ) - --extension_data = {'projective_ds_helper' : files('projective_ds_helper.pyx')} -+extension_data = {'projective_ds_helper': files('projective_ds_helper.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/dynamics/complex_dynamics/meson.build b/src/sage/dynamics/complex_dynamics/meson.build -index f39e2237898..5319488776e 100644 ---- a/src/sage/dynamics/complex_dynamics/meson.build -+++ b/src/sage/dynamics/complex_dynamics/meson.build -@@ -6,7 +6,7 @@ py.install_sources( - subdir: 'sage/dynamics/complex_dynamics', - ) - --extension_data = {'mandel_julia_helper' : files('mandel_julia_helper.pyx')} -+extension_data = {'mandel_julia_helper': files('mandel_julia_helper.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/env.py b/src/sage/env.py -index 57b7371dd6a..6c3df0d93a7 100644 ---- a/src/sage/env.py -+++ b/src/sage/env.py -@@ -324,17 +324,8 @@ def sage_include_directories(use_sources=False): - return dirs - - --def get_cblas_pc_module_name() -> str: -- """ -- Return the name of the BLAS libraries to be used. -- """ -- import pkgconfig -- cblas_pc_modules = CBLAS_PC_MODULES.split(':') -- return next(blas_lib for blas_lib in cblas_pc_modules if pkgconfig.exists(blas_lib)) -- -- - default_required_modules = ('fflas-ffpack', 'givaro', 'gsl', 'linbox', 'Singular', -- 'libpng', 'gdlib', 'm4ri', 'zlib', 'cblas', 'ecl') -+ 'libpng', 'gdlib', 'm4ri', 'zlib', 'ecl') - - - default_optional_modules = ('lapack',) -@@ -359,7 +350,7 @@ def cython_aliases(required_modules=None, optional_modules=None): - sage: cython_aliases() - {...} - sage: sorted(cython_aliases().keys()) -- ['CBLAS_CFLAGS', -+ ['ECL_CFLAGS', - ..., - 'ZLIB_LIBRARIES'] - sage: cython_aliases(required_modules=('module-that-is-assumed-to-not-exist')) -@@ -406,8 +397,6 @@ def cython_aliases(required_modules=None, optional_modules=None): - for lib, required in itertools.chain(((lib, True) for lib in required_modules), - ((lib, False) for lib in optional_modules)): - var = lib.upper().replace("-", "") + "_" -- if lib == 'cblas': -- lib = get_cblas_pc_module_name() - if lib == 'zlib': - aliases[var + "CFLAGS"] = "" - try: -diff --git a/src/sage/ext/interpreters/meson.build b/src/sage/ext/interpreters/meson.build -index f965ce83da0..8445b7028c5 100644 ---- a/src/sage/ext/interpreters/meson.build -+++ b/src/sage/ext/interpreters/meson.build -@@ -41,12 +41,12 @@ interpreters = custom_target( - #endforeach - - extension_data = { -- 'wrapper_cc' : interpreters[7], -- 'wrapper_cdf' : interpreters[9], -- 'wrapper_el' : interpreters[11], -- 'wrapper_py' : interpreters[13], -- 'wrapper_rdf' : interpreters[15], -- 'wrapper_rr' : interpreters[17], -+ 'wrapper_cc': interpreters[7], -+ 'wrapper_cdf': interpreters[9], -+ 'wrapper_el': interpreters[11], -+ 'wrapper_py': interpreters[13], -+ 'wrapper_rdf': interpreters[15], -+ 'wrapper_rr': interpreters[17], - } - - interpreters_dep = declare_dependency( -diff --git a/src/sage/ext/meson.build b/src/sage/ext/meson.build -index 3c8ee5056d8..833684f832a 100644 ---- a/src/sage/ext/meson.build -+++ b/src/sage/ext/meson.build -@@ -14,9 +14,9 @@ py.install_sources( - ) - - extension_data = { -- 'fast_callable' : files('fast_callable.pyx'), -- 'fast_eval' : files('fast_eval.pyx'), -- 'memory' : files('memory.pyx'), -+ 'fast_callable': files('fast_callable.pyx'), -+ 'fast_eval': files('fast_eval.pyx'), -+ 'memory': files('memory.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/functions/meson.build b/src/sage/functions/meson.build -index c37ec96e9ff..2616fd37e50 100644 ---- a/src/sage/functions/meson.build -+++ b/src/sage/functions/meson.build -@@ -24,7 +24,7 @@ py.install_sources( - subdir: 'sage/functions', - ) - --extension_data = {'prime_pi' : files('prime_pi.pyx')} -+extension_data = {'prime_pi': files('prime_pi.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/games/meson.build b/src/sage/games/meson.build -index 11e322b4f67..d2aada916b1 100644 ---- a/src/sage/games/meson.build -+++ b/src/sage/games/meson.build -@@ -8,7 +8,7 @@ py.install_sources( - subdir: 'sage/games', - ) - --extension_data = {'sudoku_backtrack' : files('sudoku_backtrack.pyx')} -+extension_data = {'sudoku_backtrack': files('sudoku_backtrack.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/geometry/meson.build b/src/sage/geometry/meson.build -index 2acd9926344..25cef06e740 100644 ---- a/src/sage/geometry/meson.build -+++ b/src/sage/geometry/meson.build -@@ -30,12 +30,12 @@ py.install_sources( - ) - - extension_data = { -- 'abc' : files('abc.pyx'), -- 'integral_points_generic_dense' : files('integral_points_generic_dense.pyx'), -- 'integral_points_integer_dense' : files('integral_points_integer_dense.pyx'), -- 'palp_normal_form' : files('palp_normal_form.pyx'), -- 'point_collection' : files('point_collection.pyx'), -- 'toric_lattice_element' : files('toric_lattice_element.pyx'), -+ 'abc': files('abc.pyx'), -+ 'integral_points_generic_dense': files('integral_points_generic_dense.pyx'), -+ 'integral_points_integer_dense': files('integral_points_integer_dense.pyx'), -+ 'palp_normal_form': files('palp_normal_form.pyx'), -+ 'point_collection': files('point_collection.pyx'), -+ 'toric_lattice_element': files('toric_lattice_element.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/meson.build b/src/sage/geometry/polyhedron/combinatorial_polyhedron/meson.build -index a183940837c..9d023ed141d 100644 ---- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/meson.build -+++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/meson.build -@@ -20,13 +20,13 @@ py.install_sources( - ) - - extension_data = { -- 'base' : files('base.pyx'), -- 'combinatorial_face' : files('combinatorial_face.pyx'), -- 'conversions' : files('conversions.pyx'), -- 'face_iterator' : files('face_iterator.pyx'), -- 'face_list_data_structure' : files('face_list_data_structure.pyx'), -- 'list_of_faces' : files('list_of_faces.pyx'), -- 'polyhedron_face_lattice' : files('polyhedron_face_lattice.pyx'), -+ 'base': files('base.pyx'), -+ 'combinatorial_face': files('combinatorial_face.pyx'), -+ 'conversions': files('conversions.pyx'), -+ 'face_iterator': files('face_iterator.pyx'), -+ 'face_list_data_structure': files('face_list_data_structure.pyx'), -+ 'list_of_faces': files('list_of_faces.pyx'), -+ 'polyhedron_face_lattice': files('polyhedron_face_lattice.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/graphs/base/meson.build b/src/sage/graphs/base/meson.build -index 903db152bfe..25922eb6154 100644 ---- a/src/sage/graphs/base/meson.build -+++ b/src/sage/graphs/base/meson.build -@@ -22,11 +22,11 @@ py.install_sources( - ) - - extension_data = { -- 'dense_graph' : files('dense_graph.pyx'), -- 'graph_backends' : files('graph_backends.pyx'), -- 'sparse_graph' : files('sparse_graph.pyx'), -- 'static_dense_graph' : files('static_dense_graph.pyx'), -- 'static_sparse_backend' : files('static_sparse_backend.pyx'), -+ 'dense_graph': files('dense_graph.pyx'), -+ 'graph_backends': files('graph_backends.pyx'), -+ 'sparse_graph': files('sparse_graph.pyx'), -+ 'static_dense_graph': files('static_dense_graph.pyx'), -+ 'static_sparse_backend': files('static_sparse_backend.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/graphs/generators/meson.build b/src/sage/graphs/generators/meson.build -index eda4837c26c..6cbee41a2ef 100644 ---- a/src/sage/graphs/generators/meson.build -+++ b/src/sage/graphs/generators/meson.build -@@ -20,8 +20,8 @@ py.install_sources( - ) - - extension_data = { -- 'distance_regular' : files('distance_regular.pyx'), -- 'trees' : files('trees.pyx'), -+ 'distance_regular': files('distance_regular.pyx'), -+ 'trees': files('trees.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/graphs/graph_decompositions/meson.build b/src/sage/graphs/graph_decompositions/meson.build -index e30b80fac1e..06763ab1771 100644 ---- a/src/sage/graphs/graph_decompositions/meson.build -+++ b/src/sage/graphs/graph_decompositions/meson.build -@@ -31,13 +31,13 @@ py.install_sources( - ) - - extension_data = { -- 'bandwidth' : files('bandwidth.pyx'), -- 'cutwidth' : files('cutwidth.pyx'), -- 'fast_digraph' : files('fast_digraph.pyx'), -- 'graph_products' : files('graph_products.pyx'), -- 'rankwidth' : files('rankwidth.pyx'), -- 'tree_decomposition' : files('tree_decomposition.pyx'), -- 'vertex_separation' : files('vertex_separation.pyx'), -+ 'bandwidth': files('bandwidth.pyx'), -+ 'cutwidth': files('cutwidth.pyx'), -+ 'fast_digraph': files('fast_digraph.pyx'), -+ 'graph_products': files('graph_products.pyx'), -+ 'rankwidth': files('rankwidth.pyx'), -+ 'tree_decomposition': files('tree_decomposition.pyx'), -+ 'vertex_separation': files('vertex_separation.pyx'), - } - - foreach name, pyx : extension_data -@@ -57,8 +57,8 @@ endforeach - - extension_data_cpp = { - 'clique_separators': files('clique_separators.pyx'), -- 'slice_decomposition' : files('slice_decomposition.pyx'), -- 'modular_decomposition' : files('modular_decomposition.pyx'), -+ 'slice_decomposition': files('slice_decomposition.pyx'), -+ 'modular_decomposition': files('modular_decomposition.pyx'), - } - - foreach name, pyx : extension_data_cpp -diff --git a/src/sage/graphs/meson.build b/src/sage/graphs/meson.build -index d55d4013b03..fce249794c7 100644 ---- a/src/sage/graphs/meson.build -+++ b/src/sage/graphs/meson.build -@@ -94,27 +94,27 @@ py.install_sources( - - - extension_data = { -- 'asteroidal_triples' : files('asteroidal_triples.pyx'), -- 'centrality' : files('centrality.pyx'), -- 'chrompoly' : files('chrompoly.pyx'), -- 'cliquer' : files('cliquer.pyx'), -- 'comparability' : files('comparability.pyx'), -- 'connectivity' : files('connectivity.pyx'), -- 'convexity_properties' : files('convexity_properties.pyx'), -- 'distances_all_pairs' : files('distances_all_pairs.pyx'), -- 'generic_graph_pyx' : files('generic_graph_pyx.pyx'), -- 'genus' : files('genus.pyx'), -- 'graph_generators_pyx' : files('graph_generators_pyx.pyx'), -- 'hyperbolicity' : files('hyperbolicity.pyx'), -- 'independent_sets' : files('independent_sets.pyx'), -- 'isoperimetric_inequalities' : files('isoperimetric_inequalities.pyx'), -- 'line_graph' : files('line_graph.pyx'), -- 'matchpoly' : files('matchpoly.pyx'), -- 'planarity' : files('planarity.pyx'), -- 'spanning_tree' : files('spanning_tree.pyx'), -- 'strongly_regular_db' : files('strongly_regular_db.pyx'), -- 'views' : files('views.pyx'), -- 'weakly_chordal' : files('weakly_chordal.pyx'), -+ 'asteroidal_triples': files('asteroidal_triples.pyx'), -+ 'centrality': files('centrality.pyx'), -+ 'chrompoly': files('chrompoly.pyx'), -+ 'cliquer': files('cliquer.pyx'), -+ 'comparability': files('comparability.pyx'), -+ 'connectivity': files('connectivity.pyx'), -+ 'convexity_properties': files('convexity_properties.pyx'), -+ 'distances_all_pairs': files('distances_all_pairs.pyx'), -+ 'generic_graph_pyx': files('generic_graph_pyx.pyx'), -+ 'genus': files('genus.pyx'), -+ 'graph_generators_pyx': files('graph_generators_pyx.pyx'), -+ 'hyperbolicity': files('hyperbolicity.pyx'), -+ 'independent_sets': files('independent_sets.pyx'), -+ 'isoperimetric_inequalities': files('isoperimetric_inequalities.pyx'), -+ 'line_graph': files('line_graph.pyx'), -+ 'matchpoly': files('matchpoly.pyx'), -+ 'planarity': files('planarity.pyx'), -+ 'spanning_tree': files('spanning_tree.pyx'), -+ 'strongly_regular_db': files('strongly_regular_db.pyx'), -+ 'views': files('views.pyx'), -+ 'weakly_chordal': files('weakly_chordal.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/groups/matrix_gps/meson.build b/src/sage/groups/matrix_gps/meson.build -index 00ab019a0b1..0faf67b8329 100644 ---- a/src/sage/groups/matrix_gps/meson.build -+++ b/src/sage/groups/matrix_gps/meson.build -@@ -29,8 +29,8 @@ py.install_sources( - ) - - extension_data = { -- 'group_element' : files('group_element.pyx'), -- 'group_element_gap' : files('group_element_gap.pyx'), -+ 'group_element': files('group_element.pyx'), -+ 'group_element_gap': files('group_element_gap.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/groups/meson.build b/src/sage/groups/meson.build -index 256c3a76b92..86c294ea3ce 100644 ---- a/src/sage/groups/meson.build -+++ b/src/sage/groups/meson.build -@@ -33,8 +33,8 @@ py.install_sources( - ) - - extension_data = { -- 'group' : files('group.pyx'), -- 'libgap_wrapper' : files('libgap_wrapper.pyx'), -+ 'group': files('group.pyx'), -+ 'libgap_wrapper': files('libgap_wrapper.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/groups/perm_gps/meson.build b/src/sage/groups/perm_gps/meson.build -index 0ea630f847d..1c3461bea81 100644 ---- a/src/sage/groups/perm_gps/meson.build -+++ b/src/sage/groups/perm_gps/meson.build -@@ -13,7 +13,7 @@ py.install_sources( - subdir: 'sage/groups/perm_gps', - ) - --extension_data = {'permgroup_element' : files('permgroup_element.pyx')} -+extension_data = {'permgroup_element': files('permgroup_element.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/groups/perm_gps/partn_ref/meson.build b/src/sage/groups/perm_gps/partn_ref/meson.build -index 3e5687721ec..c047b23bd03 100644 ---- a/src/sage/groups/perm_gps/partn_ref/meson.build -+++ b/src/sage/groups/perm_gps/partn_ref/meson.build -@@ -25,18 +25,18 @@ py.install_sources( - ) - - extension_data = { -- 'automorphism_group_canonical_label' : files( -+ 'automorphism_group_canonical_label': files( - 'automorphism_group_canonical_label.pyx', - ), -- 'canonical_augmentation' : files('canonical_augmentation.pyx'), -- 'data_structures' : files('data_structures.pyx'), -- 'double_coset' : files('double_coset.pyx'), -- 'refinement_binary' : files('refinement_binary.pyx'), -- 'refinement_graphs' : files('refinement_graphs.pyx'), -- 'refinement_lists' : files('refinement_lists.pyx'), -- 'refinement_matrices' : files('refinement_matrices.pyx'), -- 'refinement_python' : files('refinement_python.pyx'), -- 'refinement_sets' : files('refinement_sets.pyx'), -+ 'canonical_augmentation': files('canonical_augmentation.pyx'), -+ 'data_structures': files('data_structures.pyx'), -+ 'double_coset': files('double_coset.pyx'), -+ 'refinement_binary': files('refinement_binary.pyx'), -+ 'refinement_graphs': files('refinement_graphs.pyx'), -+ 'refinement_lists': files('refinement_lists.pyx'), -+ 'refinement_matrices': files('refinement_matrices.pyx'), -+ 'refinement_python': files('refinement_python.pyx'), -+ 'refinement_sets': files('refinement_sets.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/groups/perm_gps/partn_ref2/meson.build b/src/sage/groups/perm_gps/partn_ref2/meson.build -index 55e2ad83c52..7d0da166ddc 100644 ---- a/src/sage/groups/perm_gps/partn_ref2/meson.build -+++ b/src/sage/groups/perm_gps/partn_ref2/meson.build -@@ -6,7 +6,7 @@ py.install_sources( - subdir: 'sage/groups/perm_gps/partn_ref2', - ) - --extension_data = {'refinement_generic' : files('refinement_generic.pyx')} -+extension_data = {'refinement_generic': files('refinement_generic.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/groups/semimonomial_transformations/meson.build b/src/sage/groups/semimonomial_transformations/meson.build -index e9b3232b24a..d210dca2aff 100644 ---- a/src/sage/groups/semimonomial_transformations/meson.build -+++ b/src/sage/groups/semimonomial_transformations/meson.build -@@ -8,7 +8,7 @@ py.install_sources( - ) - - extension_data = { -- 'semimonomial_transformation' : files('semimonomial_transformation.pyx'), -+ 'semimonomial_transformation': files('semimonomial_transformation.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/interacts/meson.build b/src/sage/interacts/meson.build -index b3e2bbdddeb..ad9212363db 100644 ---- a/src/sage/interacts/meson.build -+++ b/src/sage/interacts/meson.build -@@ -11,7 +11,7 @@ py.install_sources( - subdir: 'sage/interacts', - ) - --extension_data = {'library_cython' : files('library_cython.pyx')} -+extension_data = {'library_cython': files('library_cython.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/interfaces/meson.build b/src/sage/interfaces/meson.build -index 18d13e7771b..6245e54154b 100644 ---- a/src/sage/interfaces/meson.build -+++ b/src/sage/interfaces/meson.build -@@ -65,8 +65,8 @@ py.install_sources( - ) - - extension_data = { -- 'process' : files('process.pyx'), -- 'sagespawn' : files('sagespawn.pyx'), -+ 'process': files('process.pyx'), -+ 'sagespawn': files('sagespawn.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/lfunctions/meson.build b/src/sage/lfunctions/meson.build -index 09a51db11bb..8537e233edc 100644 ---- a/src/sage/lfunctions/meson.build -+++ b/src/sage/lfunctions/meson.build -@@ -9,7 +9,7 @@ py.install_sources( - subdir: 'sage/lfunctions', - ) - --extension_data = {'zero_sums' : files('zero_sums.pyx')} -+extension_data = {'zero_sums': files('zero_sums.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/libs/arb/meson.build b/src/sage/libs/arb/meson.build -index a3ee01097af..e58eddb2f6f 100644 ---- a/src/sage/libs/arb/meson.build -+++ b/src/sage/libs/arb/meson.build -@@ -19,7 +19,7 @@ py.install_sources( - subdir: 'sage/libs/arb', - ) - --extension_data = {'arith' : files('arith.pyx')} -+extension_data = {'arith': files('arith.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/libs/flint/meson.build b/src/sage/libs/flint/meson.build -index 2350dbaf013..eeefdc536ea 100644 ---- a/src/sage/libs/flint/meson.build -+++ b/src/sage/libs/flint/meson.build -@@ -162,17 +162,17 @@ py.install_sources( - ) - - extension_data = { -- 'arith' : files('arith.pyx'), -- 'arith_sage' : files('arith_sage.pyx'), -- 'flint_sage' : files('flint_sage.pyx'), -- 'fmpq_poly_sage' : files('fmpq_poly_sage.pyx'), -- 'fmpz_factor_sage' : files('fmpz_factor_sage.pyx'), -- 'fmpz_poly' : files('fmpz_poly.pyx'), -- 'fmpz_poly_sage' : files('fmpz_poly_sage.pyx'), -- 'qsieve' : files('qsieve.pyx'), -- 'qsieve_sage' : files('qsieve_sage.pyx'), -- 'ulong_extras' : files('ulong_extras.pyx'), -- 'ulong_extras_sage' : files('ulong_extras_sage.pyx'), -+ 'arith': files('arith.pyx'), -+ 'arith_sage': files('arith_sage.pyx'), -+ 'flint_sage': files('flint_sage.pyx'), -+ 'fmpq_poly_sage': files('fmpq_poly_sage.pyx'), -+ 'fmpz_factor_sage': files('fmpz_factor_sage.pyx'), -+ 'fmpz_poly': files('fmpz_poly.pyx'), -+ 'fmpz_poly_sage': files('fmpz_poly_sage.pyx'), -+ 'qsieve': files('qsieve.pyx'), -+ 'qsieve_sage': files('qsieve_sage.pyx'), -+ 'ulong_extras': files('ulong_extras.pyx'), -+ 'ulong_extras_sage': files('ulong_extras_sage.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/libs/gap/meson.build b/src/sage/libs/gap/meson.build -index ed0bad3bcce..af77ea307b0 100644 ---- a/src/sage/libs/gap/meson.build -+++ b/src/sage/libs/gap/meson.build -@@ -23,9 +23,9 @@ py.install_sources( - fs.copyfile('sage.gaprc') - - extension_data = { -- 'element' : files('element.pyx'), -- 'libgap' : files('libgap.pyx'), -- 'util' : files('util.pyx'), -+ 'element': files('element.pyx'), -+ 'libgap': files('libgap.pyx'), -+ 'util': files('util.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/libs/gmp/meson.build b/src/sage/libs/gmp/meson.build -index 42a1e652267..26bf24d5084 100644 ---- a/src/sage/libs/gmp/meson.build -+++ b/src/sage/libs/gmp/meson.build -@@ -15,7 +15,7 @@ py.install_sources( - subdir: 'sage/libs/gmp', - ) - --extension_data = {'pylong' : files('pylong.pyx')} -+extension_data = {'pylong': files('pylong.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/libs/gsl/meson.build b/src/sage/libs/gsl/meson.build -index b96776f35a8..a70c61d1297 100644 ---- a/src/sage/libs/gsl/meson.build -+++ b/src/sage/libs/gsl/meson.build -@@ -68,7 +68,7 @@ py.install_sources( - subdir: 'sage/libs/gsl', - ) - --extension_data = {'array' : files('array.pyx')} -+extension_data = {'array': files('array.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/libs/mpmath/meson.build b/src/sage/libs/mpmath/meson.build -index a49cfaa64df..cc8cdc84e98 100644 ---- a/src/sage/libs/mpmath/meson.build -+++ b/src/sage/libs/mpmath/meson.build -@@ -12,10 +12,10 @@ py.install_sources( - ) - - extension_data = { -- 'ext_impl' : files('ext_impl.pyx'), -- 'ext_libmp' : files('ext_libmp.pyx'), -- 'ext_main' : files('ext_main.pyx'), -- 'utils' : files('utils.pyx'), -+ 'ext_impl': files('ext_impl.pyx'), -+ 'ext_libmp': files('ext_libmp.pyx'), -+ 'ext_main': files('ext_main.pyx'), -+ 'utils': files('utils.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/libs/pari/meson.build b/src/sage/libs/pari/meson.build -index 9df9ad0861e..817aca83c0c 100644 ---- a/src/sage/libs/pari/meson.build -+++ b/src/sage/libs/pari/meson.build -@@ -21,14 +21,14 @@ py.install_sources( - ) - - extension_data = { -- 'convert_flint' : files('convert_flint.pyx'), -- 'convert_gmp' : files('convert_gmp.pyx'), -- 'convert_sage' : files('convert_sage.pyx'), -- 'convert_sage_complex_double' : files('convert_sage_complex_double.pyx'), -- 'convert_sage_matrix' : files('convert_sage_matrix.pyx'), -- 'convert_sage_real_double' : files('convert_sage_real_double.pyx'), -- 'convert_sage_real_mpfr' : files('convert_sage_real_mpfr.pyx'), -- 'misc' : files('misc.pyx'), -+ 'convert_flint': files('convert_flint.pyx'), -+ 'convert_gmp': files('convert_gmp.pyx'), -+ 'convert_sage': files('convert_sage.pyx'), -+ 'convert_sage_complex_double': files('convert_sage_complex_double.pyx'), -+ 'convert_sage_matrix': files('convert_sage_matrix.pyx'), -+ 'convert_sage_real_double': files('convert_sage_real_double.pyx'), -+ 'convert_sage_real_mpfr': files('convert_sage_real_mpfr.pyx'), -+ 'misc': files('misc.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/libs/symmetrica/meson.build b/src/sage/libs/symmetrica/meson.build -index 2cc224eb082..6d14c74c397 100644 ---- a/src/sage/libs/symmetrica/meson.build -+++ b/src/sage/libs/symmetrica/meson.build -@@ -15,7 +15,7 @@ py.install_sources( - subdir: 'sage/libs/symmetrica', - ) - --extension_data = {'symmetrica' : files('symmetrica.pyx')} -+extension_data = {'symmetrica': files('symmetrica.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/matrix/meson.build b/src/sage/matrix/meson.build -index 3e703312d11..c15ff3f0dd6 100644 ---- a/src/sage/matrix/meson.build -+++ b/src/sage/matrix/meson.build -@@ -101,40 +101,40 @@ py.install_sources( - ) - - extension_data = { -- 'action' : files('action.pyx'), -- 'args' : files('args.pyx'), -- 'change_ring' : files('change_ring.pyx'), -- 'constructor' : files('constructor.pyx'), -- 'echelon_matrix' : files('echelon_matrix.pyx'), -- 'matrix0' : files('matrix0.pyx'), -- 'matrix1' : files('matrix1.pyx'), -- 'matrix2' : files('matrix2.pyx'), -- 'matrix_cdv' : files('matrix_cdv.pyx'), -- 'matrix_complex_ball_dense' : files('matrix_complex_ball_dense.pyx'), -- 'matrix_complex_double_dense' : files('matrix_complex_double_dense.pyx'), -- 'matrix_dense' : files('matrix_dense.pyx'), -- 'matrix_double_dense' : files('matrix_double_dense.pyx'), -- 'matrix_double_sparse' : files('matrix_double_sparse.pyx'), -- 'matrix_gap' : files('matrix_gap.pyx'), -- 'matrix_generic_dense' : files('matrix_generic_dense.pyx'), -- 'matrix_generic_sparse' : files('matrix_generic_sparse.pyx'), -- 'matrix_gfpn_dense' : files('matrix_gfpn_dense.pyx'), -+ 'action': files('action.pyx'), -+ 'args': files('args.pyx'), -+ 'change_ring': files('change_ring.pyx'), -+ 'constructor': files('constructor.pyx'), -+ 'echelon_matrix': files('echelon_matrix.pyx'), -+ 'matrix0': files('matrix0.pyx'), -+ 'matrix1': files('matrix1.pyx'), -+ 'matrix2': files('matrix2.pyx'), -+ 'matrix_cdv': files('matrix_cdv.pyx'), -+ 'matrix_complex_ball_dense': files('matrix_complex_ball_dense.pyx'), -+ 'matrix_complex_double_dense': files('matrix_complex_double_dense.pyx'), -+ 'matrix_dense': files('matrix_dense.pyx'), -+ 'matrix_double_dense': files('matrix_double_dense.pyx'), -+ 'matrix_double_sparse': files('matrix_double_sparse.pyx'), -+ 'matrix_gap': files('matrix_gap.pyx'), -+ 'matrix_generic_dense': files('matrix_generic_dense.pyx'), -+ 'matrix_generic_sparse': files('matrix_generic_sparse.pyx'), -+ 'matrix_gfpn_dense': files('matrix_gfpn_dense.pyx'), - 'matrix_gf2e_dense': files('matrix_gf2e_dense.pyx'), -- 'matrix_laurent_mpolynomial_dense' : files( -+ 'matrix_laurent_mpolynomial_dense': files( - 'matrix_laurent_mpolynomial_dense.pyx', - ), -- 'matrix_numpy_dense' : files('matrix_numpy_dense.pyx'), -- 'matrix_numpy_integer_dense' : files('matrix_numpy_integer_dense.pyx'), -- 'matrix_polynomial_dense' : files('matrix_polynomial_dense.pyx'), -- 'matrix_real_double_dense' : files('matrix_real_double_dense.pyx'), -- 'matrix_sparse' : files('matrix_sparse.pyx'), -- 'matrix_symbolic_dense' : files('matrix_symbolic_dense.pyx'), -- 'matrix_symbolic_sparse' : files('matrix_symbolic_sparse.pyx'), -- 'matrix_window' : files('matrix_window.pyx'), -- 'misc' : files('misc.pyx'), -- 'misc_flint' : files('misc_flint.pyx'), -- 'misc_mpfr' : files('misc_mpfr.pyx'), -- 'strassen' : files('strassen.pyx'), -+ 'matrix_numpy_dense': files('matrix_numpy_dense.pyx'), -+ 'matrix_numpy_integer_dense': files('matrix_numpy_integer_dense.pyx'), -+ 'matrix_polynomial_dense': files('matrix_polynomial_dense.pyx'), -+ 'matrix_real_double_dense': files('matrix_real_double_dense.pyx'), -+ 'matrix_sparse': files('matrix_sparse.pyx'), -+ 'matrix_symbolic_dense': files('matrix_symbolic_dense.pyx'), -+ 'matrix_symbolic_sparse': files('matrix_symbolic_sparse.pyx'), -+ 'matrix_window': files('matrix_window.pyx'), -+ 'misc': files('misc.pyx'), -+ 'misc_flint': files('misc_flint.pyx'), -+ 'misc_mpfr': files('misc_mpfr.pyx'), -+ 'strassen': files('strassen.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/matroids/meson.build b/src/sage/matroids/meson.build -index 98187387863..a69fcbef5fb 100644 ---- a/src/sage/matroids/meson.build -+++ b/src/sage/matroids/meson.build -@@ -47,20 +47,20 @@ py.install_sources( - ) - - extension_data = { -- 'basis_exchange_matroid' : files('basis_exchange_matroid.pyx'), -- 'basis_matroid' : files('basis_matroid.pyx'), -- 'circuit_closures_matroid' : files('circuit_closures_matroid.pyx'), -- 'circuits_matroid' : files('circuits_matroid.pyx'), -- 'extension' : files('extension.pyx'), -- 'lean_matrix' : files('lean_matrix.pyx'), -- 'linear_matroid' : files('linear_matroid.pyx'), -- 'matroid' : files('matroid.pyx'), -- 'set_system' : files('set_system.pyx'), -- 'transversal_matroid' : files('transversal_matroid.pyx'), -- 'union_matroid' : files('union_matroid.pyx'), -- 'unpickling' : files('unpickling.pyx'), -- 'flats_matroid' : files('flats_matroid.pyx'), -- 'graphic_matroid' : files('graphic_matroid.pyx'), -+ 'basis_exchange_matroid': files('basis_exchange_matroid.pyx'), -+ 'basis_matroid': files('basis_matroid.pyx'), -+ 'circuit_closures_matroid': files('circuit_closures_matroid.pyx'), -+ 'circuits_matroid': files('circuits_matroid.pyx'), -+ 'extension': files('extension.pyx'), -+ 'lean_matrix': files('lean_matrix.pyx'), -+ 'linear_matroid': files('linear_matroid.pyx'), -+ 'matroid': files('matroid.pyx'), -+ 'set_system': files('set_system.pyx'), -+ 'transversal_matroid': files('transversal_matroid.pyx'), -+ 'union_matroid': files('union_matroid.pyx'), -+ 'unpickling': files('unpickling.pyx'), -+ 'flats_matroid': files('flats_matroid.pyx'), -+ 'graphic_matroid': files('graphic_matroid.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py -index 5c2b53217a2..82ab564d4e1 100644 ---- a/src/sage/misc/cython.py -+++ b/src/sage/misc/cython.py -@@ -50,16 +50,12 @@ def _standard_libs_libdirs_incdirs_aliases(): - {...}) - """ - aliases = cython_aliases() -- standard_libs = [ -- 'mpfr', 'gmp', 'gmpxx', 'pari', 'm', -- 'ec', 'gsl', -- ] + aliases["CBLAS_LIBRARIES"] + [ -- 'ntl'] -+ standard_libs = ["mpfr", "gmp", "gmpxx", "pari", "m", "ec", "gsl", "ntl"] - standard_libdirs = [] - if SAGE_LOCAL: - standard_libdirs.append(os.path.join(SAGE_LOCAL, "lib")) -- standard_libdirs.extend(aliases["CBLAS_LIBDIR"] + aliases["NTL_LIBDIR"]) -- standard_incdirs = [dir.as_posix() for dir in get_include_dirs()] + aliases["CBLAS_INCDIR"] + aliases["NTL_INCDIR"] -+ standard_libdirs.extend(aliases["NTL_LIBDIR"]) -+ standard_incdirs = [dir.as_posix() for dir in get_include_dirs()] + aliases["NTL_INCDIR"] - return standard_libs, standard_libdirs, standard_incdirs, aliases - - ################################################################ -diff --git a/src/sage/misc/meson.build b/src/sage/misc/meson.build -index f44095ff136..e56df568eb2 100644 ---- a/src/sage/misc/meson.build -+++ b/src/sage/misc/meson.build -@@ -119,38 +119,38 @@ py.install_sources( - ) - - extension_data = { -- 'allocator' : files('allocator.pyx'), -- 'binary_tree' : files('binary_tree.pyx'), -- 'c3' : files('c3.pyx'), -- 'c3_controlled' : files('c3_controlled.pyx'), -- 'cachefunc' : files('cachefunc.pyx'), -- 'callable_dict' : files('callable_dict.pyx'), -- 'citation' : files('citation.pyx'), -- 'classcall_metaclass' : files('classcall_metaclass.pyx'), -- 'constant_function' : files('constant_function.pyx'), -- 'derivative' : files('derivative.pyx'), -- 'fast_methods' : files('fast_methods.pyx'), -- 'fpickle' : files('fpickle.pyx'), -- 'function_mangling' : files('function_mangling.pyx'), -- 'inherit_comparison' : files('inherit_comparison.pyx'), -- 'instancedoc' : files('instancedoc.pyx'), -- 'lazy_attribute' : files('lazy_attribute.pyx'), -- 'lazy_import' : files('lazy_import.pyx'), -- 'lazy_list' : files('lazy_list.pyx'), -- 'lazy_string' : files('lazy_string.pyx'), -- 'misc_c' : files('misc_c.pyx'), -- 'nested_class' : files('nested_class.pyx'), -- 'parser' : files('parser.pyx'), -- 'persist' : files('persist.pyx'), -- 'pickle_old' : files('pickle_old.pyx'), -- 'randstate' : files('randstate.pyx'), -- 'reset' : files('reset.pyx'), -- 'sage_ostools' : files('sage_ostools.pyx'), -- 'sage_timeit_class' : files('sage_timeit_class.pyx'), -- 'search' : files('search.pyx'), -- 'session' : files('session.pyx'), -- 'stopgap' : files('stopgap.pyx'), -- 'weak_dict' : files('weak_dict.pyx'), -+ 'allocator': files('allocator.pyx'), -+ 'binary_tree': files('binary_tree.pyx'), -+ 'c3': files('c3.pyx'), -+ 'c3_controlled': files('c3_controlled.pyx'), -+ 'cachefunc': files('cachefunc.pyx'), -+ 'callable_dict': files('callable_dict.pyx'), -+ 'citation': files('citation.pyx'), -+ 'classcall_metaclass': files('classcall_metaclass.pyx'), -+ 'constant_function': files('constant_function.pyx'), -+ 'derivative': files('derivative.pyx'), -+ 'fast_methods': files('fast_methods.pyx'), -+ 'fpickle': files('fpickle.pyx'), -+ 'function_mangling': files('function_mangling.pyx'), -+ 'inherit_comparison': files('inherit_comparison.pyx'), -+ 'instancedoc': files('instancedoc.pyx'), -+ 'lazy_attribute': files('lazy_attribute.pyx'), -+ 'lazy_import': files('lazy_import.pyx'), -+ 'lazy_list': files('lazy_list.pyx'), -+ 'lazy_string': files('lazy_string.pyx'), -+ 'misc_c': files('misc_c.pyx'), -+ 'nested_class': files('nested_class.pyx'), -+ 'parser': files('parser.pyx'), -+ 'persist': files('persist.pyx'), -+ 'pickle_old': files('pickle_old.pyx'), -+ 'randstate': files('randstate.pyx'), -+ 'reset': files('reset.pyx'), -+ 'sage_ostools': files('sage_ostools.pyx'), -+ 'sage_timeit_class': files('sage_timeit_class.pyx'), -+ 'search': files('search.pyx'), -+ 'session': files('session.pyx'), -+ 'stopgap': files('stopgap.pyx'), -+ 'weak_dict': files('weak_dict.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/modular/arithgroup/meson.build b/src/sage/modular/arithgroup/meson.build -index 14de8056ac4..f099b12eb07 100644 ---- a/src/sage/modular/arithgroup/meson.build -+++ b/src/sage/modular/arithgroup/meson.build -@@ -17,8 +17,8 @@ py.install_sources( - ) - - extension_data = { -- 'arithgroup_element' : files('arithgroup_element.pyx'), -- 'congroup' : files('congroup.pyx'), -+ 'arithgroup_element': files('arithgroup_element.pyx'), -+ 'congroup': files('congroup.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/modular/meson.build b/src/sage/modular/meson.build -index ce0b69b112e..4d66ac75fc1 100644 ---- a/src/sage/modular/meson.build -+++ b/src/sage/modular/meson.build -@@ -17,7 +17,7 @@ py.install_sources( - subdir: 'sage/modular', - ) - --extension_data = {'hypergeometric_misc' : files('hypergeometric_misc.pyx')} -+extension_data = {'hypergeometric_misc': files('hypergeometric_misc.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/modular/modform/meson.build b/src/sage/modular/modform/meson.build -index 11ec687d275..0ed9fee9966 100644 ---- a/src/sage/modular/modform/meson.build -+++ b/src/sage/modular/modform/meson.build -@@ -32,8 +32,8 @@ py.install_sources( - ) - - extension_data = { -- 'eis_series_cython' : files('eis_series_cython.pyx'), -- 'l_series_gross_zagier_coeffs' : files('l_series_gross_zagier_coeffs.pyx'), -+ 'eis_series_cython': files('eis_series_cython.pyx'), -+ 'l_series_gross_zagier_coeffs': files('l_series_gross_zagier_coeffs.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/modular/modsym/meson.build b/src/sage/modular/modsym/meson.build -index 63e8ced7d53..6b284a0766a 100644 ---- a/src/sage/modular/modsym/meson.build -+++ b/src/sage/modular/modsym/meson.build -@@ -27,11 +27,11 @@ py.install_sources( - ) - - extension_data = { -- 'apply' : files('apply.pyx'), -- 'heilbronn' : files('heilbronn.pyx'), -- 'manin_symbol' : files('manin_symbol.pyx'), -- 'p1list' : files('p1list.pyx'), -- 'relation_matrix_pyx' : files('relation_matrix_pyx.pyx'), -+ 'apply': files('apply.pyx'), -+ 'heilbronn': files('heilbronn.pyx'), -+ 'manin_symbol': files('manin_symbol.pyx'), -+ 'p1list': files('p1list.pyx'), -+ 'relation_matrix_pyx': files('relation_matrix_pyx.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/modular/pollack_stevens/meson.build b/src/sage/modular/pollack_stevens/meson.build -index 8724ee0df43..f34fc978707 100644 ---- a/src/sage/modular/pollack_stevens/meson.build -+++ b/src/sage/modular/pollack_stevens/meson.build -@@ -13,7 +13,7 @@ py.install_sources( - subdir: 'sage/modular/pollack_stevens', - ) - --extension_data = {'dist' : files('dist.pyx')} -+extension_data = {'dist': files('dist.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/modules/meson.build b/src/sage/modules/meson.build -index 6d73f06888c..e74fa44c904 100644 ---- a/src/sage/modules/meson.build -+++ b/src/sage/modules/meson.build -@@ -68,20 +68,20 @@ py.install_sources( - ) - - extension_data = { -- 'finite_submodule_iter' : files('finite_submodule_iter.pyx'), -- 'free_module_element' : files('free_module_element.pyx'), -- 'module' : files('module.pyx'), -- 'vector_complex_double_dense' : files('vector_complex_double_dense.pyx'), -- 'vector_double_dense' : files('vector_double_dense.pyx'), -- 'vector_integer_dense' : files('vector_integer_dense.pyx'), -- 'vector_integer_sparse' : files('vector_integer_sparse.pyx'), -- 'vector_modn_dense' : files('vector_modn_dense.pyx'), -- 'vector_modn_sparse' : files('vector_modn_sparse.pyx'), -- 'vector_numpy_dense' : files('vector_numpy_dense.pyx'), -- 'vector_numpy_integer_dense' : files('vector_numpy_integer_dense.pyx'), -- 'vector_rational_dense' : files('vector_rational_dense.pyx'), -- 'vector_rational_sparse' : files('vector_rational_sparse.pyx'), -- 'vector_real_double_dense' : files('vector_real_double_dense.pyx'), -+ 'finite_submodule_iter': files('finite_submodule_iter.pyx'), -+ 'free_module_element': files('free_module_element.pyx'), -+ 'module': files('module.pyx'), -+ 'vector_complex_double_dense': files('vector_complex_double_dense.pyx'), -+ 'vector_double_dense': files('vector_double_dense.pyx'), -+ 'vector_integer_dense': files('vector_integer_dense.pyx'), -+ 'vector_integer_sparse': files('vector_integer_sparse.pyx'), -+ 'vector_modn_dense': files('vector_modn_dense.pyx'), -+ 'vector_modn_sparse': files('vector_modn_sparse.pyx'), -+ 'vector_numpy_dense': files('vector_numpy_dense.pyx'), -+ 'vector_numpy_integer_dense': files('vector_numpy_integer_dense.pyx'), -+ 'vector_rational_dense': files('vector_rational_dense.pyx'), -+ 'vector_rational_sparse': files('vector_rational_sparse.pyx'), -+ 'vector_real_double_dense': files('vector_real_double_dense.pyx'), - } - - foreach name, pyx : extension_data -@@ -96,7 +96,7 @@ foreach name, pyx : extension_data - endforeach - - extension_data_cpp = { -- 'numpy_util' : files('numpy_util.pyx'), -+ 'numpy_util': files('numpy_util.pyx'), - 'vector_mod2_dense': files('vector_mod2_dense.pyx'), - } - -diff --git a/src/sage/modules/with_basis/meson.build b/src/sage/modules/with_basis/meson.build -index 971012fcf4c..f96bfba3cf7 100644 ---- a/src/sage/modules/with_basis/meson.build -+++ b/src/sage/modules/with_basis/meson.build -@@ -11,7 +11,7 @@ py.install_sources( - subdir: 'sage/modules/with_basis', - ) - --extension_data = {'indexed_element' : files('indexed_element.pyx')} -+extension_data = {'indexed_element': files('indexed_element.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/monoids/meson.build b/src/sage/monoids/meson.build -index 9b590ee95df..8f07db72cb2 100644 ---- a/src/sage/monoids/meson.build -+++ b/src/sage/monoids/meson.build -@@ -18,7 +18,7 @@ py.install_sources( - ) - - extension_data = { -- 'free_abelian_monoid_element' : files('free_abelian_monoid_element.pyx'), -+ 'free_abelian_monoid_element': files('free_abelian_monoid_element.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/numerical/backends/meson.build b/src/sage/numerical/backends/meson.build -index 57454e81e88..c9fa626eafe 100644 ---- a/src/sage/numerical/backends/meson.build -+++ b/src/sage/numerical/backends/meson.build -@@ -38,17 +38,17 @@ py.install_sources( - ) - - extension_data = { -- 'cvxopt_backend' : files('cvxopt_backend.pyx'), -- 'cvxopt_sdp_backend' : files('cvxopt_sdp_backend.pyx'), -- 'cvxpy_backend' : files('cvxpy_backend.pyx'), -- 'generic_backend' : files('generic_backend.pyx'), -- 'generic_sdp_backend' : files('generic_sdp_backend.pyx'), -- 'glpk_backend' : files('glpk_backend.pyx'), -- 'glpk_exact_backend' : files('glpk_exact_backend.pyx'), -- 'glpk_graph_backend' : files('glpk_graph_backend.pyx'), -- 'interactivelp_backend' : files('interactivelp_backend.pyx'), -- 'matrix_sdp_backend' : files('matrix_sdp_backend.pyx'), -- 'ppl_backend' : files('ppl_backend.pyx'), -+ 'cvxopt_backend': files('cvxopt_backend.pyx'), -+ 'cvxopt_sdp_backend': files('cvxopt_sdp_backend.pyx'), -+ 'cvxpy_backend': files('cvxpy_backend.pyx'), -+ 'generic_backend': files('generic_backend.pyx'), -+ 'generic_sdp_backend': files('generic_sdp_backend.pyx'), -+ 'glpk_backend': files('glpk_backend.pyx'), -+ 'glpk_exact_backend': files('glpk_exact_backend.pyx'), -+ 'glpk_graph_backend': files('glpk_graph_backend.pyx'), -+ 'interactivelp_backend': files('interactivelp_backend.pyx'), -+ 'matrix_sdp_backend': files('matrix_sdp_backend.pyx'), -+ 'ppl_backend': files('ppl_backend.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/numerical/meson.build b/src/sage/numerical/meson.build -index 718df394a61..cf7ad6b7c3b 100644 ---- a/src/sage/numerical/meson.build -+++ b/src/sage/numerical/meson.build -@@ -19,11 +19,11 @@ py.install_sources( - ) - - extension_data = { -- 'gauss_legendre' : files('gauss_legendre.pyx'), -- 'linear_functions' : files('linear_functions.pyx'), -- 'linear_tensor_element' : files('linear_tensor_element.pyx'), -- 'mip' : files('mip.pyx'), -- 'sdp' : files('sdp.pyx'), -+ 'gauss_legendre': files('gauss_legendre.pyx'), -+ 'linear_functions': files('linear_functions.pyx'), -+ 'linear_tensor_element': files('linear_tensor_element.pyx'), -+ 'mip': files('mip.pyx'), -+ 'sdp': files('sdp.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/plot/meson.build b/src/sage/plot/meson.build -index aa0ef708923..28eaedf478c 100644 ---- a/src/sage/plot/meson.build -+++ b/src/sage/plot/meson.build -@@ -34,7 +34,7 @@ py.install_sources( - subdir: 'sage/plot', - ) - --extension_data = {'complex_plot' : files('complex_plot.pyx')} -+extension_data = {'complex_plot': files('complex_plot.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/plot/plot3d/meson.build b/src/sage/plot/plot3d/meson.build -index cf8e33a2c5d..ab5e1d17d99 100644 ---- a/src/sage/plot/plot3d/meson.build -+++ b/src/sage/plot/plot3d/meson.build -@@ -28,12 +28,12 @@ py.install_sources( - ) - - extension_data = { -- 'base' : files('base.pyx'), -- 'implicit_surface' : files('implicit_surface.pyx'), -- 'index_face_set' : files('index_face_set.pyx'), -- 'shapes' : files('shapes.pyx'), -- 'transform' : files('transform.pyx'), -- 'parametric_surface' : files('parametric_surface.pyx'), -+ 'base': files('base.pyx'), -+ 'implicit_surface': files('implicit_surface.pyx'), -+ 'index_face_set': files('index_face_set.pyx'), -+ 'shapes': files('shapes.pyx'), -+ 'transform': files('transform.pyx'), -+ 'parametric_surface': files('parametric_surface.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/probability/meson.build b/src/sage/probability/meson.build -index 008efb6bf34..b58d3c10cea 100644 ---- a/src/sage/probability/meson.build -+++ b/src/sage/probability/meson.build -@@ -7,7 +7,7 @@ py.install_sources( - ) - - extension_data = { -- 'probability_distribution' : files('probability_distribution.pyx'), -+ 'probability_distribution': files('probability_distribution.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/quadratic_forms/meson.build b/src/sage/quadratic_forms/meson.build -index d7d8bb0a6c1..170c8920dba 100644 ---- a/src/sage/quadratic_forms/meson.build -+++ b/src/sage/quadratic_forms/meson.build -@@ -36,9 +36,9 @@ py.install_sources( - ) - - extension_data = { -- 'count_local_2' : files('count_local_2.pyx'), -- 'quadratic_form__evaluate' : files('quadratic_form__evaluate.pyx'), -- 'ternary' : files('ternary.pyx'), -+ 'count_local_2': files('count_local_2.pyx'), -+ 'quadratic_form__evaluate': files('quadratic_form__evaluate.pyx'), -+ 'ternary': files('ternary.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/quivers/meson.build b/src/sage/quivers/meson.build -index 6d93bb01a06..451056ea4bb 100644 ---- a/src/sage/quivers/meson.build -+++ b/src/sage/quivers/meson.build -@@ -15,8 +15,8 @@ py.install_sources( - ) - - extension_data = { -- 'algebra_elements' : files('algebra_elements.pyx'), -- 'paths' : files('paths.pyx'), -+ 'algebra_elements': files('algebra_elements.pyx'), -+ 'paths': files('paths.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/rings/convert/meson.build b/src/sage/rings/convert/meson.build -index 2e248c33814..61dba9fe0e6 100644 ---- a/src/sage/rings/convert/meson.build -+++ b/src/sage/rings/convert/meson.build -@@ -6,7 +6,7 @@ py.install_sources( - subdir: 'sage/rings/convert', - ) - --extension_data = {'mpfi' : files('mpfi.pyx')} -+extension_data = {'mpfi': files('mpfi.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/rings/finite_rings/meson.build b/src/sage/rings/finite_rings/meson.build -index 41ee9f0f0c6..8af2dd5b89a 100644 ---- a/src/sage/rings/finite_rings/meson.build -+++ b/src/sage/rings/finite_rings/meson.build -@@ -40,16 +40,16 @@ py.install_sources( - ) - - extension_data = { -- 'element_base' : files('element_base.pyx'), -- 'element_pari_ffelt' : files('element_pari_ffelt.pyx'), -- 'finite_field_base' : files('finite_field_base.pyx'), -- 'hom_finite_field' : files('hom_finite_field.pyx'), -- 'hom_prime_finite_field' : files('hom_prime_finite_field.pyx'), -- 'integer_mod' : files('integer_mod.pyx'), -- 'residue_field' : files('residue_field.pyx'), -- 'residue_field_givaro' : files('residue_field_givaro.pyx'), -- 'residue_field_ntl_gf2e' : files('residue_field_ntl_gf2e.pyx'), -- 'residue_field_pari_ffelt' : files('residue_field_pari_ffelt.pyx'), -+ 'element_base': files('element_base.pyx'), -+ 'element_pari_ffelt': files('element_pari_ffelt.pyx'), -+ 'finite_field_base': files('finite_field_base.pyx'), -+ 'hom_finite_field': files('hom_finite_field.pyx'), -+ 'hom_prime_finite_field': files('hom_prime_finite_field.pyx'), -+ 'integer_mod': files('integer_mod.pyx'), -+ 'residue_field': files('residue_field.pyx'), -+ 'residue_field_givaro': files('residue_field_givaro.pyx'), -+ 'residue_field_ntl_gf2e': files('residue_field_ntl_gf2e.pyx'), -+ 'residue_field_pari_ffelt': files('residue_field_pari_ffelt.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/rings/function_field/meson.build b/src/sage/rings/function_field/meson.build -index d99579c9c54..b8673f2b9fa 100644 ---- a/src/sage/rings/function_field/meson.build -+++ b/src/sage/rings/function_field/meson.build -@@ -38,11 +38,11 @@ py.install_sources( - ) - - extension_data = { -- 'element' : files('element.pyx'), -- 'element_polymod' : files('element_polymod.pyx'), -- 'element_rational' : files('element_rational.pyx'), -- 'hermite_form_polynomial' : files('hermite_form_polynomial.pyx'), -- 'khuri_makdisi' : files('khuri_makdisi.pyx'), -+ 'element': files('element.pyx'), -+ 'element_polymod': files('element_polymod.pyx'), -+ 'element_rational': files('element_rational.pyx'), -+ 'hermite_form_polynomial': files('hermite_form_polynomial.pyx'), -+ 'khuri_makdisi': files('khuri_makdisi.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/rings/meson.build b/src/sage/rings/meson.build -index 743c223dcc7..ec65cf584b5 100644 ---- a/src/sage/rings/meson.build -+++ b/src/sage/rings/meson.build -@@ -121,42 +121,42 @@ py.install_sources( - ) - - extension_data = { -- 'abc' : files('abc.pyx'), -- 'complex_arb' : files('complex_arb.pyx'), -- 'complex_conversion' : files('complex_conversion.pyx'), -- 'complex_interval' : files('complex_interval.pyx'), -- 'complex_mpc' : files('complex_mpc.pyx'), -- 'complex_mpfr' : files('complex_mpfr.pyx'), -- 'factorint' : files('factorint.pyx'), -- 'factorint_flint' : files('factorint_flint.pyx'), -- 'factorint_pari' : files('factorint_pari.pyx'), -- 'fast_arith' : files('fast_arith.pyx'), -- 'fraction_field_element' : files('fraction_field_element.pyx'), -- 'integer' : files('integer.pyx'), -- 'integer_ring' : files('integer_ring.pyx'), -- 'laurent_series_ring_element' : files('laurent_series_ring_element.pyx'), -- 'morphism' : files('morphism.pyx'), -- 'noncommutative_ideals' : files('noncommutative_ideals.pyx'), -- 'power_series_mpoly' : files('power_series_mpoly.pyx'), -- 'power_series_pari' : files('power_series_pari.pyx'), -- 'power_series_poly' : files('power_series_poly.pyx'), -- 'power_series_ring_element' : files('power_series_ring_element.pyx'), -- 'puiseux_series_ring_element' : files('puiseux_series_ring_element.pyx'), -- 'real_arb' : files('real_arb.pyx'), -- 'real_double' : files('real_double.pyx'), -- 'real_double_element_gsl' : files('real_double_element_gsl.pyx'), -- 'real_interval_absolute' : files('real_interval_absolute.pyx'), -- 'real_lazy' : files('real_lazy.pyx'), -- 'real_mpfi' : files('real_mpfi.pyx'), -- 'real_mpfr' : files('real_mpfr.pyx'), -- 'ring' : files('ring.pyx'), -- 'ring_extension' : files('ring_extension.pyx'), -- 'ring_extension_conversion' : files('ring_extension_conversion.pyx'), -- 'ring_extension_element' : files('ring_extension_element.pyx'), -- 'ring_extension_morphism' : files('ring_extension_morphism.pyx'), -- 'sum_of_squares' : files('sum_of_squares.pyx'), -- 'tate_algebra_element' : files('tate_algebra_element.pyx'), -- 'tate_algebra_ideal' : files('tate_algebra_ideal.pyx'), -+ 'abc': files('abc.pyx'), -+ 'complex_arb': files('complex_arb.pyx'), -+ 'complex_conversion': files('complex_conversion.pyx'), -+ 'complex_interval': files('complex_interval.pyx'), -+ 'complex_mpc': files('complex_mpc.pyx'), -+ 'complex_mpfr': files('complex_mpfr.pyx'), -+ 'factorint': files('factorint.pyx'), -+ 'factorint_flint': files('factorint_flint.pyx'), -+ 'factorint_pari': files('factorint_pari.pyx'), -+ 'fast_arith': files('fast_arith.pyx'), -+ 'fraction_field_element': files('fraction_field_element.pyx'), -+ 'integer': files('integer.pyx'), -+ 'integer_ring': files('integer_ring.pyx'), -+ 'laurent_series_ring_element': files('laurent_series_ring_element.pyx'), -+ 'morphism': files('morphism.pyx'), -+ 'noncommutative_ideals': files('noncommutative_ideals.pyx'), -+ 'power_series_mpoly': files('power_series_mpoly.pyx'), -+ 'power_series_pari': files('power_series_pari.pyx'), -+ 'power_series_poly': files('power_series_poly.pyx'), -+ 'power_series_ring_element': files('power_series_ring_element.pyx'), -+ 'puiseux_series_ring_element': files('puiseux_series_ring_element.pyx'), -+ 'real_arb': files('real_arb.pyx'), -+ 'real_double': files('real_double.pyx'), -+ 'real_double_element_gsl': files('real_double_element_gsl.pyx'), -+ 'real_interval_absolute': files('real_interval_absolute.pyx'), -+ 'real_lazy': files('real_lazy.pyx'), -+ 'real_mpfi': files('real_mpfi.pyx'), -+ 'real_mpfr': files('real_mpfr.pyx'), -+ 'ring': files('ring.pyx'), -+ 'ring_extension': files('ring_extension.pyx'), -+ 'ring_extension_conversion': files('ring_extension_conversion.pyx'), -+ 'ring_extension_element': files('ring_extension_element.pyx'), -+ 'ring_extension_morphism': files('ring_extension_morphism.pyx'), -+ 'sum_of_squares': files('sum_of_squares.pyx'), -+ 'tate_algebra_element': files('tate_algebra_element.pyx'), -+ 'tate_algebra_ideal': files('tate_algebra_ideal.pyx'), - } - - foreach name, pyx : extension_data -@@ -226,7 +226,7 @@ extension_data_cpp = { - ), - 'bernoulli_mod_p': files('bernoulli_mod_p.pyx'), - # Has to be compiled as c++ due to https://github.com/cython/cython/issues/6524 -- 'complex_double' : files('complex_double.pyx'), -+ 'complex_double': files('complex_double.pyx'), - 'fraction_field_FpT': files('fraction_field_FpT.pyx'), - 'rational': files('rational.pyx'), - } -diff --git a/src/sage/rings/number_field/meson.build b/src/sage/rings/number_field/meson.build -index f8659c09448..6a2d77e7d14 100644 ---- a/src/sage/rings/number_field/meson.build -+++ b/src/sage/rings/number_field/meson.build -@@ -37,11 +37,11 @@ py.install_sources( - ) - - extension_data = { -- 'number_field_base' : files('number_field_base.pyx'), -- 'number_field_element_base' : files('number_field_element_base.pyx'), -- 'number_field_morphisms' : files('number_field_morphisms.pyx'), -- 'totallyreal' : files('totallyreal.pyx'), -- 'totallyreal_data' : files('totallyreal_data.pyx'), -+ 'number_field_base': files('number_field_base.pyx'), -+ 'number_field_element_base': files('number_field_element_base.pyx'), -+ 'number_field_morphisms': files('number_field_morphisms.pyx'), -+ 'totallyreal': files('totallyreal.pyx'), -+ 'totallyreal_data': files('totallyreal_data.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/rings/padics/meson.build b/src/sage/rings/padics/meson.build -index b85d18ca5ed..f40436ebe60 100644 ---- a/src/sage/rings/padics/meson.build -+++ b/src/sage/rings/padics/meson.build -@@ -82,24 +82,24 @@ py.install_sources( - ) - - extension_data = { -- 'common_conversion' : files('common_conversion.pyx'), -- 'local_generic_element' : files('local_generic_element.pyx'), -- 'morphism' : files('morphism.pyx'), -- 'padic_capped_absolute_element' : files('padic_capped_absolute_element.pyx'), -- 'padic_capped_relative_element' : files('padic_capped_relative_element.pyx'), -- 'padic_fixed_mod_element' : files('padic_fixed_mod_element.pyx'), -- 'padic_floating_point_element' : files('padic_floating_point_element.pyx'), -- 'padic_generic_element' : files('padic_generic_element.pyx'), -- 'padic_relaxed_element' : files('padic_relaxed_element.pyx'), -- 'padic_relaxed_errors' : files('padic_relaxed_errors.pyx'), -- 'qadic_flint_CA' : files('qadic_flint_CA.pyx'), -- 'qadic_flint_CR' : files('qadic_flint_CR.pyx'), -- 'qadic_flint_FM' : files('qadic_flint_FM.pyx'), -- 'qadic_flint_FP' : files('qadic_flint_FP.pyx'), -- 'relative_ramified_CA' : files('relative_ramified_CA.pyx'), -- 'relative_ramified_CR' : files('relative_ramified_CR.pyx'), -- 'relative_ramified_FM' : files('relative_ramified_FM.pyx'), -- 'relative_ramified_FP' : files('relative_ramified_FP.pyx'), -+ 'common_conversion': files('common_conversion.pyx'), -+ 'local_generic_element': files('local_generic_element.pyx'), -+ 'morphism': files('morphism.pyx'), -+ 'padic_capped_absolute_element': files('padic_capped_absolute_element.pyx'), -+ 'padic_capped_relative_element': files('padic_capped_relative_element.pyx'), -+ 'padic_fixed_mod_element': files('padic_fixed_mod_element.pyx'), -+ 'padic_floating_point_element': files('padic_floating_point_element.pyx'), -+ 'padic_generic_element': files('padic_generic_element.pyx'), -+ 'padic_relaxed_element': files('padic_relaxed_element.pyx'), -+ 'padic_relaxed_errors': files('padic_relaxed_errors.pyx'), -+ 'qadic_flint_CA': files('qadic_flint_CA.pyx'), -+ 'qadic_flint_CR': files('qadic_flint_CR.pyx'), -+ 'qadic_flint_FM': files('qadic_flint_FM.pyx'), -+ 'qadic_flint_FP': files('qadic_flint_FP.pyx'), -+ 'relative_ramified_CA': files('relative_ramified_CA.pyx'), -+ 'relative_ramified_CR': files('relative_ramified_CR.pyx'), -+ 'relative_ramified_FM': files('relative_ramified_FM.pyx'), -+ 'relative_ramified_FP': files('relative_ramified_FP.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/rings/polynomial/meson.build b/src/sage/rings/polynomial/meson.build -index 64df9a6b861..5db1364f8f3 100644 ---- a/src/sage/rings/polynomial/meson.build -+++ b/src/sage/rings/polynomial/meson.build -@@ -102,28 +102,28 @@ py.install_sources( - ) - - extension_data = { -- 'commutative_polynomial' : files('commutative_polynomial.pyx'), -- 'cyclotomic' : files('cyclotomic.pyx'), -- 'evaluation_flint' : files('evaluation_flint.pyx'), -- 'hilbert' : files('hilbert.pyx'), -- 'laurent_polynomial' : files('laurent_polynomial.pyx'), -- 'laurent_polynomial_mpair' : files('laurent_polynomial_mpair.pyx'), -- 'multi_polynomial' : files('multi_polynomial.pyx'), -- 'multi_polynomial_ring_base' : files('multi_polynomial_ring_base.pyx'), -- 'ore_polynomial_element' : files('ore_polynomial_element.pyx'), -- 'polydict' : files('polydict.pyx'), -- 'polynomial_compiled' : files('polynomial_compiled.pyx'), -- 'polynomial_complex_arb' : files('polynomial_complex_arb.pyx'), -- 'polynomial_element' : files('polynomial_element.pyx'), -- 'polynomial_number_field' : files('polynomial_number_field.pyx'), -- 'polynomial_real_mpfr_dense' : files('polynomial_real_mpfr_dense.pyx'), -- 'polynomial_ring_homomorphism' : files('polynomial_ring_homomorphism.pyx'), -- 'real_roots' : files('real_roots.pyx'), -- 'refine_root' : files('refine_root.pyx'), -- 'skew_polynomial_element' : files('skew_polynomial_element.pyx'), -- 'skew_polynomial_finite_field' : files('skew_polynomial_finite_field.pyx'), -- 'skew_polynomial_finite_order' : files('skew_polynomial_finite_order.pyx'), -- 'symmetric_reduction' : files('symmetric_reduction.pyx'), -+ 'commutative_polynomial': files('commutative_polynomial.pyx'), -+ 'cyclotomic': files('cyclotomic.pyx'), -+ 'evaluation_flint': files('evaluation_flint.pyx'), -+ 'hilbert': files('hilbert.pyx'), -+ 'laurent_polynomial': files('laurent_polynomial.pyx'), -+ 'laurent_polynomial_mpair': files('laurent_polynomial_mpair.pyx'), -+ 'multi_polynomial': files('multi_polynomial.pyx'), -+ 'multi_polynomial_ring_base': files('multi_polynomial_ring_base.pyx'), -+ 'ore_polynomial_element': files('ore_polynomial_element.pyx'), -+ 'polydict': files('polydict.pyx'), -+ 'polynomial_compiled': files('polynomial_compiled.pyx'), -+ 'polynomial_complex_arb': files('polynomial_complex_arb.pyx'), -+ 'polynomial_element': files('polynomial_element.pyx'), -+ 'polynomial_number_field': files('polynomial_number_field.pyx'), -+ 'polynomial_real_mpfr_dense': files('polynomial_real_mpfr_dense.pyx'), -+ 'polynomial_ring_homomorphism': files('polynomial_ring_homomorphism.pyx'), -+ 'real_roots': files('real_roots.pyx'), -+ 'refine_root': files('refine_root.pyx'), -+ 'skew_polynomial_element': files('skew_polynomial_element.pyx'), -+ 'skew_polynomial_finite_field': files('skew_polynomial_finite_field.pyx'), -+ 'skew_polynomial_finite_order': files('skew_polynomial_finite_order.pyx'), -+ 'symmetric_reduction': files('symmetric_reduction.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/rings/polynomial/weil/meson.build b/src/sage/rings/polynomial/weil/meson.build -index 86a37c42c2f..4f3e0073121 100644 ---- a/src/sage/rings/polynomial/weil/meson.build -+++ b/src/sage/rings/polynomial/weil/meson.build -@@ -6,7 +6,7 @@ py.install_sources( - subdir: 'sage/rings/polynomial/weil', - ) - --extension_data = {'weil_polynomials' : files('weil_polynomials.pyx')} -+extension_data = {'weil_polynomials': files('weil_polynomials.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/rings/semirings/meson.build b/src/sage/rings/semirings/meson.build -index b92ea837850..ae143c6ef83 100644 ---- a/src/sage/rings/semirings/meson.build -+++ b/src/sage/rings/semirings/meson.build -@@ -9,7 +9,7 @@ py.install_sources( - subdir: 'sage/rings/semirings', - ) - --extension_data = {'tropical_semiring' : files('tropical_semiring.pyx')} -+extension_data = {'tropical_semiring': files('tropical_semiring.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/sat/solvers/meson.build b/src/sage/sat/solvers/meson.build -index ef9d98ea04c..ac37d2c3ced 100644 ---- a/src/sage/sat/solvers/meson.build -+++ b/src/sage/sat/solvers/meson.build -@@ -9,7 +9,7 @@ py.install_sources( - subdir: 'sage/sat/solvers', - ) - --extension_data = {'satsolver' : files('satsolver.pyx')} -+extension_data = {'satsolver': files('satsolver.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/schemes/elliptic_curves/meson.build b/src/sage/schemes/elliptic_curves/meson.build -index 155f8e8a2d9..fd1488b36be 100644 ---- a/src/sage/schemes/elliptic_curves/meson.build -+++ b/src/sage/schemes/elliptic_curves/meson.build -@@ -59,9 +59,9 @@ py.install_sources( - ) - - extension_data = { -- 'descent_two_isogeny' : files('descent_two_isogeny.pyx'), -- 'mod_sym_num' : files('mod_sym_num.pyx'), -- 'period_lattice_region' : files('period_lattice_region.pyx'), -+ 'descent_two_isogeny': files('descent_two_isogeny.pyx'), -+ 'mod_sym_num': files('mod_sym_num.pyx'), -+ 'period_lattice_region': files('period_lattice_region.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/schemes/toric/meson.build b/src/sage/schemes/toric/meson.build -index b534a186130..4a78d14e568 100644 ---- a/src/sage/schemes/toric/meson.build -+++ b/src/sage/schemes/toric/meson.build -@@ -18,7 +18,7 @@ py.install_sources( - subdir: 'sage/schemes/toric', - ) - --extension_data = {'divisor_class' : files('divisor_class.pyx')} -+extension_data = {'divisor_class': files('divisor_class.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/src/sage/sets/meson.build b/src/sage/sets/meson.build -index 1ab6ba327dd..4f1d4a6638d 100644 ---- a/src/sage/sets/meson.build -+++ b/src/sage/sets/meson.build -@@ -29,11 +29,11 @@ py.install_sources( - ) - - extension_data = { -- 'disjoint_set' : files('disjoint_set.pyx'), -- 'family' : files('family.pyx'), -- 'finite_set_map_cy' : files('finite_set_map_cy.pyx'), -- 'pythonclass' : files('pythonclass.pyx'), -- 'recursively_enumerated_set' : files('recursively_enumerated_set.pyx'), -+ 'disjoint_set': files('disjoint_set.pyx'), -+ 'family': files('family.pyx'), -+ 'finite_set_map_cy': files('finite_set_map_cy.pyx'), -+ 'pythonclass': files('pythonclass.pyx'), -+ 'recursively_enumerated_set': files('recursively_enumerated_set.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/stats/distributions/meson.build b/src/sage/stats/distributions/meson.build -index df2b2d246b9..cde85eacda9 100644 ---- a/src/sage/stats/distributions/meson.build -+++ b/src/sage/stats/distributions/meson.build -@@ -11,7 +11,7 @@ py.install_sources( - ) - - extension_data = { -- 'discrete_gaussian_integer' : files( -+ 'discrete_gaussian_integer': files( - 'dgs_bern.c', - 'dgs_gauss_dp.c', - 'dgs_gauss_mp.c', -diff --git a/src/sage/stats/hmm/meson.build b/src/sage/stats/hmm/meson.build -index d45861127e9..c1acc958caf 100644 ---- a/src/sage/stats/hmm/meson.build -+++ b/src/sage/stats/hmm/meson.build -@@ -12,10 +12,10 @@ py.install_sources( - ) - - extension_data = { -- 'chmm' : files('chmm.pyx'), -- 'distributions' : files('distributions.pyx'), -- 'hmm' : files('hmm.pyx'), -- 'util' : files('util.pyx'), -+ 'chmm': files('chmm.pyx'), -+ 'distributions': files('distributions.pyx'), -+ 'hmm': files('hmm.pyx'), -+ 'util': files('util.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/stats/meson.build b/src/sage/stats/meson.build -index 35e8edb05a8..6a75bccdee6 100644 ---- a/src/sage/stats/meson.build -+++ b/src/sage/stats/meson.build -@@ -11,8 +11,8 @@ py.install_sources( - ) - - extension_data = { -- 'intlist' : files('intlist.pyx'), -- 'time_series' : files('time_series.pyx'), -+ 'intlist': files('intlist.pyx'), -+ 'time_series': files('time_series.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/structure/meson.build b/src/sage/structure/meson.build -index 74de406646c..a3a6970d743 100644 ---- a/src/sage/structure/meson.build -+++ b/src/sage/structure/meson.build -@@ -57,25 +57,25 @@ py.install_sources( - ) - - extension_data = { -- 'category_object' : files('category_object.pyx'), -- 'coerce' : files('coerce.pyx'), -- 'coerce_actions' : files('coerce_actions.pyx'), -- 'coerce_dict' : files('coerce_dict.pyx'), -- 'coerce_maps' : files('coerce_maps.pyx'), -- 'debug_options' : files('debug_options.pyx'), -- 'element' : files('element.pyx'), -- 'element_wrapper' : files('element_wrapper.pyx'), -- 'factory' : files('factory.pyx'), -- 'list_clone' : files('list_clone.pyx'), -- 'list_clone_demo' : files('list_clone_demo.pyx'), -- 'list_clone_timings_cy' : files('list_clone_timings_cy.pyx'), -- 'mutability' : files('mutability.pyx'), -- 'parent' : files('parent.pyx'), -- 'parent_base' : files('parent_base.pyx'), -- 'parent_gens' : files('parent_gens.pyx'), -- 'parent_old' : files('parent_old.pyx'), -- 'richcmp' : files('richcmp.pyx'), -- 'sage_object' : files('sage_object.pyx'), -+ 'category_object': files('category_object.pyx'), -+ 'coerce': files('coerce.pyx'), -+ 'coerce_actions': files('coerce_actions.pyx'), -+ 'coerce_dict': files('coerce_dict.pyx'), -+ 'coerce_maps': files('coerce_maps.pyx'), -+ 'debug_options': files('debug_options.pyx'), -+ 'element': files('element.pyx'), -+ 'element_wrapper': files('element_wrapper.pyx'), -+ 'factory': files('factory.pyx'), -+ 'list_clone': files('list_clone.pyx'), -+ 'list_clone_demo': files('list_clone_demo.pyx'), -+ 'list_clone_timings_cy': files('list_clone_timings_cy.pyx'), -+ 'mutability': files('mutability.pyx'), -+ 'parent': files('parent.pyx'), -+ 'parent_base': files('parent_base.pyx'), -+ 'parent_gens': files('parent_gens.pyx'), -+ 'parent_old': files('parent_old.pyx'), -+ 'richcmp': files('richcmp.pyx'), -+ 'sage_object': files('sage_object.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/symbolic/meson.build b/src/sage/symbolic/meson.build -index bb8e3c1433e..44e605742b0 100644 ---- a/src/sage/symbolic/meson.build -+++ b/src/sage/symbolic/meson.build -@@ -33,8 +33,8 @@ py.install_sources( - ) - - extension_data = { -- 'function' : files('function.pyx'), -- 'ring' : files('ring.pyx'), -+ 'function': files('function.pyx'), -+ 'ring': files('ring.pyx'), - } - - foreach name, pyx : extension_data -diff --git a/src/sage/tests/meson.build b/src/sage/tests/meson.build -index a76a068cf60..e6d5293ae74 100644 ---- a/src/sage/tests/meson.build -+++ b/src/sage/tests/meson.build -@@ -24,7 +24,7 @@ py.install_sources( - subdir: 'sage/tests', - ) - --extension_data = {'cython' : files('cython.pyx')} -+extension_data = {'cython': files('cython.pyx')} - - foreach name, pyx : extension_data - py.extension_module( -diff --git a/virtual-packages.yml b/virtual-packages.yml -new file mode 100644 -index 00000000000..30b838c0188 diff --git a/srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch b/srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch index cd7e96ee47c0ae..1fde72cc1d199b 100644 --- a/srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch +++ b/srcpkgs/sagemath/patches/40679-Update_to_maxima_5.49.patch @@ -602,8 +602,8 @@ index 8fada2b4e9b..02cfc43f282 100644 sage: y = var('y') diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py index b5531b112b4..15f74fe5779 100644 ---- a/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py -+++ b/src/sage/tests/books/computational-mathematics-with-sagemath/calculus_doctest.py +--- a/src/sage/tests/books/computational_mathematics_with_sagemath/calculus_doctest.py ++++ b/src/sage/tests/books/computational_mathematics_with_sagemath/calculus_doctest.py @@ -256,7 +256,7 @@ Sage example in ./calculus.tex, line 1086:: diff --git a/srcpkgs/sagemath/patches/40816-Meson:_Build_docs_for_Maxima_as_well.patch b/srcpkgs/sagemath/patches/40816-Meson:_Build_docs_for_Maxima_as_well.patch deleted file mode 100644 index 8c3acbf3fee2da..00000000000000 --- a/srcpkgs/sagemath/patches/40816-Meson:_Build_docs_for_Maxima_as_well.patch +++ /dev/null @@ -1,113 +0,0 @@ -diff --git a/src/sage/config.py.in b/src/sage/config.py.in -index de5ad8b2169..f75e951f3b8 100644 ---- a/src/sage/config.py.in -+++ b/src/sage/config.py.in -@@ -21,7 +21,7 @@ MAXIMA = "@SAGE_MAXIMA@".replace("${prefix}", SAGE_LOCAL) - # Set this to the empty string if your ECL can load maxima without - # further prodding. - MAXIMA_FAS = "@SAGE_MAXIMA_FAS@".replace("${prefix}", SAGE_LOCAL) --MAXIMA_SHARE = "@SAGE_MAXIMA_SHARE@".replace("${prefix}", SAGE_LOCAL) -+MAXIMA_PREFIX = "@SAGE_MAXIMA_PREFIX@".replace("${prefix}", SAGE_LOCAL) - - # Delete this line if your ECL can load Kenzo without further prodding. - KENZO_FAS = "@SAGE_KENZO_FAS@".replace("${prefix}", SAGE_LOCAL) -diff --git a/src/sage/env.py b/src/sage/env.py -index c7c46bf4ec3..71e87c3f0f6 100644 ---- a/src/sage/env.py -+++ b/src/sage/env.py -@@ -204,7 +204,7 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st - PPLPY_DOCS = var("PPLPY_DOCS", join(SAGE_SHARE, "doc", "pplpy")) - MAXIMA = var("MAXIMA", "maxima") - MAXIMA_FAS = var("MAXIMA_FAS") --MAXIMA_SHARE = var("MAXIMA_SHARE") -+MAXIMA_PREFIX = var("MAXIMA_PREFIX") - KENZO_FAS = var("KENZO_FAS") - SAGE_NAUTY_BINS_PREFIX = var("SAGE_NAUTY_BINS_PREFIX", "") - SAGE_ECMBIN = var("SAGE_ECMBIN", "ecm") -diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py -index 154a2cc34e0..9df024abf39 100644 ---- a/src/sage/interfaces/maxima.py -+++ b/src/sage/interfaces/maxima.py -@@ -515,7 +515,7 @@ - - import pexpect - --from sage.env import MAXIMA -+from sage.env import MAXIMA, MAXIMA_PREFIX - from sage.interfaces.expect import Expect, ExpectElement, gc_disabled - from sage.interfaces.maxima_abstract import ( - MaximaAbstract, -@@ -587,11 +587,16 @@ def __init__(self, script_subdirectory=None, logfile=None, server=None, - # See trac # 6818. - init_code.append('nolabels : true') - -+ env = {} -+ if MAXIMA_PREFIX: -+ env['MAXIMA_PREFIX'] = MAXIMA_PREFIX -+ - MaximaAbstract.__init__(self, "maxima") - Expect.__init__(self, - name='maxima', - prompt=r'\(\%i[0-9]+\) ', - command='{0} -p {1}'.format(MAXIMA, shlex.quote(STARTUP)), -+ env=env, - script_subdirectory=script_subdirectory, - restart_on_ctrlc=False, - verbose_start=False, -diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py -index 637ef29a6f2..3d27bd834b5 100644 ---- a/src/sage/interfaces/maxima_lib.py -+++ b/src/sage/interfaces/maxima_lib.py -@@ -112,11 +112,12 @@ - # - # https://www.gnu.org/licenses/ - # **************************************************************************** -+import os - - import sage.rings.real_double - import sage.symbolic.expression - import sage.symbolic.integration.integral --from sage.env import MAXIMA_FAS, MAXIMA_SHARE -+from sage.env import MAXIMA_FAS, MAXIMA_PREFIX - from sage.interfaces.maxima_abstract import ( - MaximaAbstract, - MaximaAbstractElement, -@@ -141,6 +142,9 @@ - ecl_eval("(in-package :maxima)") - ecl_eval("(set-locale-subdir)") - -+if MAXIMA_PREFIX: -+ os.environ["MAXIMA_PREFIX"] = MAXIMA_PREFIX -+ - # This workaround has to happen before any call to (set-pathnames). - # To be safe please do not call anything other than - # (set-locale-subdir) before this block. -@@ -207,10 +211,10 @@ - - # Add search paths - # Keep these in sync with the default Maxima search paths defined in subprojects/maxima-/src/share-subdirs_autogenerated.lisp --if MAXIMA_SHARE: -+if MAXIMA_PREFIX: - import_packages = "{affine,algebra,algebra/charsets,algebra/solver,amatrix,bernstein,calculus,cobyla,cobyla/ex,cobyla/lisp,colnew,colnew/ex1,colnew/ex2,colnew/ex3,colnew/ex4,colnew/lisp,combinatorics,contrib,contrib/Eulix,contrib/Grobner,contrib/Zeilberger,contrib/alt-display,contrib/altsimp,contrib/binsplit,contrib/bitwise,contrib/boolsimp,contrib/coma,contrib/diffequations,contrib/diffequations/tests,contrib/elliptic_curves,contrib/elliptic_curves/figures,contrib/format,contrib/fresnel,contrib/gentran,contrib/gentran/man,contrib/gentran/test,contrib/gf,contrib/integration,contrib/levin,contrib/lurkmathml,contrib/maxima-odesolve,contrib/maximaMathML,contrib/mcclim,contrib/noninteractive,contrib/odes,contrib/operatingsystem,contrib/prim,contrib/rand,contrib/rkf45,contrib/sarag,contrib/smath,contrib/state,contrib/symplectic_ode,contrib/trigtools,contrib/unicodedata,contrib/unit,contrib/vector3d,descriptive,diff_form,diff_form/tests,diffequations,distrib,draw,dynamics,ezunits,fftpack5,fftpack5/lisp,finance,fourier_elim,fractals,graphs,hompack,hompack/lisp,hypergeometric,integequations,integer_sequence,integration,lapack,lapack/blas,lapack/lapack,lbfgs,linearalgebra,logic,lsquares,macro,matrix,minpack,minpack/lisp,misc,mnewton,multiadditive,nelder_mead,numeric,numericalio,odepack,odepack/src,orthopoly,pdiff,physics,pslq,pytranslate,quantum,simplex,simplex/Tests,simplification,solve_rat_ineq,solve_rec,sound,stats,stringproc,sym,tensor,tensor/tracefree-code,test_batch_encodings,to_poly_solve,translators,translators/m2mj,trigonometry,utils,vector,z_transform}" -- ecl_eval(f'#$file_search_maxima: append(file_search_maxima, ["{MAXIMA_SHARE}/###.{{mac,mc,wxm}}", "{MAXIMA_SHARE}/{import_packages}/###.{{mac,mc,wxm}}"])$') -- ecl_eval(f'#$file_search_lisp: append(file_search_lisp, ["{MAXIMA_SHARE}/###.{{fas,lisp,lsp}}", "{MAXIMA_SHARE}/{import_packages}/###.{{fas,lisp,lsp}}"])$') -+ ecl_eval(f'#$file_search_maxima: append(file_search_maxima, ["{MAXIMA_PREFIX}/###.{{mac,mc,wxm}}", "{MAXIMA_PREFIX}/{import_packages}/###.{{mac,mc,wxm}}"])$') -+ ecl_eval(f'#$file_search_lisp: append(file_search_lisp, ["{MAXIMA_PREFIX}/###.{{fas,lisp,lsp}}", "{MAXIMA_PREFIX}/../src/###.{{fas,lisp,lsp}}", "{MAXIMA_PREFIX}/{import_packages}/###.{{fas,lisp,lsp}}"])$') - - # Default options set in Maxima - # display2d -- no ascii art output -diff --git a/subprojects/packagefiles/maxima/build/doc/info/meson.build b/subprojects/packagefiles/maxima/build/doc/info/meson.build -new file mode 100644 -index 00000000000..e8c69f73526 -diff --git a/subprojects/packagefiles/maxima/build/doc/meson.build b/subprojects/packagefiles/maxima/build/doc/meson.build -new file mode 100644 -index 00000000000..eba36e4bdc3 -diff --git a/subprojects/packagefiles/maxima/build/meson.build b/subprojects/packagefiles/maxima/build/meson.build -new file mode 100644 -index 00000000000..4112780103d -diff --git a/subprojects/packagefiles/maxima/infodir.patch b/subprojects/packagefiles/maxima/infodir.patch -new file mode 100644 -index 00000000000..a4c037bb848 -diff --git a/subprojects/packagefiles/maxima/maxima_prefix_bin.patch b/subprojects/packagefiles/maxima/maxima_prefix_bin.patch -new file mode 100644 -index 00000000000..0fced388ea9 diff --git a/srcpkgs/sagemath/patches/41342-Fix_a_test_failure_with_numpy_2.4.patch b/srcpkgs/sagemath/patches/41342-Fix_a_test_failure_with_numpy_2.4.patch deleted file mode 100644 index 7b8241e9ecc130..00000000000000 --- a/srcpkgs/sagemath/patches/41342-Fix_a_test_failure_with_numpy_2.4.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/sage/calculus/desolvers.py b/src/sage/calculus/desolvers.py -index 7f6ba7967e1..89a56cb54e1 100644 ---- a/src/sage/calculus/desolvers.py -+++ b/src/sage/calculus/desolvers.py -@@ -1621,7 +1621,7 @@ def desolve_odeint_inner(ivar): - assert len(des) == 1 - dvar = dvars[0] - de = des[0] -- func = fast_float(de, dvar, ivar) -+ func = lambda y, t: fast_float(de, dvar, ivar)(y.item(), t) - if not compute_jac: - Dfun = None - else: diff --git a/srcpkgs/sagemath/patches/41346-Fix_execution_count_for_newer_ipython_version.patch b/srcpkgs/sagemath/patches/41346-Fix_execution_count_for_newer_ipython_version.patch deleted file mode 100644 index 8f95fa27e3f9ab..00000000000000 --- a/srcpkgs/sagemath/patches/41346-Fix_execution_count_for_newer_ipython_version.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/sage/repl/interpreter.py b/src/sage/repl/interpreter.py -index dca9c9a1146..d18ae9e2436 100644 ---- a/src/sage/repl/interpreter.py -+++ b/src/sage/repl/interpreter.py -@@ -679,7 +679,7 @@ def interface_shell_embed(interface): - sage: shell = interface_shell_embed(gap) # needs sage.libs.gap - sage: shell.run_cell('List( [1..10], IsPrime )') # needs sage.libs.gap - [ false, true, true, false, true, false, true, false, false, false ] -- -+ - """ - cfg = sage_ipython_config.copy() - ipshell = InteractiveShellEmbed(config=cfg, diff --git a/srcpkgs/sagemath/patches/41394-Fix_doctest_failure_with_python_3.14.patch b/srcpkgs/sagemath/patches/41394-Fix_doctest_failure_with_python_3.14.patch deleted file mode 100644 index f728fba9a1636f..00000000000000 --- a/srcpkgs/sagemath/patches/41394-Fix_doctest_failure_with_python_3.14.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/src/sage/doctest/test.py b/src/sage/doctest/test.py -index 8e7ecac8bbe..d68cc67c153 100644 ---- a/src/sage/doctest/test.py -+++ b/src/sage/doctest/test.py -@@ -257,8 +257,7 @@ - sage: subprocess.call(["python3", "-m", "sage.doctest", "--warn-long", "0", # long time - ....: "--random-seed=0", "--optional=sage", "interrupt.rst"], **kwds) - Running doctests... -- Doctesting 1 file. -- Killing test interrupt.rst -+ Doctesting 1 file... - ---------------------------------------------------------------------- - Doctests interrupted: 0/1 files tested - ---------------------------------------------------------------------- diff --git a/srcpkgs/sagemath/patches/41395-Fix_test_failures_with_pyparsing_3.3.patch b/srcpkgs/sagemath/patches/41395-Fix_test_failures_with_pyparsing_3.3.patch deleted file mode 100644 index 6bd2ae34b5cba4..00000000000000 --- a/srcpkgs/sagemath/patches/41395-Fix_test_failures_with_pyparsing_3.3.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/src/sage/topology/simplicial_set_examples.py b/src/sage/topology/simplicial_set_examples.py -index be7a4084be2..cd69adb9c5a 100644 ---- a/src/sage/topology/simplicial_set_examples.py -+++ b/src/sage/topology/simplicial_set_examples.py -@@ -655,7 +655,7 @@ def simplicial_data_from_kenzo_output(filename) -> dict: - sage: S4.homology(reduced=False) # needs pyparsing - {0: Z, 1: 0, 2: 0, 3: 0, 4: Z} - """ -- from pyparsing import OneOrMore, nestedExpr -+ from pyparsing import OneOrMore, nested_expr - - with open(filename) as f: - data = f.read() -@@ -675,7 +675,7 @@ def simplicial_data_from_kenzo_output(filename) -> dict: - end = new_dim_idx - if dim == 0: - simplex_string = data[data.find('Vertices :') + len('Vertices :'):end] -- vertices = OneOrMore(nestedExpr()).parseString(simplex_string).asList()[0] -+ vertices = OneOrMore(nested_expr()).parse_string(simplex_string).asList()[0] - for v in vertices: - vertex = AbstractSimplex(0, name=v) - simplex_data[vertex] = None diff --git a/srcpkgs/sagemath/patches/41433-Fix_test_failures_with_scipy_1.17.patch b/srcpkgs/sagemath/patches/41433-Fix_test_failures_with_scipy_1.17.patch deleted file mode 100644 index 69091a6c3077e9..00000000000000 --- a/srcpkgs/sagemath/patches/41433-Fix_test_failures_with_scipy_1.17.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx -index 7ff5a3a95bc..bdbb6805585 100644 ---- a/src/sage/matrix/matrix2.pyx -+++ b/src/sage/matrix/matrix2.pyx -@@ -367,7 +367,7 @@ cdef class Matrix(Matrix1): - sage: A.solve_left(b) # needs scipy - Traceback (most recent call last): - ... -- LinAlgError: Matrix is singular. -+ LinAlgError: ...singular. - - The vector of constants needs the correct degree:: - -@@ -762,7 +762,7 @@ cdef class Matrix(Matrix1): - sage: A.solve_right(b) - Traceback (most recent call last): - ... -- LinAlgError: Matrix is singular. -+ LinAlgError: ...singular. - - The vector of constants needs the correct degree. :: - diff --git a/srcpkgs/sagemath/patches/41469-Prevent_leaking_file_descriptors.patch b/srcpkgs/sagemath/patches/41469-Prevent_leaking_file_descriptors.patch deleted file mode 100644 index f5d0f608905711..00000000000000 --- a/srcpkgs/sagemath/patches/41469-Prevent_leaking_file_descriptors.patch +++ /dev/null @@ -1,98 +0,0 @@ -diff --git a/src/sage/databases/sql_db.py b/src/sage/databases/sql_db.py -index d86643bea21..f3548810be9 100644 ---- a/src/sage/databases/sql_db.py -+++ b/src/sage/databases/sql_db.py -@@ -1109,6 +1109,12 @@ def __init__(self, filename=None, read_only=None, skeleton=None): - raise RuntimeError('Cannot update skeleton of a read only ' - + 'database.') - -+ def __enter__(self): -+ return self -+ -+ def __exit__(self, exc_type, exc, tb): -+ self.__connection__.close() -+ - def __repr__(self): - """ - Override the print output to display useful info regarding the -diff --git a/src/sage/schemes/elliptic_curves/constructor.py b/src/sage/schemes/elliptic_curves/constructor.py -index fee15d24802..fde3a98b36f 100644 ---- a/src/sage/schemes/elliptic_curves/constructor.py -+++ b/src/sage/schemes/elliptic_curves/constructor.py -@@ -437,7 +437,8 @@ def create_key_and_extra_args(self, x=None, y=None, j=None, minimal_twist=True, - if isinstance(x, str): - # Interpret x as a Cremona or LMFDB label. - from sage.databases.cremona import CremonaDatabase -- x, data = CremonaDatabase().coefficients_and_data(x) -+ with CremonaDatabase() as D: -+ x, data = D.coefficients_and_data(x) - # data is only valid for elliptic curves over QQ. - if R not in (None, QQ): - data = {} -@@ -753,10 +754,11 @@ def coefficients_from_j(j, minimal_twist=True): - Elist = [E for E in Elist if E.conductor() == min_cond] - if len(Elist) > 1: - from sage.databases.cremona import CremonaDatabase, parse_cremona_label -- if min_cond <= CremonaDatabase().largest_conductor(): -- sorter = lambda E: parse_cremona_label(E.label(), numerical_class_code=True) -- else: -- sorter = lambda E: E.ainvs() -+ with CremonaDatabase() as D: -+ if min_cond <= D.largest_conductor(): -+ sorter = lambda E: parse_cremona_label(E.label(), numerical_class_code=True) -+ else: -+ sorter = lambda E: E.ainvs() - Elist.sort(key=sorter) - return Sequence(Elist[0].ainvs()) - -diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py -index d7dba7acbfb..2d578e116a2 100644 ---- a/src/sage/schemes/elliptic_curves/ell_rational_field.py -+++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py -@@ -686,12 +686,13 @@ def database_attributes(self): - LookupError: Cremona database does not contain entry for Elliptic Curve - defined by y^2 + 8*x*y + 21*y = x^3 + 13*x^2 + 34*x + 55 over Rational Field - """ -- from sage.databases.cremona import CremonaDatabase - ainvs = self.minimal_model().ainvs() -- try: -- return CremonaDatabase().data_from_coefficients(ainvs) -- except RuntimeError: -- raise LookupError("Cremona database does not contain entry for " + repr(self)) -+ with sage.databases.cremona.CremonaDatabase() as D: -+ try: -+ attrs = D.data_from_coefficients(ainvs) -+ return attrs -+ except RuntimeError: -+ raise LookupError("Cremona database does not contain entry for " + repr(self)) - - def database_curve(self): - r""" -@@ -718,10 +719,10 @@ def database_curve(self): - return self.__database_curve - except AttributeError: - verbose_verbose("Looking up %s in the database." % self) -- D = sage.databases.cremona.CremonaDatabase() - ainvs = list(self.minimal_model().ainvs()) - try: -- self.__database_curve = D.elliptic_curve_from_ainvs(ainvs) -+ with sage.databases.cremona.CremonaDatabase() as D: -+ self.__database_curve = D.elliptic_curve_from_ainvs(ainvs) - except RuntimeError: - raise RuntimeError("Elliptic curve %s not in the database." % self) - return self.__database_curve -diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py -index 28043f56b95..c038caa8320 100644 ---- a/src/sage/schemes/elliptic_curves/isogeny_class.py -+++ b/src/sage/schemes/elliptic_curves/isogeny_class.py -@@ -1087,8 +1087,8 @@ def _compute(self): - label = self.E.cremona_label(space=False) - except RuntimeError: - raise RuntimeError("unable to find %s in the database" % self.E) -- db = sage.databases.cremona.CremonaDatabase() -- curves = db.isogeny_class(label) -+ with sage.databases.cremona.CremonaDatabase() as db: -+ curves = db.isogeny_class(label) - if not curves: - raise RuntimeError("unable to find %s in the database" % self.E) - # All curves will have the same conductor and isogeny class, diff --git a/srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch b/srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch deleted file mode 100644 index 5a8ff7fc50626c..00000000000000 --- a/srcpkgs/sagemath/patches/41728-Patch_for_mpmath_1.4.patch +++ /dev/null @@ -1,5691 +0,0 @@ -diff --git a/src/sage/env.py b/src/sage/env.py -index a1092291650..f6c198a8617 100644 ---- a/src/sage/env.py -+++ b/src/sage/env.py -@@ -228,8 +228,9 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st - OPENMP_CFLAGS = var("OPENMP_CFLAGS", "") - OPENMP_CXXFLAGS = var("OPENMP_CXXFLAGS", "") - --# Make sure mpmath uses Sage types --os.environ['MPMATH_SAGE'] = '1' -+# Make sure that mpmath < 1.4 does not try to use Sage types -+os.environ.pop('MPMATH_SAGE', None) -+os.environ['MPMATH_NOSAGE'] = '1' - - # misc - SAGE_BANNER = var("SAGE_BANNER", "") -diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py -index 78eb4992aa6..59966f40bd0 100644 ---- a/src/sage/functions/error.py -+++ b/src/sage/functions/error.py -@@ -256,8 +256,8 @@ def _evalf_(self, x, parent=None, algorithm=None): - 0.995322265018953 - sage: erf(2).n(200) # needs sage.symbolic - 0.99532226501895273416206925636725292861089179704006007673835 -- sage: erf(pi - 1/2*I).n(100) # needs sage.symbolic -- 1.0000111669099367825726058952 + 1.6332655417638522934072124547e-6*I -+ sage: erf(pi - 1/2*I).n(100) # needs sage.symbolic # abs tol 1e-28 -+ 1.0000111669099367825726058952 + 1.6332655417638522934072124548e-6*I - - TESTS: - -diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py -index e074c430808..09d2bbda71b 100644 ---- a/src/sage/functions/exp_integral.py -+++ b/src/sage/functions/exp_integral.py -@@ -993,7 +993,7 @@ def _evalf_(self, z, parent=None, algorithm=None): - sage: N(cos_integral(10^-10), digits=30) # needs sage.symbolic - -22.4486352650389239795759024568 - sage: cos_integral(ComplexField(100)(I)) # needs sage.symbolic -- 0.83786694098020824089467857943 + 1.5707963267948966192313216916*I -+ 0.83786694098020824089467857944 + 1.5707963267948966192313216916*I - """ - return _mpmath_utils_call(_mpmath_ci, z, parent=parent) - -diff --git a/src/sage/libs/mpmath/all.py b/src/sage/libs/mpmath/all.py -index ea35faeb721..14a4be971e6 100644 ---- a/src/sage/libs/mpmath/all.py -+++ b/src/sage/libs/mpmath/all.py -@@ -22,5 +22,5 @@ - - - def eval_constant(name, ring): -- prec = ring.precision() + 20 -+ prec = int(ring.precision() + 20) - return ring(_constants_funcs[name](prec)) >> prec -diff --git a/src/sage/libs/mpmath/ext_impl.pxd b/src/sage/libs/mpmath/ext_impl.pxd -deleted file mode 100644 -index 586d10d17f2..00000000000 ---- a/src/sage/libs/mpmath/ext_impl.pxd -+++ /dev/null -@@ -1,66 +0,0 @@ --from sage.libs.gmp.all cimport mpz_t -- --ctypedef struct MPopts: -- long prec -- int rounding -- --cdef mpz_set_integer(mpz_t v, x) --cdef mpzi(mpz_t n) --cdef mpzl(mpz_t n) --cdef str rndmode_to_python(int rnd) --cdef rndmode_from_python(str rnd) -- --ctypedef struct MPF: -- mpz_t man -- mpz_t exp -- int special -- --cdef void MPF_init(MPF *x) noexcept --cdef void MPF_clear(MPF *x) noexcept --cdef void MPF_set(MPF *dest, MPF *src) noexcept --cdef void MPF_set_zero(MPF *x) noexcept --cdef void MPF_set_one(MPF *x) noexcept --cdef void MPF_set_nan(MPF *x) noexcept --cdef void MPF_set_inf(MPF *x) noexcept --cdef void MPF_set_ninf(MPF *x) noexcept --cdef MPF_set_si(MPF *x, long n) --cdef MPF_set_int(MPF *x, n) --cdef MPF_set_man_exp(MPF *x, man, exp) --cdef MPF_set_tuple(MPF *x, tuple value) --cdef MPF_to_tuple(MPF *x) --cdef MPF_set_double(MPF *r, double x) --cdef double MPF_to_double(MPF *x, bint strict) noexcept --cdef MPF_to_fixed(mpz_t r, MPF *x, long prec, bint truncate) --cdef int MPF_sgn(MPF *x) noexcept --cdef void MPF_neg(MPF *r, MPF *s) noexcept --cdef void MPF_abs(MPF *r, MPF *s) noexcept --cdef MPF_normalize(MPF *x, MPopts opts) --cdef void MPF_pos(MPF *x, MPF *y, MPopts opts) noexcept --cdef MPF_add(MPF *r, MPF *s, MPF *t, MPopts opts) --cdef MPF_sub(MPF *r, MPF *s, MPF *t, MPopts opts) --cdef bint MPF_eq(MPF *s, MPF *t) noexcept --cdef bint MPF_ne(MPF *s, MPF *t) noexcept --cdef int MPF_cmp(MPF *s, MPF *t) noexcept --cdef bint MPF_lt(MPF *s, MPF *t) noexcept --cdef bint MPF_le(MPF *s, MPF *t) noexcept --cdef bint MPF_gt(MPF *s, MPF *t) noexcept --cdef bint MPF_ge(MPF *s, MPF *t) noexcept --cdef MPF_mul(MPF *r, MPF *s, MPF *t, MPopts opts) --cdef MPF_div(MPF *r, MPF *s, MPF *t, MPopts opts) --cdef int MPF_sqrt(MPF *r, MPF *s, MPopts opts) noexcept --cdef MPF_hypot(MPF *r, MPF *a, MPF *b, MPopts opts) --cdef MPF_pow_int(MPF *r, MPF *x, mpz_t n, MPopts opts) --cdef MPF_set_double(MPF *r, double x) --cdef MPF_exp(MPF *y, MPF *x, MPopts opts) --cdef MPF_complex_sqrt(MPF *c, MPF *d, MPF *a, MPF *b, MPopts opts) --cdef MPF_complex_exp(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts) --cdef int MPF_log(MPF *y, MPF *x, MPopts opts) noexcept --cdef MPF_set_pi(MPF *x, MPopts opts) --cdef MPF_set_ln2(MPF *x, MPopts opts) --cdef MPF_cos(MPF *c, MPF *x, MPopts opts) --cdef MPF_sin(MPF *c, MPF *x, MPopts opts) --cdef MPF_cos_sin(MPF *c, MPF *s, MPF *x, MPopts opts) --cdef int MPF_pow(MPF *z, MPF *x, MPF *y, MPopts opts) except -1 --cdef MPF_complex_pow(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *yre, MPF *yim, MPopts opts) --cdef MPF_hypsum(MPF *a, MPF *b, int p, int q, param_types, str ztype, coeffs, \ -- z, long prec, long wp, long epsshift, dict magnitude_check, kwargs) -diff --git a/src/sage/libs/mpmath/ext_impl.pyx b/src/sage/libs/mpmath/ext_impl.pyx -deleted file mode 100644 -index fb078719ac0..00000000000 ---- a/src/sage/libs/mpmath/ext_impl.pyx -+++ /dev/null -@@ -1,2284 +0,0 @@ --""" --This module provides the core implementation of multiprecision --floating-point arithmetic. Operations are done in-place. -- --TESTS: -- --See if :issue:`15118` is fixed:: -- -- sage: import mpmath -- sage: mpmath.mpf(0)^(-2) -- Traceback (most recent call last): -- ... -- ZeroDivisionError -- sage: mpmath.zeta(2r, -3r) -- Traceback (most recent call last): -- ... -- ZeroDivisionError --""" -- --#***************************************************************************** --# 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 2 of the License, or --# (at your option) any later version. --# http://www.gnu.org/licenses/ --#***************************************************************************** -- --from cpython.long cimport * --from cpython.float cimport * --from cpython.complex cimport * --from cpython.number cimport * -- --from libc.math cimport sqrt as fsqrt --from libc.math cimport frexp -- --from cysignals.signals cimport sig_check -- --from sage.ext.stdsage cimport PY_NEW --from sage.libs.gmp.all cimport * --from sage.libs.mpfr cimport * --from sage.rings.integer cimport Integer -- --from sage.libs.gmp.pylong cimport * -- --cdef mpz_set_integer(mpz_t v, x): -- if isinstance(x, int): -- mpz_set_pylong(v, x) -- elif isinstance(x, Integer): -- mpz_set(v, (x).value) -- else: -- raise TypeError("cannot convert %s to an integer" % x) -- --cdef inline void mpz_add_si(mpz_t a, mpz_t b, long x) noexcept: -- if x >= 0: -- mpz_add_ui(a, b, x) -- else: -- # careful: overflow when negating LONG_MIN -- mpz_sub_ui(a, b, -x) -- --cdef inline mpzi(mpz_t n): -- return mpz_get_pyintlong(n) -- --cdef inline mpzl(mpz_t n): -- return mpz_get_pylong(n) -- --# This should be done better --cdef int mpz_tstbit_abs(mpz_t z, unsigned long bit_index) noexcept: -- cdef int res -- if mpz_sgn(z) < 0: -- mpz_neg(z, z) -- res = mpz_tstbit(z, bit_index) -- mpz_neg(z, z) -- else: -- res = mpz_tstbit(z, bit_index) -- return res -- --cdef void mpz_set_fixed(mpz_t t, MPF *x, int prec, bint abs=False) noexcept: -- """ -- Set t = x, or t = |x|, as a fixed-point number with prec bits. -- """ -- cdef int offset -- offset = mpz_get_si(x.exp) + prec -- if offset >= 0: -- mpz_mul_2exp(t, x.man, offset) -- else: -- mpz_tdiv_q_2exp(t, x.man, -offset) -- if abs: -- mpz_abs(t, t) -- --cdef unsigned long mpz_bitcount(mpz_t z) noexcept: -- if mpz_sgn(z) == 0: -- return 0 -- return mpz_sizeinbase(z, 2) -- --# The following limits allowed exponent shifts. We could use mpz_fits_slong_p, --# but then (-LONG_MIN) wraps around; we may also not be able to add large --# shifts safely. A higher limit could be used on 64-bit systems, but --# it is unlikely that anyone will run into this (adding numbers --# that differ by 2^(2^30), at precisions of 2^30 bits). -- --# Note: MPFR's emax is 1073741823 --DEF MAX_SHIFT = 536870912 # 2^29 -- --cdef int mpz_reasonable_shift(mpz_t z) noexcept: -- if mpz_sgn(z) > 0: -- return mpz_cmp_ui(z, MAX_SHIFT) < 0 -- else: -- return mpz_cmp_si(z, -MAX_SHIFT) > 0 -- --DEF ROUND_N = 0 --DEF ROUND_F = 1 --DEF ROUND_C = 2 --DEF ROUND_D = 3 --DEF ROUND_U = 4 -- --DEF S_NORMAL = 0 --DEF S_ZERO = 1 --DEF S_NZERO = 2 --DEF S_INF = 3 --DEF S_NINF = 4 --DEF S_NAN = 5 -- --cdef inline str rndmode_to_python(int rnd): -- if rnd == ROUND_N: return 'n' -- if rnd == ROUND_F: return 'f' -- if rnd == ROUND_C: return 'c' -- if rnd == ROUND_D: return 'd' -- if rnd == ROUND_U: return 'u' -- --cdef inline rndmode_from_python(str rnd): -- if rnd == 'n': return ROUND_N -- if rnd == 'f': return ROUND_F -- if rnd == 'c': return ROUND_C -- if rnd == 'd': return ROUND_D -- if rnd == 'u': return ROUND_U -- --cdef inline mpfr_rnd_t rndmode_to_mpfr(int rnd) noexcept: -- if rnd == ROUND_N: return MPFR_RNDN -- if rnd == ROUND_F: return MPFR_RNDD -- if rnd == ROUND_C: return MPFR_RNDU -- if rnd == ROUND_D: return MPFR_RNDZ -- if rnd == ROUND_U: return MPFR_RNDA -- --cdef inline int reciprocal_rnd(int rnd) noexcept: -- if rnd == ROUND_N: return ROUND_N -- if rnd == ROUND_D: return ROUND_U -- if rnd == ROUND_U: return ROUND_D -- if rnd == ROUND_C: return ROUND_F -- if rnd == ROUND_F: return ROUND_C -- --cdef MPopts opts_exact --cdef MPopts opts_double_precision --cdef MPopts opts_mini_prec -- --opts_exact.prec = 0 --opts_exact.rounding = ROUND_N --opts_double_precision.prec = 53 --opts_double_precision.rounding = ROUND_N --opts_mini_prec.prec = 5 --opts_mini_prec.rounding = ROUND_D -- --cdef double _double_inf = float("1e300") * float("1e300") --cdef double _double_ninf = -_double_inf --cdef double _double_nan = _double_inf - _double_inf -- --cdef inline void MPF_init(MPF *x) noexcept: -- """Allocate space and set value to zero. -- Must be called exactly once when creating a new MPF.""" -- x.special = S_ZERO -- mpz_init(x.man) -- mpz_init(x.exp) -- --cdef inline void MPF_clear(MPF *x) noexcept: -- """Deallocate space. Must be called exactly once when finished with an MPF.""" -- mpz_clear(x.man) -- mpz_clear(x.exp) -- --cdef inline void MPF_set(MPF *dest, MPF *src) noexcept: -- """Clone MPF value. Assumes source value is already normalized.""" -- if src is dest: -- return -- dest.special = src.special -- mpz_set(dest.man, src.man) -- mpz_set(dest.exp, src.exp) -- --cdef inline void MPF_set_zero(MPF *x) noexcept: -- """Set value to 0.""" -- x.special = S_ZERO -- --cdef inline void MPF_set_one(MPF *x) noexcept: -- """Set value to 1.""" -- x.special = S_NORMAL -- mpz_set_ui(x.man, 1) -- mpz_set_ui(x.exp, 0) -- --cdef inline void MPF_set_nan(MPF *x) noexcept: -- """Set value to NaN (not a number).""" -- x.special = S_NAN -- --cdef inline void MPF_set_inf(MPF *x) noexcept: -- """Set value to +infinity.""" -- x.special = S_INF -- --cdef inline void MPF_set_ninf(MPF *x) noexcept: -- """Set value to -infinity.""" -- x.special = S_NINF -- --cdef MPF_set_si(MPF *x, long n): -- """Set value to that of a given C (long) integer.""" -- if n: -- x.special = S_NORMAL -- mpz_set_si(x.man, n) -- mpz_set_ui(x.exp, 0) -- MPF_normalize(x, opts_exact) -- else: -- MPF_set_zero(x) -- --cdef MPF_set_int(MPF *x, n): -- """Set value to that of a given Python integer.""" -- x.special = S_NORMAL -- mpz_set_integer(x.man, n) -- if mpz_sgn(x.man): -- mpz_set_ui(x.exp, 0) -- MPF_normalize(x, opts_exact) -- else: -- MPF_set_zero(x) -- --cdef MPF_set_man_exp(MPF *x, man, exp): -- """ -- Set value to man*2^exp where man, exp may be of any appropriate -- Python integer types. -- """ -- x.special = S_NORMAL -- mpz_set_integer(x.man, man) -- mpz_set_integer(x.exp, exp) -- MPF_normalize(x, opts_exact) -- -- --# Temporary variables. Note: not thread-safe. --# Used by MPF_add/MPF_sub/MPF_div --cdef mpz_t tmp_exponent --mpz_init(tmp_exponent) --cdef MPF tmp0 --MPF_init(&tmp0) -- --# Used by MPF_hypot and MPF_cmp, which may call MPF_add/MPF_sub --cdef MPF tmp1 --MPF_init(&tmp1) --cdef MPF tmp2 --MPF_init(&tmp2) -- -- --# Constants needed in a few places --cdef MPF MPF_C_1 --MPF_init(&MPF_C_1) --MPF_set_si(&MPF_C_1, 1) --cdef Integer MPZ_ZERO = Integer(0) --cdef tuple _mpf_fzero = (0, MPZ_ZERO, 0, 0) --cdef tuple _mpf_fnan = (0, MPZ_ZERO, -123, -1) --cdef tuple _mpf_finf = (0, MPZ_ZERO, -456, -2) --cdef tuple _mpf_fninf = (1, MPZ_ZERO, -789, -3) -- --cdef MPF_set_tuple(MPF *x, tuple value): -- """ -- Set value of an MPF to that of a normalized (sign, man, exp, bc) tuple -- in the format used by mpmath.libmp. -- """ -- #cdef int sign -- cdef Integer man -- sign, _man, exp, _ = value -- if isinstance(_man, Integer): -- man = _man -- else: -- # This is actually very unlikely; it should never happen -- # in internal code that man isn't an Integer. Maybe the check -- # can be avoided by doing checks in e.g. MPF_set_any? -- man = Integer(_man) -- if mpz_sgn(man.value): -- MPF_set_man_exp(x, man, exp) -- if sign: -- mpz_neg(x.man, x.man) -- return -- if value == _mpf_fzero: -- MPF_set_zero(x) -- elif value == _mpf_finf: -- MPF_set_inf(x) -- elif value == _mpf_fninf: -- MPF_set_ninf(x) -- else: -- MPF_set_nan(x) -- --cdef MPF_to_tuple(MPF *x): -- """Convert MPF value to (sign, man, exp, bc) tuple.""" -- cdef Integer man -- if x.special: -- if x.special == S_ZERO: return _mpf_fzero -- #if x.special == S_NZERO: return _mpf_fnzero -- if x.special == S_INF: return _mpf_finf -- if x.special == S_NINF: return _mpf_fninf -- return _mpf_fnan -- man = PY_NEW(Integer) -- if mpz_sgn(x.man) < 0: -- mpz_neg(man.value, x.man) -- sign = 1 -- else: -- mpz_set(man.value, x.man) -- sign = 0 -- exp = mpz_get_pyintlong(x.exp) -- bc = mpz_sizeinbase(x.man, 2) -- return (sign, man, exp, bc) -- --cdef MPF_set_double(MPF *r, double x): -- """ -- Set r to the value of a C double x. -- """ -- cdef int exp -- cdef double man -- if x != x: -- MPF_set_nan(r) -- return -- if x == _double_inf: -- MPF_set_inf(r) -- return -- if x == _double_ninf: -- MPF_set_ninf(r) -- return -- man = frexp(x, &exp) -- man *= 9007199254740992.0 -- mpz_set_d(r.man, man) -- mpz_set_si(r.exp, exp-53) -- r.special = S_NORMAL -- MPF_normalize(r, opts_exact) -- --import math as pymath -- --# TODO: implement this function safely without using the Python math module --cdef double MPF_to_double(MPF *x, bint strict) noexcept: -- """Convert MPF value to a Python float.""" -- if x.special == S_NORMAL: -- man = mpzi(x.man) -- exp = mpzi(x.exp) -- bc = mpz_sizeinbase(x.man, 2) -- try: -- if bc < 100: -- return pymath.ldexp(man, exp) -- # Try resizing the mantissa. Overflow may still happen here. -- n = bc - 53 -- m = man >> n -- return pymath.ldexp(m, exp + n) -- except OverflowError: -- if strict: -- raise -- # Overflow to infinity -- if exp + bc > 0: -- if man < 0: -- return _double_ninf -- else: -- return _double_inf -- # Underflow to zero -- return 0.0 -- if x.special == S_ZERO: -- return 0.0 -- if x.special == S_INF: -- return _double_inf -- if x.special == S_NINF: -- return _double_ninf -- return _double_nan -- --cdef MPF_to_fixed(mpz_t r, MPF *x, long prec, bint truncate): -- """ -- Set r = x, r being in the format of a fixed-point number with prec bits. -- Floor division is used unless truncate=True in which case -- truncating division is used. -- """ -- cdef long shift -- if x.special: -- if x.special == S_ZERO or x.special == S_NZERO: -- mpz_set_ui(r, 0) -- return -- raise ValueError("cannot create fixed-point number from special value") -- if mpz_reasonable_shift(x.exp): -- # XXX: signed integer overflow -- shift = mpz_get_si(x.exp) + prec -- if shift >= 0: -- mpz_mul_2exp(r, x.man, shift) -- else: -- if truncate: -- mpz_tdiv_q_2exp(r, x.man, -shift) -- else: -- mpz_fdiv_q_2exp(r, x.man, -shift) -- return -- # Underflow -- if mpz_sgn(x.exp) < 0: -- mpz_set_ui(r, 0) -- return -- raise OverflowError("cannot convert huge number to fixed-point format") -- --cdef int MPF_sgn(MPF *x) noexcept: -- """ -- Give the sign of an MPF (-1, 0, or 1). -- """ -- if x.special: -- if x.special == S_INF: -- return 1 -- if x.special == S_NINF: -- return -1 -- return 0 -- return mpz_sgn(x.man) -- --cdef void MPF_neg(MPF *r, MPF *s) noexcept: -- """ -- Set r = -s. MPF_neg(x, x) negates in place. -- """ -- if s.special: -- if s.special == S_ZERO: -- r.special = S_ZERO # r.special = S_NZERO -- elif s.special == S_NZERO: -- r.special = S_ZERO -- elif s.special == S_INF: -- r.special = S_NINF -- elif s.special == S_NINF: -- r.special = S_INF -- else: -- r.special = s.special -- return -- r.special = s.special -- mpz_neg(r.man, s.man) -- if r is not s: -- mpz_set(r.exp, s.exp) -- --cdef void MPF_abs(MPF *r, MPF *s) noexcept: -- """ -- Set r = abs(s). MPF_abs(r, r) sets the absolute value in place. -- """ -- if s.special: -- if s.special == S_NINF: -- r.special = S_INF -- else: -- r.special = s.special -- return -- r.special = s.special -- mpz_abs(r.man, s.man) -- if r is not s: -- mpz_set(r.exp, s.exp) -- --cdef MPF_normalize(MPF *x, MPopts opts): -- """ -- Normalize. -- -- With prec = 0, trailing zero bits are stripped but no rounding -- is performed. -- """ -- cdef int sign -- cdef long trail, bc, shift -- if x.special != S_NORMAL: -- return -- sign = mpz_sgn(x.man) -- if sign == 0: -- x.special = S_ZERO -- mpz_set_ui(x.exp, 0) -- return -- bc = mpz_sizeinbase(x.man, 2) -- shift = bc - opts.prec -- # Ok if mantissa small and no trailing zero bits -- if (shift <= 0 or not opts.prec) and mpz_odd_p(x.man): -- return -- # Mantissa is too large, so divide by appropriate power of 2 -- # Need to be careful about rounding -- if shift > 0 and opts.prec: -- if opts.rounding == ROUND_N: -- if mpz_tstbit_abs(x.man, shift-1): -- if mpz_tstbit_abs(x.man, shift) or mpz_scan1(x.man, 0) < (shift-1): -- if sign < 0: -- mpz_fdiv_q_2exp(x.man, x.man, shift) -- else: -- mpz_cdiv_q_2exp(x.man, x.man, shift) -- else: -- mpz_tdiv_q_2exp(x.man, x.man, shift) -- else: -- mpz_tdiv_q_2exp(x.man, x.man, shift) -- elif opts.rounding == ROUND_D: -- mpz_tdiv_q_2exp(x.man, x.man, shift) -- elif opts.rounding == ROUND_F: -- mpz_fdiv_q_2exp(x.man, x.man, shift) -- elif opts.rounding == ROUND_C: -- mpz_cdiv_q_2exp(x.man, x.man, shift) -- elif opts.rounding == ROUND_U: -- if sign < 0: -- mpz_fdiv_q_2exp(x.man, x.man, shift) -- else: -- mpz_cdiv_q_2exp(x.man, x.man, shift) -- else: -- raise ValueError("bad rounding mode") -- else: -- shift = 0 -- # Strip trailing bits -- trail = mpz_scan1(x.man, 0) -- if 0 < trail < bc: -- mpz_tdiv_q_2exp(x.man, x.man, trail) -- shift += trail -- mpz_add_si(x.exp, x.exp, shift) -- --cdef void MPF_pos(MPF *x, MPF *y, MPopts opts) noexcept: -- """ -- Set x = +y (i.e. copy the value, and round if the -- working precision is smaller than the width -- of the mantissa of y). -- """ -- MPF_set(x, y) -- MPF_normalize(x, opts) -- --cdef void _add_special(MPF *r, MPF *s, MPF *t) noexcept: -- if s.special == S_ZERO: -- # (+0) + (-0) = +0 -- if t.special == S_NZERO: -- MPF_set(r, s) -- # (+0) + x = x -- else: -- MPF_set(r, t) -- elif t.special == S_ZERO: -- # (-0) + (+0) = +0 -- if s.special == S_NZERO: -- MPF_set(r, t) -- # x + (+0) = x -- else: -- MPF_set(r, s) -- # (+/- 0) + x = x -- elif s.special == S_NZERO: -- MPF_set(r, t) -- elif t.special == S_NZERO: -- MPF_set(r, s) -- # (+/- inf) + (-/+ inf) = nan -- elif ((s.special == S_INF and t.special == S_NINF) or -- (s.special == S_NINF and t.special == S_INF)): -- MPF_set_nan(r) -- # nan or +/- inf trumps any finite number -- elif s.special == S_NAN or t.special == S_NAN: -- MPF_set_nan(r) -- elif s.special: -- MPF_set(r, s) -- else: -- MPF_set(r, t) -- return -- --cdef void _sub_special(MPF *r, MPF *s, MPF *t) noexcept: -- if s.special == S_ZERO: -- # (+0) - (+/-0) = (+0) -- if t.special == S_NZERO: -- MPF_set(r, s) -- else: -- # (+0) - x = (-x) -- MPF_neg(r, t) -- elif t.special == S_ZERO: -- # x - (+0) = x; also covers (-0) - (+0) = (-0) -- MPF_set(r, s) -- # (-0) - x = x -- elif s.special == S_NZERO: -- # (-0) - (-0) = (+0) -- if t.special == S_NZERO: -- MPF_set_zero(r) -- # (-0) - x = -x -- else: -- MPF_neg(r, t) -- elif t.special == S_NZERO: -- # x - (-0) = x -- MPF_set(r, s) -- # (+/- inf) - (+/- inf) = nan -- elif ((s.special == S_INF and t.special == S_INF) or -- (s.special == S_NINF and t.special == S_NINF)): -- MPF_set_nan(r) -- elif s.special == S_NAN or t.special == S_NAN: -- MPF_set_nan(r) -- # nan - x or (+/-inf) - x = l.h.s -- elif s.special: -- MPF_set(r, s) -- # x - nan or x - (+/-inf) = (- r.h.s) -- else: -- MPF_neg(r, t) -- --cdef void _mul_special(MPF *r, MPF *s, MPF *t) noexcept: -- if s.special == S_ZERO: -- if t.special == S_NORMAL or t.special == S_ZERO: -- MPF_set(r, s) -- elif t.special == S_NZERO: -- MPF_set(r, t) -- else: -- MPF_set_nan(r) -- elif t.special == S_ZERO: -- if s.special == S_NORMAL: -- MPF_set(r, t) -- elif s.special == S_NZERO: -- MPF_set(r, s) -- else: -- MPF_set_nan(r) -- elif s.special == S_NZERO: -- if t.special == S_NORMAL: -- if mpz_sgn(t.man) < 0: -- MPF_set_zero(r) -- else: -- MPF_set(r, s) -- else: -- MPF_set_nan(r) -- elif t.special == S_NZERO: -- if s.special == S_NORMAL: -- if mpz_sgn(s.man) < 0: -- MPF_set_zero(r) -- else: -- MPF_set(r, t) -- else: -- MPF_set_nan(r) -- elif s.special == S_NAN or t.special == S_NAN: -- MPF_set_nan(r) -- else: -- if MPF_sgn(s) == MPF_sgn(t): -- MPF_set_inf(r) -- else: -- MPF_set_ninf(r) -- --cdef _div_special(MPF *r, MPF *s, MPF *t): -- # TODO: handle signed zeros correctly -- if s.special == S_NAN or t.special == S_NAN: -- MPF_set_nan(r) -- elif t.special == S_ZERO or t.special == S_NZERO: -- raise ZeroDivisionError -- elif s.special == S_ZERO or s.special == S_NZERO: -- MPF_set_zero(r) -- elif s.special == S_NORMAL: -- MPF_set_zero(r) -- elif s.special == S_INF or s.special == S_NINF: -- if t.special == S_INF or t.special == S_NINF: -- MPF_set_nan(r) -- elif MPF_sgn(s) == MPF_sgn(t): -- MPF_set_inf(r) -- else: -- MPF_set_ninf(r) -- # else: -- elif t.special == S_INF or t.special == S_NINF: -- MPF_set_zero(r) -- --cdef _add_perturbation(MPF *r, MPF *s, int sign, MPopts opts): -- cdef long shift -- if opts.rounding == ROUND_N: -- MPF_set(r, s) -- else: -- shift = opts.prec - mpz_sizeinbase(s.man, 2) + 8 -- if shift < 0: -- shift = 8 -- mpz_mul_2exp(r.man, s.man, shift) -- mpz_add_si(r.man, r.man, sign) -- mpz_sub_ui(r.exp, s.exp, shift) -- MPF_normalize(r, opts) -- --cdef MPF_add(MPF *r, MPF *s, MPF *t, MPopts opts): -- """ -- Set r = s + t, with exact rounding. -- -- With prec = 0, the addition is performed exactly. Note that this -- may cause overflow if the exponents are huge. -- """ -- cdef long shift, sbc, tbc -- #assert (r is not s) and (r is not t) -- if s.special or t.special: -- _add_special(r, s, t) -- return -- r.special = S_NORMAL -- # Difference between exponents -- mpz_sub(tmp_exponent, s.exp, t.exp) -- if mpz_reasonable_shift(tmp_exponent): -- shift = mpz_get_si(tmp_exponent) -- if shift >= 0: -- # |s| >> |t| -- if shift > 2*opts.prec and opts.prec: -- sbc = mpz_sizeinbase(s.man, 2) -- tbc = mpz_sizeinbase(t.man, 2) -- if shift + sbc - tbc > opts.prec+8: -- _add_perturbation(r, s, mpz_sgn(t.man), opts) -- return -- # |s| > |t| -- mpz_mul_2exp(tmp0.man, s.man, shift) -- mpz_add(r.man, tmp0.man, t.man) -- mpz_set(r.exp, t.exp) -- MPF_normalize(r, opts) -- elif shift < 0: -- shift = -shift -- # |s| << |t| -- if shift > 2*opts.prec and opts.prec: -- sbc = mpz_sizeinbase(s.man, 2) -- tbc = mpz_sizeinbase(t.man, 2) -- if shift + tbc - sbc > opts.prec+8: -- _add_perturbation(r, t, mpz_sgn(s.man), opts) -- return -- # |s| < |t| -- mpz_mul_2exp(tmp0.man, t.man, shift) -- mpz_add(r.man, tmp0.man, s.man) -- mpz_set(r.exp, s.exp) -- MPF_normalize(r, opts) -- else: -- if not opts.prec: -- raise OverflowError("the exact result does not fit in memory") -- # |s| >>> |t| -- if mpz_sgn(tmp_exponent) > 0: -- _add_perturbation(r, s, mpz_sgn(t.man), opts) -- # |s| <<< |t| -- else: -- _add_perturbation(r, t, mpz_sgn(s.man), opts) -- --cdef MPF_sub(MPF *r, MPF *s, MPF *t, MPopts opts): -- """ -- Set r = s - t, with exact rounding. -- -- With prec = 0, the addition is performed exactly. Note that this -- may cause overflow if the exponents are huge. -- """ -- cdef long shift, sbc, tbc -- #assert (r is not s) and (r is not t) -- if s.special or t.special: -- _sub_special(r, s, t) -- return -- r.special = S_NORMAL -- # Difference between exponents -- mpz_sub(tmp_exponent, s.exp, t.exp) -- if mpz_reasonable_shift(tmp_exponent): -- shift = mpz_get_si(tmp_exponent) -- if shift >= 0: -- # |s| >> |t| -- if shift > 2*opts.prec and opts.prec: -- sbc = mpz_sizeinbase(s.man, 2) -- tbc = mpz_sizeinbase(t.man, 2) -- if shift + sbc - tbc > opts.prec+8: -- _add_perturbation(r, s, -mpz_sgn(t.man), opts) -- return -- # |s| > |t| -- mpz_mul_2exp(tmp0.man, s.man, shift) -- mpz_sub(r.man, tmp0.man, t.man) -- mpz_set(r.exp, t.exp) -- MPF_normalize(r, opts) -- elif shift < 0: -- shift = -shift -- # |s| << |t| -- if shift > 2*opts.prec and opts.prec: -- sbc = mpz_sizeinbase(s.man, 2) -- tbc = mpz_sizeinbase(t.man, 2) -- if shift + tbc - sbc > opts.prec+8: -- _add_perturbation(r, t, -mpz_sgn(s.man), opts) -- MPF_neg(r, r) -- return -- # |s| < |t| -- mpz_mul_2exp(tmp0.man, t.man, shift) -- mpz_sub(r.man, s.man, tmp0.man) -- mpz_set(r.exp, s.exp) -- MPF_normalize(r, opts) -- else: -- if not opts.prec: -- raise OverflowError("the exact result does not fit in memory") -- # |s| >>> |t| -- if mpz_sgn(tmp_exponent) > 0: -- _add_perturbation(r, s, -mpz_sgn(t.man), opts) -- # |s| <<< |t| -- else: -- _add_perturbation(r, t, -mpz_sgn(s.man), opts) -- MPF_neg(r, r) -- --cdef bint MPF_eq(MPF *s, MPF *t) noexcept: -- """ -- Evaluates s == t. -- """ -- if s.special == S_NAN or t.special == S_NAN: -- return False -- if s.special == t.special: -- if s.special == S_NORMAL: -- return (mpz_cmp(s.man, t.man) == 0) and (mpz_cmp(s.exp, t.exp) == 0) -- else: -- return True -- return False -- --cdef bint MPF_ne(MPF *s, MPF *t) noexcept: -- """ -- Evaluates s != t. -- """ -- if s.special == S_NAN or t.special == S_NAN: -- return True -- if s.special == S_NORMAL and t.special == S_NORMAL: -- return (mpz_cmp(s.man, t.man) != 0) or (mpz_cmp(s.exp, t.exp) != 0) -- return s.special != t.special -- --cdef int MPF_cmp(MPF *s, MPF *t) noexcept: -- """ -- Evaluates cmp(s,t). Conventions for nan follow those -- of the mpmath.libmp function. -- """ -- cdef long sbc, tbc -- cdef int cm -- if MPF_eq(s, t): -- return 0 -- if s.special != S_NORMAL or t.special != S_NORMAL: -- if s.special == S_ZERO: return -MPF_sgn(t) -- if t.special == S_ZERO: return MPF_sgn(s) -- if t.special == S_NAN: return 1 -- if s.special == S_INF: return 1 -- if t.special == S_NINF: return 1 -- return -1 -- if mpz_sgn(s.man) != mpz_sgn(t.man): -- if mpz_sgn(s.man) < 0: -- return -1 -- else: -- return 1 -- if not mpz_cmp(s.exp, t.exp): -- return mpz_cmp(s.man, t.man) -- mpz_add_ui(tmp1.exp, s.exp, mpz_sizeinbase(s.man, 2)) -- mpz_add_ui(tmp2.exp, t.exp, mpz_sizeinbase(t.man, 2)) -- cm = mpz_cmp(tmp1.exp, tmp2.exp) -- if mpz_sgn(s.man) < 0: -- if cm < 0: return 1 -- if cm > 0: return -1 -- else: -- if cm < 0: return -1 -- if cm > 0: return 1 -- MPF_sub(&tmp1, s, t, opts_mini_prec) -- return MPF_sgn(&tmp1) -- --cdef bint MPF_lt(MPF *s, MPF *t) noexcept: -- """ -- Evaluates s < t. -- """ -- if s.special == S_NAN or t.special == S_NAN: -- return False -- return MPF_cmp(s, t) < 0 -- --cdef bint MPF_le(MPF *s, MPF *t) noexcept: -- """ -- Evaluates s <= t. -- """ -- if s.special == S_NAN or t.special == S_NAN: -- return False -- return MPF_cmp(s, t) <= 0 -- --cdef bint MPF_gt(MPF *s, MPF *t) noexcept: -- """ -- Evaluates s > t. -- """ -- if s.special == S_NAN or t.special == S_NAN: -- return False -- return MPF_cmp(s, t) > 0 -- --cdef bint MPF_ge(MPF *s, MPF *t) noexcept: -- """ -- Evaluates s >= t. -- """ -- if s.special == S_NAN or t.special == S_NAN: -- return False -- return MPF_cmp(s, t) >= 0 -- --cdef MPF_mul(MPF *r, MPF *s, MPF *t, MPopts opts): -- """ -- Set r = s * t, with correct rounding. -- -- With prec = 0, the multiplication is performed exactly, -- i.e. no rounding is performed. -- """ -- if s.special or t.special: -- _mul_special(r, s, t) -- else: -- r.special = S_NORMAL -- mpz_mul(r.man, s.man, t.man) -- mpz_add(r.exp, s.exp, t.exp) -- if opts.prec: -- MPF_normalize(r, opts) -- --cdef MPF_div(MPF *r, MPF *s, MPF *t, MPopts opts): -- """ -- Set r = s / t, with correct rounding. -- """ -- cdef int sign -- cdef long sbc, tbc, extra -- cdef mpz_t rem -- #assert (r is not s) and (r is not t) -- if s.special or t.special: -- _div_special(r, s, t) -- return -- r.special = S_NORMAL -- # Division by a power of two <=> shift exponents -- if mpz_cmp_si(t.man, 1) == 0: -- MPF_set(&tmp0, s) -- mpz_sub(tmp0.exp, tmp0.exp, t.exp) -- MPF_normalize(&tmp0, opts) -- MPF_set(r, &tmp0) -- return -- elif mpz_cmp_si(t.man, -1) == 0: -- MPF_neg(&tmp0, s) -- mpz_sub(tmp0.exp, tmp0.exp, t.exp) -- MPF_normalize(&tmp0, opts) -- MPF_set(r, &tmp0) -- return -- sign = mpz_sgn(s.man) != mpz_sgn(t.man) -- # Same strategy as for addition: if there is a remainder, perturb -- # the result a few bits outside the precision range before rounding -- extra = opts.prec - mpz_sizeinbase(s.man,2) + mpz_sizeinbase(t.man,2) + 5 -- if extra < 5: -- extra = 5 -- mpz_init(rem) -- mpz_mul_2exp(tmp0.man, s.man, extra) -- mpz_tdiv_qr(r.man, rem, tmp0.man, t.man) -- if mpz_sgn(rem): -- mpz_mul_2exp(r.man, r.man, 1) -- if sign: -- mpz_sub_ui(r.man, r.man, 1) -- else: -- mpz_add_ui(r.man, r.man, 1) -- extra += 1 -- mpz_clear(rem) -- mpz_sub(r.exp, s.exp, t.exp) -- mpz_sub_ui(r.exp, r.exp, extra) -- MPF_normalize(r, opts) -- --cdef int MPF_sqrt(MPF *r, MPF *s, MPopts opts) noexcept: -- """ -- Set r = sqrt(s), with correct rounding. -- """ -- cdef long shift -- cdef mpz_t rem -- #assert r is not s -- if s.special: -- if s.special == S_ZERO or s.special == S_INF: -- MPF_set(r, s) -- else: -- MPF_set_nan(r) -- return 0 -- if mpz_sgn(s.man) < 0: -- MPF_set_nan(r) -- return 1 -- r.special = S_NORMAL -- if mpz_odd_p(s.exp): -- mpz_sub_ui(r.exp, s.exp, 1) -- mpz_mul_2exp(r.man, s.man, 1) -- elif mpz_cmp_ui(s.man, 1) == 0: -- # Square of a power of two -- mpz_set_ui(r.man, 1) -- mpz_tdiv_q_2exp(r.exp, s.exp, 1) -- MPF_normalize(r, opts) -- return 0 -- else: -- mpz_set(r.man, s.man) -- mpz_set(r.exp, s.exp) -- shift = 2*opts.prec - mpz_sizeinbase(r.man,2) + 4 -- if shift < 4: -- shift = 4 -- shift += shift & 1 -- mpz_mul_2exp(r.man, r.man, shift) -- if opts.rounding == ROUND_F or opts.rounding == ROUND_D: -- mpz_sqrt(r.man, r.man) -- else: -- mpz_init(rem) -- mpz_sqrtrem(r.man, rem, r.man) -- if mpz_sgn(rem): -- mpz_mul_2exp(r.man, r.man, 1) -- mpz_add_ui(r.man, r.man, 1) -- shift += 2 -- mpz_clear(rem) -- mpz_add_si(r.exp, r.exp, -shift) -- mpz_tdiv_q_2exp(r.exp, r.exp, 1) -- MPF_normalize(r, opts) -- return 0 -- --cdef MPF_hypot(MPF *r, MPF *a, MPF *b, MPopts opts): -- """ -- Set r = sqrt(a^2 + b^2) -- """ -- cdef MPopts tmp_opts -- if a.special == S_ZERO: -- MPF_abs(r, b) -- MPF_normalize(r, opts) -- return -- if b.special == S_ZERO: -- MPF_abs(r, a) -- MPF_normalize(r, opts) -- return -- tmp_opts = opts -- tmp_opts.prec += 30 -- MPF_mul(&tmp1, a, a, opts_exact) -- MPF_mul(&tmp2, b, b, opts_exact) -- MPF_add(r, &tmp1, &tmp2, tmp_opts) -- MPF_sqrt(r, r, opts) -- --cdef MPF_pow_int(MPF *r, MPF *x, mpz_t n, MPopts opts): -- """ -- Set r = x ** n. Currently falls back to mpmath.libmp -- unless n is tiny. -- """ -- cdef long m, absm -- cdef unsigned long bc -- cdef int nsign -- if x.special != S_NORMAL: -- nsign = mpz_sgn(n) -- if x.special == S_ZERO: -- if nsign < 0: -- raise ZeroDivisionError -- elif nsign == 0: -- MPF_set(r, &MPF_C_1) -- else: -- MPF_set_zero(r) -- elif x.special == S_INF: -- if nsign > 0: -- MPF_set(r, x) -- elif nsign == 0: -- MPF_set_nan(r) -- else: -- MPF_set_zero(r) -- elif x.special == S_NINF: -- if nsign > 0: -- if mpz_odd_p(n): -- MPF_set(r, x) -- else: -- MPF_neg(r, x) -- elif nsign == 0: -- MPF_set_nan(r) -- else: -- MPF_set_zero(r) -- else: -- MPF_set_nan(r) -- return -- bc = mpz_sizeinbase(r.man,2) -- r.special = S_NORMAL -- if mpz_reasonable_shift(n): -- m = mpz_get_si(n) -- if m == 0: -- MPF_set(r, &MPF_C_1) -- return -- if m == 1: -- MPF_set(r, x) -- MPF_normalize(r, opts) -- return -- if m == 2: -- MPF_mul(r, x, x, opts) -- return -- if m == -1: -- MPF_div(r, &MPF_C_1, x, opts) -- return -- if m == -2: -- MPF_mul(r, x, x, opts_exact) -- MPF_div(r, &MPF_C_1, r, opts) -- return -- absm = abs(m) -- if bc * absm < 10000: -- mpz_pow_ui(r.man, x.man, absm) -- mpz_mul_ui(r.exp, x.exp, absm) -- if m < 0: -- MPF_div(r, &MPF_C_1, r, opts) -- else: -- MPF_normalize(r, opts) -- return -- r.special = S_NORMAL -- # (2^p)^n -- if mpz_cmp_si(x.man, 1) == 0: -- mpz_set(r.man, x.man) -- mpz_mul(r.exp, x.exp, n) -- return -- # (-2^p)^n -- if mpz_cmp_si(x.man, -1) == 0: -- if mpz_odd_p(n): -- mpz_set(r.man, x.man) -- else: -- mpz_neg(r.man, x.man) -- mpz_mul(r.exp, x.exp, n) -- return -- # TODO: implement efficiently here -- import mpmath.libmp -- MPF_set_tuple(r, -- mpmath.libmp.mpf_pow_int(MPF_to_tuple(x), mpzi(n), -- opts.prec, rndmode_to_python(opts.rounding))) -- --cdef mpz_t _pi_value --cdef int _pi_prec = -1 -- --cdef mpz_t _ln2_value --cdef int _ln2_prec = -1 -- --cdef mpz_set_pi(mpz_t x, int prec): -- """ -- Set x = pi as a fixed-point number. -- """ -- global _pi_value -- global _pi_prec -- if prec <= _pi_prec: -- mpz_tdiv_q_2exp(x, _pi_value, _pi_prec-prec) -- else: -- from mpmath.libmp import pi_fixed -- if _pi_prec < 0: -- mpz_init(_pi_value) -- mpz_set_integer(_pi_value, pi_fixed(prec)) -- mpz_set(x, _pi_value) -- _pi_prec = prec -- --cdef mpz_set_ln2(mpz_t x, int prec): -- """ -- Set x = ln(2) as a fixed-point number. -- """ -- global _ln2_value -- global _ln2_prec -- if prec <= _ln2_prec: -- mpz_tdiv_q_2exp(x, _ln2_value, _ln2_prec-prec) -- else: -- from mpmath.libmp import ln2_fixed -- if _ln2_prec < 0: -- mpz_init(_ln2_value) -- mpz_set_integer(_ln2_value, ln2_fixed(prec)) -- mpz_set(x, _ln2_value) -- _ln2_prec = prec -- --cdef void _cy_exp_mpfr(mpz_t y, mpz_t x, int prec) noexcept: -- """ -- Compute y = exp(x) for fixed-point numbers y and x using MPFR, -- assuming that no overflow will occur. -- """ -- cdef mpfr_t yf, xf -- mpfr_init2(xf, mpz_bitcount(x)+2) -- mpfr_init2(yf, prec+2) -- mpfr_set_z(xf, x, MPFR_RNDN) -- mpfr_div_2exp(xf, xf, prec, MPFR_RNDN) -- mpfr_exp(yf, xf, MPFR_RNDN) -- mpfr_mul_2exp(yf, yf, prec, MPFR_RNDN) -- mpfr_get_z(y, yf, MPFR_RNDN) -- mpfr_clear(yf) -- mpfr_clear(xf) -- --cdef cy_exp_basecase(mpz_t y, mpz_t x, int prec): -- """ -- Compute y = exp(x) for fixed-point numbers y and x, assuming -- that x is small (|x| ~< 1). At small precisions, this function -- is equivalent to the exp_basecase function in -- mpmath.libmp.exp_fixed. -- """ -- cdef int k, r, u -- cdef mpz_t s0, s1, x2, a -- # TODO: could use custom implementation here; for now switch to MPFR -- if prec > 2000: -- _cy_exp_mpfr(y, x, prec) -- return -- mpz_init(s0) -- mpz_init(s1) -- mpz_init(x2) -- mpz_init(a) -- r = fsqrt(prec) -- prec += r -- mpz_set_ui(s0, 1) -- mpz_mul_2exp(s0, s0, prec) -- mpz_set(s1, s0) -- k = 2 -- mpz_mul(x2, x, x) -- mpz_fdiv_q_2exp(x2, x2, prec) -- mpz_set(a, x2) -- while mpz_sgn(a): -- sig_check() -- mpz_fdiv_q_ui(a, a, k) -- mpz_add(s0, s0, a) -- k += 1 -- mpz_fdiv_q_ui(a, a, k) -- mpz_add(s1, s1, a) -- k += 1 -- mpz_mul(a, a, x2) -- mpz_fdiv_q_2exp(a, a, prec) -- mpz_mul(s1, s1, x) -- mpz_fdiv_q_2exp(s1, s1, prec) -- mpz_add(s0, s0, s1) -- u = r -- while r: -- sig_check() -- mpz_mul(s0, s0, s0) -- mpz_fdiv_q_2exp(s0, s0, prec) -- r -= 1 -- mpz_fdiv_q_2exp(y, s0, u) -- mpz_clear(s0) -- mpz_clear(s1) -- mpz_clear(x2) -- mpz_clear(a) -- -- --cdef MPF_exp(MPF *y, MPF *x, MPopts opts): -- """ -- Set y = exp(x). -- """ -- cdef bint sign, is_int -- cdef long wp, wpmod, offset, mag -- cdef mpz_t t, u -- cdef tuple w -- if x.special: -- if x.special == S_ZERO: -- MPF_set_si(y, 1) -- elif x.special == S_NINF: -- MPF_set_zero(y) -- elif x.special == S_INF: -- MPF_set_inf(y) -- else: -- MPF_set_nan(y) -- return -- wp = opts.prec + 14 -- sign = mpz_sgn(x.man) < 0 -- is_int = mpz_sgn(x.exp) >= 0 -- # note: bogus if not reasonable shift -- mag = mpz_bitcount(x.man) + mpz_get_si(x.exp) -- if (not mpz_reasonable_shift(x.exp)) or mag < -wp: -- if mpz_sgn(x.exp) <= 0: -- # perturb -- MPF_set_one(y) -- if opts.rounding != ROUND_N: -- mpz_mul_2exp(y.man, y.man, wp) -- if sign: -- mpz_sub_ui(y.man, y.man, 1) -- else: -- mpz_add_ui(y.man, y.man, 1) -- mpz_set_si(y.exp, -wp) -- MPF_normalize(y, opts) -- return -- else: -- raise OverflowError("exp of a huge number") -- #offset = mpz_get_si(x.exp) + wp -- mpz_init(t) -- if mag > 1: -- wpmod = wp + mag -- mpz_set_fixed(t, x, wpmod, False) -- mpz_init(u) -- mpz_set_ln2(u, wpmod) -- # y.exp, t = divmod(t, ln2) -- mpz_fdiv_qr(y.exp,t,t,u) -- mpz_clear(u) -- mpz_fdiv_q_2exp(t, t, mag) -- else: -- mpz_set_fixed(t, x, wp, False) -- mpz_set_ui(y.exp, 0) -- cy_exp_basecase(y.man, t, wp) -- mpz_add_si(y.exp, y.exp, -wp) -- y.special = S_NORMAL -- mpz_clear(t) -- MPF_normalize(y, opts) -- -- --cdef MPF_complex_sqrt(MPF *c, MPF *d, MPF *a, MPF *b, MPopts opts): -- """ -- Set c+di = sqrt(a+bi). -- -- c, a and d, b may be the same objects. -- """ -- cdef int apos, bneg -- cdef MPF t, u, v -- cdef MPopts wpopts -- if b.special == S_ZERO: -- if a.special == S_ZERO: -- MPF_set_zero(c) -- MPF_set_zero(d) -- # a+bi, a < 0, b = 0 -- elif MPF_sgn(a) < 0: -- MPF_abs(d, a) -- MPF_sqrt(d, d, opts) -- MPF_set_zero(c) -- # a > 0 -- else: -- MPF_sqrt(c, a, opts) -- MPF_set_zero(d) -- return -- wpopts.prec = opts.prec + 20 -- wpopts.rounding = ROUND_D -- MPF_init(&t) -- MPF_init(&u) -- MPF_init(&v) -- apos = MPF_sgn(a) >= 0 -- bneg = MPF_sgn(b) <= 0 -- if apos: -- # real part -- MPF_hypot(&t, a, b, wpopts) # t = abs(a+bi) + a -- MPF_add(&t, &t, a, wpopts) -- MPF_set(&u, &t) -- mpz_sub_ui(u.exp, u.exp, 1) # u = t / 2 -- MPF_sqrt(c, &u, opts) # re = sqrt(u) -- # imag part -- mpz_add_ui(t.exp, t.exp, 1) # t = 2*t -- MPF_sqrt(&u, &t, wpopts) # u = sqrt(t) -- MPF_div(d, b, &u, opts) # im = b / u -- else: -- MPF_set(&v, b) -- MPF_hypot(&t, a, b, wpopts) # t = abs(a+bi) - a -- MPF_sub(&t, &t, a, wpopts) -- MPF_set(&u, &t) -- mpz_sub_ui(u.exp, u.exp, 1) # u = t / 2 -- MPF_sqrt(d, &u, opts) # im = sqrt(u) -- mpz_add_ui(t.exp, t.exp, 1) # t = 2*t -- MPF_sqrt(&u, &t, wpopts) # u = sqrt(t) -- MPF_div(c, &v, &u, opts) # re = b / u -- if bneg: -- MPF_neg(c, c) -- MPF_neg(d, d) -- MPF_clear(&t) -- MPF_clear(&u) -- MPF_clear(&v) -- --cdef int MPF_get_mpfr_overflow(mpfr_t y, MPF *x) noexcept: -- """ -- Store the mpmath number x exactly in the MPFR variable y. The precision -- of y will be adjusted if necessary. If the exponent overflows, only -- the mantissa is stored and 1 is returned; if no overflow occurs, -- the function returns 0. -- """ -- cdef long prec, exp -- if x.special != S_NORMAL: -- if x.special == S_ZERO: -- mpfr_set_ui(y, 0, MPFR_RNDN) -- elif x.special == S_INF: -- mpfr_set_inf(y, 1) -- elif x.special == S_NINF: -- mpfr_set_inf(y, -1) -- else: -- mpfr_set_nan(y) -- return 0 -- prec = mpz_bitcount(x.man) -- # Minimum precision for MPFR -- if prec < 2: -- prec = 2 -- mpfr_set_prec(y, prec) -- mpfr_set_z(y, x.man, MPFR_RNDN) -- if mpz_reasonable_shift(x.exp): -- exp = mpz_get_si(x.exp) -- if exp >= 0: -- mpfr_mul_2exp(y, y, exp, MPFR_RNDN) -- else: -- mpfr_div_2exp(y, y, -exp, MPFR_RNDN) -- return 0 -- else: -- return 1 -- --cdef MPF_set_mpfr(MPF *y, mpfr_t x, MPopts opts): -- """ -- Convert the MPFR number x to a normalized MPF y. -- inf/nan and zero are handled. -- """ -- cdef long exp -- # TODO: use mpfr_regular_p with MPFR 3 -- if mpfr_nan_p(x): -- MPF_set_nan(y) -- return -- if mpfr_inf_p(x): -- if mpfr_sgn(x) > 0: -- MPF_set_inf(y) -- else: -- MPF_set_ninf(y) -- return -- if mpfr_zero_p(x): -- MPF_set_zero(y) -- return -- exp = mpfr_get_z_exp(y.man, x) -- mpz_set_si(y.exp, exp) -- y.special = S_NORMAL -- MPF_normalize(y, opts) -- --cdef int MPF_log(MPF *y, MPF *x, MPopts opts) noexcept: -- """ -- Set y = log(|x|). Returns 1 if x is negative. -- """ -- cdef MPF t -- cdef bint negative, overflow -- cdef mpfr_rnd_t rndmode -- cdef mpfr_t yy, xx -- if x.special != S_NORMAL: -- if x.special == S_ZERO: -- MPF_set_ninf(y) -- return 0 -- if x.special == S_INF: -- MPF_set_inf(y) -- return 0 -- if x.special == S_NAN: -- MPF_set_nan(y) -- return 0 -- if x.special == S_NINF: -- MPF_set_inf(y) -- return 1 -- -- negative = MPF_sgn(x) < 0 -- mpfr_init2(xx, opts.prec) -- mpfr_init2(yy, opts.prec) -- -- overflow = MPF_get_mpfr_overflow(xx, x) -- rndmode = rndmode_to_mpfr(opts.rounding) -- -- if overflow: -- MPF_init(&t) -- # Copy x exponent in case x and y are aliased -- mpz_set(t.exp, x.exp) -- -- # log(m * 2^e) = log(m) + e*log(2) -- mpfr_abs(xx, xx, MPFR_RNDN) -- mpfr_log(yy, xx, rndmode) -- MPF_set_mpfr(y, yy, opts) -- -- mpz_set_ln2(t.man, opts.prec+20) -- mpz_mul(t.man, t.man, t.exp) -- mpz_set_si(t.exp, -(opts.prec+20)) -- t.special = S_NORMAL -- -- MPF_add(y, y, &t, opts) -- MPF_clear(&t) -- else: -- mpfr_abs(xx, xx, MPFR_RNDN) -- mpfr_log(yy, xx, rndmode) -- MPF_set_mpfr(y, yy, opts) -- -- mpfr_clear(xx) -- mpfr_clear(yy) -- return negative -- --cdef MPF_set_pi(MPF *x, MPopts opts): -- """ -- Set x = pi. -- """ -- x.special = S_NORMAL -- mpz_set_pi(x.man, (opts.prec+20)) -- mpz_set_si(x.exp, -(opts.prec+20)) -- MPF_normalize(x, opts) -- --cdef MPF_set_ln2(MPF *x, MPopts opts): -- """ -- Set x = ln(2). -- """ -- x.special = S_NORMAL -- mpz_set_ln2(x.man, (opts.prec+20)) -- mpz_set_si(x.exp, -(opts.prec+20)) -- MPF_normalize(x, opts) -- -- --def exp_fixed(Integer x, int prec, ln2=None): -- """ -- Return a fixed-point approximation of exp(x) where x is a fixed-point -- number. -- -- EXAMPLES:: -- -- sage: from sage.libs.mpmath.ext_impl import exp_fixed -- sage: y = exp_fixed(1<<53, 53) -- sage: float(y) / 2^53 -- 2.718281828459044 -- """ -- cdef Integer v -- cdef mpz_t n, t -- cdef long nn -- mpz_init(n) -- mpz_init(t) -- if ln2 is None: -- mpz_set_ln2(t, prec) -- mpz_fdiv_qr(n, t, x.value, t) -- else: -- mpz_fdiv_qr(n, t, x.value, (ln2).value) -- nn = mpz_get_si(n) -- v = PY_NEW(Integer) -- cy_exp_basecase(v.value, t, prec) -- if nn >= 0: -- mpz_mul_2exp(v.value, v.value, nn) -- else: -- mpz_fdiv_q_2exp(v.value, v.value, -nn) -- mpz_clear(t) -- mpz_clear(n) -- return v -- -- --def cos_sin_fixed(Integer x, int prec, pi2=None): -- """ -- Return fixed-point approximations of cos(x), sin(x) where -- x is a fixed-point number. -- -- EXAMPLES:: -- -- sage: from sage.libs.mpmath.ext_impl import cos_sin_fixed -- sage: c, s = cos_sin_fixed(1<<53, 53) -- sage: float(c) / 2^53 -- 0.5403023058681398 -- sage: float(s) / 2^53 -- 0.8414709848078965 -- """ -- cdef Integer cv, sv -- cdef mpfr_t t, cf, sf -- mpfr_init2(t, mpz_bitcount(x.value)+2) -- mpfr_init2(cf, prec) -- mpfr_init2(sf, prec) -- mpfr_set_z(t, x.value, MPFR_RNDN) -- mpfr_div_2exp(t, t, prec, MPFR_RNDN) -- mpfr_sin_cos(sf, cf, t, MPFR_RNDN) -- mpfr_mul_2exp(cf, cf, prec, MPFR_RNDN) -- mpfr_mul_2exp(sf, sf, prec, MPFR_RNDN) -- cv = PY_NEW(Integer) -- sv = PY_NEW(Integer) -- mpfr_get_z(cv.value, cf, MPFR_RNDN) -- mpfr_get_z(sv.value, sf, MPFR_RNDN) -- mpfr_clear(t) -- mpfr_clear(cf) -- mpfr_clear(sf) -- return cv, sv -- -- --DEF MAX_LOG_INT_CACHE = 2000 -- --cdef mpz_t log_int_cache[MAX_LOG_INT_CACHE+1] --cdef long log_int_cache_prec[MAX_LOG_INT_CACHE+1] --cdef bint log_int_cache_initialized = 0 -- --cdef mpz_log_int(mpz_t v, mpz_t n, int prec): -- """ -- Set v = log(n) where n is an integer and v is a fixed-point number -- with the specified precision. -- """ -- cdef mpfr_t f -- mpfr_init2(f, prec+15) -- mpfr_set_z(f, n, MPFR_RNDN) -- mpfr_log(f, f, MPFR_RNDN) -- mpfr_mul_2exp(f, f, prec, MPFR_RNDN) -- mpfr_get_z(v, f, MPFR_RNDN) -- mpfr_clear(f) -- -- --def log_int_fixed(n, long prec, ln2=None): -- """ -- Return fixed-point approximation of log(n). -- -- EXAMPLES:: -- -- sage: from sage.libs.mpmath.ext_impl import log_int_fixed -- sage: float(log_int_fixed(5, 53)) / 2^53 -- 1.6094379124341003 -- sage: float(log_int_fixed(5, 53)) / 2^53 # exercise cache -- 1.6094379124341003 -- """ -- global log_int_cache_initialized -- cdef Integer t -- cdef int i -- t = PY_NEW(Integer) -- mpz_set_integer(t.value, n) -- if mpz_sgn(t.value) <= 0: -- mpz_set_ui(t.value, 0) -- elif mpz_cmp_ui(t.value, MAX_LOG_INT_CACHE) <= 0: -- if not log_int_cache_initialized: -- for i in range(MAX_LOG_INT_CACHE+1): -- mpz_init(log_int_cache[i]) -- log_int_cache_prec[i] = 0 -- log_int_cache_initialized = 1 -- i = mpz_get_si(t.value) -- if log_int_cache_prec[i] < prec: -- mpz_log_int(log_int_cache[i], t.value, prec+64) -- log_int_cache_prec[i] = prec+64 -- mpz_tdiv_q_2exp(t.value, log_int_cache[i], log_int_cache_prec[i]-prec) -- -- else: -- mpz_log_int(t.value, t.value, prec) -- return t -- -- --cdef _MPF_cos_python(MPF *c, MPF *x, MPopts opts): -- """ -- Compute c = cos(x) by calling the mpmath.libmp Python implementation. -- """ -- from mpmath.libmp.libelefun import mpf_cos_sin -- ct = mpf_cos_sin(MPF_to_tuple(x), opts.prec, -- rndmode_to_python(opts.rounding), 1, False) -- MPF_set_tuple(c, ct) -- --cdef _MPF_sin_python(MPF *s, MPF *x, MPopts opts): -- """ -- Compute s = sin(x) by calling the mpmath.libmp Python implementation. -- """ -- from mpmath.libmp.libelefun import mpf_cos_sin -- st = mpf_cos_sin(MPF_to_tuple(x), opts.prec, -- rndmode_to_python(opts.rounding), 2, False) -- MPF_set_tuple(s, st) -- -- --cdef MPF_cos(MPF *c, MPF *x, MPopts opts): -- """ -- Set c = cos(x) -- """ -- cdef mpfr_t cf, xf -- cdef bint overflow -- if x.special != S_NORMAL: -- if x.special == S_ZERO: -- MPF_set_one(c) -- else: -- MPF_set_nan(c) -- return -- mpfr_init(xf) -- mpfr_init2(cf, opts.prec) -- overflow = MPF_get_mpfr_overflow(xf, x) -- if overflow or opts.rounding == ROUND_U: -- _MPF_cos_python(c, x, opts) -- else: -- mpfr_cos(cf, xf, rndmode_to_mpfr(opts.rounding)) -- MPF_set_mpfr(c, cf, opts) -- mpfr_clear(xf) -- mpfr_clear(cf) -- --cdef MPF_sin(MPF *s, MPF *x, MPopts opts): -- """ -- Set s = sin(x) -- """ -- cdef mpfr_t sf, xf -- cdef bint overflow -- if x.special != S_NORMAL: -- if x.special == S_ZERO: -- MPF_set_zero(s) -- else: -- MPF_set_nan(s) -- return -- mpfr_init(xf) -- mpfr_init2(sf, opts.prec) -- overflow = MPF_get_mpfr_overflow(xf, x) -- if overflow or opts.rounding == ROUND_U: -- _MPF_sin_python(s, x, opts) -- else: -- mpfr_sin(sf, xf, rndmode_to_mpfr(opts.rounding)) -- MPF_set_mpfr(s, sf, opts) -- mpfr_clear(xf) -- mpfr_clear(sf) -- --cdef MPF_cos_sin(MPF *c, MPF *s, MPF *x, MPopts opts): -- """ -- Set c = cos(x), s = sin(x) -- """ -- cdef mpfr_t cf, sf, xf -- cdef bint overflow -- if x.special != S_NORMAL: -- if x.special == S_ZERO: -- MPF_set_one(c) -- MPF_set_zero(s) -- else: -- MPF_set_nan(c) -- MPF_set_nan(s) -- return -- mpfr_init(xf) -- mpfr_init2(sf, opts.prec) -- mpfr_init2(cf, opts.prec) -- overflow = MPF_get_mpfr_overflow(xf, x) -- if overflow or opts.rounding == ROUND_U: -- _MPF_cos_python(c, x, opts) -- _MPF_sin_python(s, x, opts) -- else: -- mpfr_sin_cos(sf, cf, xf, rndmode_to_mpfr(opts.rounding)) -- MPF_set_mpfr(s, sf, opts) -- MPF_set_mpfr(c, cf, opts) -- mpfr_clear(xf) -- mpfr_clear(cf) -- mpfr_clear(sf) -- -- --cdef MPF_complex_exp(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts): -- """ -- Set re+im*i = exp(a+bi) -- """ -- cdef MPF mag, c, s -- cdef MPopts wopts -- if a.special == S_ZERO: -- MPF_cos_sin(re, im, b, opts) -- return -- if b.special == S_ZERO: -- MPF_exp(re, a, opts) -- MPF_set_zero(im) -- return -- MPF_init(&mag) -- MPF_init(&c) -- MPF_init(&s) -- wopts = opts -- wopts.prec += 4 -- MPF_exp(&mag, a, wopts) -- MPF_cos_sin(&c, &s, b, wopts) -- MPF_mul(re, &mag, &c, opts) -- MPF_mul(im, &mag, &s, opts) -- MPF_clear(&mag) -- MPF_clear(&c) -- MPF_clear(&s) -- --cdef int MPF_pow(MPF *z, MPF *x, MPF *y, MPopts opts) except -1: -- """ -- Set z = x^y for real x and y and returns 0 if the result is real-valued. -- If the result is complex, does nothing and returns 1. -- """ -- cdef MPopts wopts -- cdef mpz_t t -- cdef MPF w -- cdef int xsign, ysign -- cdef mpz_t tm -- -- # Integer exponentiation, if reasonable -- if y.special == S_NORMAL and mpz_sgn(y.exp) >= 0: -- mpz_init(tm) -- # check if size is reasonable -- mpz_add_ui(tm, y.exp, mpz_bitcount(y.man)) -- mpz_abs(tm, tm) -- if mpz_cmp_ui(tm, 10000) < 0: -- # man * 2^exp -- mpz_mul_2exp(tm, y.man, mpz_get_ui(y.exp)) -- MPF_pow_int(z, x, tm, opts) -- mpz_clear(tm) -- return 0 -- mpz_clear(tm) -- -- # x ^ 0 -- if y.special == S_ZERO: -- if x.special == S_NORMAL or x.special == S_ZERO: -- MPF_set_one(z) -- else: -- MPF_set_nan(z) -- return 0 -- -- xsign = MPF_sgn(x) -- ysign = MPF_sgn(y) -- -- if xsign < 0: -- return 1 -- -- # Square root or integer power thereof -- if y.special == S_NORMAL and mpz_cmp_si(y.exp, -1) == 0: -- # x^(1/2) -- if mpz_cmp_ui(y.man, 1) == 0: -- MPF_sqrt(z, x, opts) -- return 0 -- # x^(-1/2) -- if mpz_cmp_si(y.man, -1) == 0: -- wopts = opts -- wopts.prec += 10 -- wopts.rounding = reciprocal_rnd(wopts.rounding) -- MPF_sqrt(z, x, wopts) -- MPF_div(z, &MPF_C_1, z, opts) -- return 0 -- # x^(n/2) -- wopts = opts -- wopts.prec += 10 -- if mpz_sgn(y.man) < 0: -- wopts.rounding = reciprocal_rnd(wopts.rounding) -- mpz_init_set(t, y.man) -- MPF_sqrt(z, x, wopts) -- MPF_pow_int(z, z, t, opts) -- mpz_clear(t) -- return 0 -- -- if x.special != S_NORMAL or y.special != S_NORMAL: -- if x.special == S_NAN or y.special == S_NAN: -- MPF_set_nan(z) -- return 0 -- if y.special == S_ZERO: -- if x.special == S_NORMAL or x.special == S_ZERO: -- MPF_set_one(z) -- else: -- MPF_set_nan(z) -- return 0 -- if x.special == S_ZERO and y.special == S_NORMAL: -- if mpz_sgn(y.man) > 0: -- MPF_set_zero(z) -- return 0 -- -- wopts = opts -- wopts.prec += 10 -- MPF_init(&w) -- MPF_log(&w, x, wopts) -- MPF_mul(&w, &w, y, opts_exact) -- MPF_exp(z, &w, opts) -- MPF_clear(&w) -- return 0 -- --cdef MPF_complex_square(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts): -- """ -- Set re+im*i = (a+bi)^2 = a^2-b^2, 2ab*i. -- """ -- cdef MPF t, u -- MPF_init(&t) -- MPF_init(&u) -- MPF_mul(&t,a,a,opts_exact) -- MPF_mul(&u,b,b,opts_exact) -- MPF_sub(re, &t, &u, opts) -- MPF_mul(im, a, b, opts) -- if im.special == S_NORMAL: -- mpz_add_ui(im.exp, im.exp, 1) -- MPF_clear(&t) -- MPF_clear(&u) -- -- --cdef MPF_complex_reciprocal(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts): -- """ -- Set re+im*i = 1/(a+bi), i.e. compute the reciprocal of -- a complex number. -- """ -- cdef MPopts wopts -- cdef MPF t, u, m -- wopts = opts -- wopts.prec += 10 -- MPF_init(&t) -- MPF_init(&u) -- MPF_init(&m) -- MPF_mul(&t, a, a,opts_exact) -- MPF_mul(&u, b, b,opts_exact) -- MPF_add(&m, &t, &u,wopts) -- MPF_div(&t, a, &m, opts) -- MPF_div(&u, b, &m, opts) -- MPF_set(re, &t) -- MPF_neg(im, &u) -- MPF_clear(&t) -- MPF_clear(&u) -- MPF_clear(&m) -- -- --cdef MPF_complex_pow_int(MPF *zre, MPF *zim, MPF *xre, MPF *xim, mpz_t n, MPopts opts): -- """ -- Set zre+zim*i = (xre+xim) ^ n, i.e. raise a complex number to an integer power. -- """ -- cdef MPopts wopts -- cdef long m -- -- if xim.special == S_ZERO: -- MPF_pow_int(zre, xre, n, opts) -- MPF_set_zero(zim) -- return -- -- if xre.special == S_ZERO: -- # n % 4 -- m = mpz_get_si(n) % 4 -- if m == 0: -- MPF_pow_int(zre, xim, n, opts) -- MPF_set_zero(zim) -- return -- if m == 1: -- MPF_set_zero(zre) -- MPF_pow_int(zim, xim, n, opts) -- return -- if m == 2: -- MPF_pow_int(zre, xim, n, opts) -- MPF_neg(zre, zre) -- MPF_set_zero(zim) -- return -- if m == 3: -- MPF_set_zero(zre) -- MPF_pow_int(zim, xim, n, opts) -- MPF_neg(zim, zim) -- return -- -- if mpz_reasonable_shift(n): -- m = mpz_get_si(n) -- if m == 0: -- MPF_set_one(zre) -- MPF_set_zero(zim) -- return -- if m == 1: -- MPF_pos(zre, xre, opts) -- MPF_pos(zim, xim, opts) -- return -- if m == 2: -- MPF_complex_square(zre, zim, xre, xim, opts) -- return -- if m == -1: -- MPF_complex_reciprocal(zre, zim, xre, xim, opts) -- return -- if m == -2: -- wopts = opts -- wopts.prec += 10 -- MPF_complex_square(zre, zim, xre, xim, wopts) -- MPF_complex_reciprocal(zre, zim, zre, zim, opts) -- return -- -- xret = MPF_to_tuple(xre) -- ximt = MPF_to_tuple(xim) -- from mpmath.libmp import mpc_pow_int -- vr, vi = mpc_pow_int((xret, ximt), mpzi(n), -- opts.prec, rndmode_to_python(opts.rounding)) -- MPF_set_tuple(zre, vr) -- MPF_set_tuple(zim, vi) -- -- --cdef MPF_complex_pow_re(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *y, MPopts opts): -- """ -- Set (zre+zim*i) = (xre+xim*i) ^ y, i.e. raise a complex number -- to a real power. -- """ -- -- cdef mpz_t tm -- cdef MPopts wopts -- -- if y.special == S_ZERO: -- if xre.special == S_NORMAL and xim.special == S_NORMAL: -- # x ^ 0 -- MPF_set_one(zre) -- MPF_set_zero(zim) -- return -- -- wopts = opts -- wopts.prec += 10 -- -- if y.special == S_NORMAL: -- # Integer -- if mpz_cmp_ui(y.exp, 0) >= 0 and mpz_reasonable_shift(y.exp): -- mpz_init_set(tm, y.man) -- mpz_mul_2exp(tm, tm, mpz_get_ui(y.exp)) -- MPF_complex_pow_int(zre, zim, xre, xim, tm, opts) -- mpz_clear(tm) -- return -- # x ^ (n/2) -- if mpz_cmp_si(y.exp, -1) == 0: -- mpz_init_set(tm, y.man) -- MPF_complex_sqrt(zre, zim, xre, xim, wopts) -- MPF_complex_pow_int(zre, zim, zre, zim, tm, opts) -- mpz_clear(tm) -- return -- -- xret = MPF_to_tuple(xre) -- ximt = MPF_to_tuple(xim) -- yret = MPF_to_tuple(y) -- from mpmath.libmp import mpc_pow_mpf -- vr, vi = mpc_pow_mpf((xret, ximt), yret, -- opts.prec, rndmode_to_python(opts.rounding)) -- MPF_set_tuple(zre, vr) -- MPF_set_tuple(zim, vi) -- -- --cdef MPF_complex_pow(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *yre, MPF *yim, MPopts opts): -- """ -- Set (zre + zim*i) = (xre+xim*i) ^ (yre+yim*i). -- """ -- if yim.special == S_ZERO: -- MPF_complex_pow_re(zre, zim, xre, xim, yre, opts) -- return -- xret = MPF_to_tuple(xre) -- ximt = MPF_to_tuple(xim) -- yret = MPF_to_tuple(yre) -- yimt = MPF_to_tuple(yim) -- from mpmath.libmp import mpc_pow -- vr, vi = mpc_pow((xret, ximt), (yret, yimt), -- opts.prec, rndmode_to_python(opts.rounding)) -- MPF_set_tuple(zre, vr) -- MPF_set_tuple(zim, vi) -- -- --cdef mpz_set_tuple_fixed(mpz_t x, tuple t, long prec): -- """ -- Set the integer x to a fixed-point number with specified precision -- and the value of t = (sign,man,exp,bc). Truncating division is used -- if the value cannot be represented exactly. -- """ -- cdef long offset -- sign, man, exp, bc = t -- mpz_set_integer(x, man) -- if sign: -- mpz_neg(x, x) -- offset = exp + prec -- if offset >= 0: -- mpz_mul_2exp(x, x, offset) -- else: -- mpz_tdiv_q_2exp(x, x, -offset) -- --cdef mpz_set_complex_tuple_fixed(mpz_t x, mpz_t y, tuple t, long prec): -- """ -- Set the integers (x,y) to fixed-point numbers with the values of -- the mpf pair t = ((xsign,xman,xexp,xbc), (ysign,yman,yexp,ybc)). -- """ -- mpz_set_tuple_fixed(x, t[0], prec) -- mpz_set_tuple_fixed(y, t[1], prec) -- --cdef MPF_set_fixed(MPF *x, mpz_t man, long wp, long prec, int rnd): -- """ -- Set value of an MPF given a fixed-point mantissa of precision wp, -- rounding to the given precision and rounding mode. -- """ -- cdef MPopts opts -- opts.prec = prec -- opts.rounding = rnd -- x.special = S_NORMAL -- mpz_set(x.man, man) -- mpz_set_si(x.exp, -wp) -- MPF_normalize(x, opts) -- --# TODO: we should allocate these dynamically --DEF MAX_PARAMS = 128 --cdef mpz_t AINT[MAX_PARAMS] --cdef mpz_t BINT[MAX_PARAMS] --cdef mpz_t AP[MAX_PARAMS] --cdef mpz_t AQ[MAX_PARAMS] --cdef mpz_t BP[MAX_PARAMS] --cdef mpz_t BQ[MAX_PARAMS] --cdef mpz_t AREAL[MAX_PARAMS] --cdef mpz_t BREAL[MAX_PARAMS] --cdef mpz_t ACRE[MAX_PARAMS] --cdef mpz_t ACIM[MAX_PARAMS] --cdef mpz_t BCRE[MAX_PARAMS] --cdef mpz_t BCIM[MAX_PARAMS] -- -- --cdef MPF_hypsum(MPF *a, MPF *b, int p, int q, param_types, str ztype, coeffs, z, -- long prec, long wp, long epsshift, dict magnitude_check, kwargs): -- """ -- Evaluates a+bi = pFq(..., z) by summing the hypergeometric -- series in fixed-point arithmetic. -- -- This basically a Cython version of -- mpmath.libmp.libhyper.make_hyp_summator(). It should produce identical -- results (the calculations are exactly the same, and the same rounding -- is used for divisions). -- -- This function is not intended to be called directly; it is wrapped -- by the hypsum_internal function in ext_main.pyx. -- """ -- cdef long i, j, k, n, p_mag, cancellable_real, MAX, magn -- cdef int have_complex_param, have_complex_arg, have_complex -- -- cdef mpz_t SRE, SIM, PRE, PIM, ZRE, ZIM, TRE, TIM, URE, UIM, MUL, DIV, HIGH, LOW, one -- # Count number of parameters -- cdef int aint, bint, arat, brat, areal, breal, acomplex, bcomplex -- cdef int have_multiplier -- -- if p >= MAX_PARAMS or q >= MAX_PARAMS: -- raise NotImplementedError("too many hypergeometric function parameters") -- -- have_complex_param = 'C' in param_types -- have_complex_arg = ztype == 'C' -- have_complex = have_complex_param or have_complex_arg -- -- mpz_init(one) -- mpz_init(SRE) -- mpz_init(SIM) -- mpz_init(PRE) -- mpz_init(PIM) -- mpz_init(ZRE) -- mpz_init(ZIM) -- mpz_init(MUL) -- mpz_init(DIV) -- mpz_init(HIGH) -- mpz_init(LOW) -- mpz_init(TRE) -- mpz_init(TIM) -- mpz_init(URE) -- mpz_init(UIM) -- -- aint = bint = arat = brat = areal = breal = acomplex = bcomplex = 0 -- -- MAX = kwargs.get('maxterms', wp*100) -- mpz_set_ui(HIGH, 1) -- mpz_mul_2exp(HIGH, HIGH, epsshift) -- mpz_neg(LOW, HIGH) -- -- mpz_set_ui(one, 1) -- mpz_mul_2exp(one, one, wp) -- mpz_set(SRE, one) -- mpz_set(PRE, one) -- -- # Copy input data to mpzs -- if have_complex_arg: -- mpz_set_complex_tuple_fixed(ZRE, ZIM, z, wp) -- else: -- mpz_set_tuple_fixed(ZRE, z, wp) -- for i in range(p): -- sig_check() -- if param_types[i] == 'Z': -- mpz_init(AINT[aint]) -- mpz_set_integer(AINT[aint], coeffs[i]) -- aint += 1 -- elif param_types[i] == 'Q': -- mpz_init(AP[arat]) -- mpz_init(AQ[arat]) -- __p, __q = coeffs[i]._mpq_ -- mpz_set_integer(AP[arat], __p) -- mpz_set_integer(AQ[arat], __q) -- arat += 1 -- elif param_types[i] == 'R': -- mpz_init(AREAL[areal]) -- mpz_set_tuple_fixed(AREAL[areal], coeffs[i]._mpf_, wp) -- areal += 1 -- elif param_types[i] == 'C': -- mpz_init(ACRE[acomplex]) -- mpz_init(ACIM[acomplex]) -- mpz_set_complex_tuple_fixed(ACRE[acomplex], ACIM[acomplex], coeffs[i]._mpc_, wp) -- acomplex += 1 -- else: -- raise ValueError -- for i in range(p,p+q): -- sig_check() -- if param_types[i] == 'Z': -- mpz_init(BINT[bint]) -- mpz_set_integer(BINT[bint], coeffs[i]) -- bint += 1 -- elif param_types[i] == 'Q': -- mpz_init(BP[brat]) -- mpz_init(BQ[brat]) -- __p, __q = coeffs[i]._mpq_ -- mpz_set_integer(BP[brat], __p) -- mpz_set_integer(BQ[brat], __q) -- brat += 1 -- elif param_types[i] == 'R': -- mpz_init(BREAL[breal]) -- mpz_set_tuple_fixed(BREAL[breal], coeffs[i]._mpf_, wp) -- breal += 1 -- elif param_types[i] == 'C': -- mpz_init(BCRE[bcomplex]) -- mpz_init(BCIM[bcomplex]) -- mpz_set_complex_tuple_fixed(BCRE[bcomplex], BCIM[bcomplex], coeffs[i]._mpc_, wp) -- bcomplex += 1 -- else: -- raise ValueError -- -- cancellable_real = min(areal, breal) -- -- # Main loop -- for n in range(1, 10**8): -- -- if n in magnitude_check: -- p_mag = mpz_bitcount(PRE) -- if have_complex: -- p_mag = max(p_mag, mpz_bitcount(PIM)) -- magnitude_check[n] = wp - p_mag -- -- # Update rational part of product -- mpz_set_ui(MUL, 1) -- mpz_set_ui(DIV, n) -- -- for i in range(aint): mpz_mul(MUL, MUL, AINT[i]) -- for i in range(arat): mpz_mul(MUL, MUL, AP[i]) -- for i in range(brat): mpz_mul(MUL, MUL, BQ[i]) -- for i in range(bint): mpz_mul(DIV, DIV, BINT[i]) -- for i in range(brat): mpz_mul(DIV, DIV, BP[i]) -- for i in range(arat): mpz_mul(DIV, DIV, AQ[i]) -- -- # Check for singular terms -- if mpz_sgn(DIV) == 0: -- if mpz_sgn(MUL) == 0: -- break -- raise ZeroDivisionError -- -- # Multiply real factors -- for k in range(cancellable_real): -- sig_check() -- mpz_mul(PRE, PRE, AREAL[k]) -- mpz_fdiv_q(PRE, PRE, BREAL[k]) -- for k in range(cancellable_real, areal): -- sig_check() -- mpz_mul(PRE, PRE, AREAL[k]) -- mpz_fdiv_q_2exp(PRE, PRE, wp) -- for k in range(cancellable_real, breal): -- sig_check() -- mpz_mul_2exp(PRE, PRE, wp) -- mpz_fdiv_q(PRE, PRE, BREAL[k]) -- if have_complex: -- for k in range(cancellable_real): -- sig_check() -- mpz_mul(PIM, PIM, AREAL[k]) -- mpz_fdiv_q(PIM, PIM, BREAL[k]) -- for k in range(cancellable_real, areal): -- sig_check() -- mpz_mul(PIM, PIM, AREAL[k]) -- mpz_fdiv_q_2exp(PIM, PIM, wp) -- for k in range(cancellable_real, breal): -- sig_check() -- mpz_mul_2exp(PIM, PIM, wp) -- mpz_fdiv_q(PIM, PIM, BREAL[k]) -- -- # Update product -- if have_complex: -- if have_complex_arg: -- # PRE = ((mul*(PRE*ZRE-PIM*ZIM))//div)>>wp -- # PIM = ((mul*(PIM*ZRE+PRE*ZIM))//div)>>wp -- mpz_mul(TRE, PRE, ZRE) -- mpz_submul(TRE, PIM, ZIM) -- mpz_mul(TRE, TRE, MUL) -- -- mpz_mul(TIM, PIM, ZRE) -- mpz_addmul(TIM, PRE, ZIM) -- mpz_mul(TIM, TIM, MUL) -- -- mpz_fdiv_q(PRE, TRE, DIV) -- mpz_fdiv_q_2exp(PRE, PRE, wp) -- -- mpz_fdiv_q(PIM, TIM, DIV) -- mpz_fdiv_q_2exp(PIM, PIM, wp) -- else: -- mpz_mul(PRE, PRE, MUL) -- mpz_mul(PRE, PRE, ZRE) -- mpz_fdiv_q_2exp(PRE, PRE, wp) -- mpz_fdiv_q(PRE, PRE, DIV) -- -- mpz_mul(PIM, PIM, MUL) -- mpz_mul(PIM, PIM, ZRE) -- mpz_fdiv_q_2exp(PIM, PIM, wp) -- mpz_fdiv_q(PIM, PIM, DIV) -- -- for i in range(acomplex): -- sig_check() -- mpz_mul(TRE, PRE, ACRE[i]) -- mpz_submul(TRE, PIM, ACIM[i]) -- mpz_mul(TIM, PIM, ACRE[i]) -- mpz_addmul(TIM, PRE, ACIM[i]) -- mpz_fdiv_q_2exp(PRE, TRE, wp) -- mpz_fdiv_q_2exp(PIM, TIM, wp) -- -- for i in range(bcomplex): -- sig_check() -- mpz_mul(URE, BCRE[i], BCRE[i]) -- mpz_addmul(URE, BCIM[i], BCIM[i]) -- mpz_mul(TRE, PRE, BCRE[i]) -- mpz_addmul(TRE, PIM, BCIM[i]) -- mpz_mul(TIM, PIM, BCRE[i]) -- mpz_submul(TIM, PRE, BCIM[i]) -- mpz_mul_2exp(PRE, TRE, wp) -- mpz_fdiv_q(PRE, PRE, URE) -- mpz_mul_2exp(PIM, TIM, wp) -- mpz_fdiv_q(PIM, PIM, URE) -- else: -- mpz_mul(PRE, PRE, MUL) -- mpz_mul(PRE, PRE, ZRE) -- mpz_fdiv_q_2exp(PRE, PRE, wp) -- mpz_fdiv_q(PRE, PRE, DIV) -- -- # Add product to sum -- if have_complex: -- mpz_add(SRE, SRE, PRE) -- mpz_add(SIM, SIM, PIM) -- if mpz_cmpabs(PRE, HIGH) < 0 and mpz_cmpabs(PIM, HIGH) < 0: -- break -- else: -- mpz_add(SRE, SRE, PRE) -- if mpz_cmpabs(PRE, HIGH) < 0: -- break -- -- if n > MAX: -- from mpmath.libmp import NoConvergence -- raise NoConvergence('Hypergeometric series converges too slowly. Try increasing maxterms.') -- -- # +1 all parameters for next iteration -- for i in range(aint): mpz_add_ui(AINT[i], AINT[i], 1) -- for i in range(bint): mpz_add_ui(BINT[i], BINT[i], 1) -- for i in range(arat): mpz_add(AP[i], AP[i], AQ[i]) -- for i in range(brat): mpz_add(BP[i], BP[i], BQ[i]) -- for i in range(areal): mpz_add(AREAL[i], AREAL[i], one) -- for i in range(breal): mpz_add(BREAL[i], BREAL[i], one) -- for i in range(acomplex): mpz_add(ACRE[i], ACRE[i], one) -- for i in range(bcomplex): mpz_add(BCRE[i], BCRE[i], one) -- -- # Done -- if have_complex: -- MPF_set_fixed(a, SRE, wp, prec, ROUND_N) -- MPF_set_fixed(b, SIM, wp, prec, ROUND_N) -- if mpz_sgn(SRE): -- if mpz_sgn(SIM): -- magn = max(mpz_get_si(a.exp) + mpz_bitcount(a.man), -- mpz_get_si(b.exp) + mpz_bitcount(b.man)) -- else: -- magn = mpz_get_si(a.exp) + mpz_bitcount(a.man) -- elif mpz_sgn(SIM): -- magn = mpz_get_si(b.exp) + mpz_bitcount(b.man) -- else: -- magn = -wp -- else: -- MPF_set_fixed(a, SRE, wp, prec, ROUND_N) -- if mpz_sgn(SRE): -- magn = mpz_get_si(a.exp) + mpz_bitcount(a.man) -- else: -- magn = -wp -- -- mpz_clear(one) -- mpz_clear(SRE) -- mpz_clear(SIM) -- mpz_clear(PRE) -- mpz_clear(PIM) -- mpz_clear(ZRE) -- mpz_clear(ZIM) -- mpz_clear(MUL) -- mpz_clear(DIV) -- mpz_clear(HIGH) -- mpz_clear(LOW) -- mpz_clear(TRE) -- mpz_clear(TIM) -- mpz_clear(URE) -- mpz_clear(UIM) -- -- for i in range(aint): mpz_clear(AINT[i]) -- for i in range(bint): mpz_clear(BINT[i]) -- for i in range(arat): -- mpz_clear(AP[i]) -- mpz_clear(AQ[i]) -- for i in range(brat): -- mpz_clear(BP[i]) -- mpz_clear(BQ[i]) -- for i in range(areal): mpz_clear(AREAL[i]) -- for i in range(breal): mpz_clear(BREAL[i]) -- for i in range(acomplex): -- mpz_clear(ACRE[i]) -- mpz_clear(ACIM[i]) -- for i in range(bcomplex): -- mpz_clear(BCRE[i]) -- mpz_clear(BCIM[i]) -- -- return have_complex, magn -diff --git a/src/sage/libs/mpmath/ext_libmp.pyx b/src/sage/libs/mpmath/ext_libmp.pyx -deleted file mode 100644 -index 487a12d45bc..00000000000 ---- a/src/sage/libs/mpmath/ext_libmp.pyx -+++ /dev/null -@@ -1,230 +0,0 @@ --""" --Faster versions of some key functions in mpmath.libmp --""" --from sage.libs.mpmath.ext_impl cimport * --from sage.libs.gmp.all cimport * -- --# the next line is used by mpmath --from sage.libs.mpmath.ext_impl import exp_fixed, cos_sin_fixed, log_int_fixed -- --# Note: not thread-safe --cdef MPF tmp1 --cdef MPF tmp2 --MPF_init(&tmp1) --MPF_init(&tmp2) -- -- --def mpf_add(tuple x, tuple y, int prec=0, str rnd='d'): -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- MPF_set_tuple(&tmp2, y) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_add(&tmp1, &tmp1, &tmp2, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_sub(tuple x, tuple y, int prec=0, str rnd='d'): -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- MPF_set_tuple(&tmp2, y) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_sub(&tmp1, &tmp1, &tmp2, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_mul(tuple x, tuple y, int prec=0, str rnd='d'): -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- MPF_set_tuple(&tmp2, y) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_mul(&tmp1, &tmp1, &tmp2, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_div(tuple x, tuple y, int prec, str rnd='d'): -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- MPF_set_tuple(&tmp2, y) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_div(&tmp1, &tmp1, &tmp2, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_sqrt(tuple x, int prec, str rnd='d'): -- """ -- Compute sqrt(x) with mpf value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpf_sqrt, from_float, to_float -- sage: x = from_float(2) -- sage: y = mpf_sqrt(x, 53, 'n') -- sage: to_float(y) -- 1.4142135623730951 -- """ -- if x[0]: -- import mpmath.libmp as libmp -- raise libmp.ComplexResult("square root of a negative number") -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_sqrt(&tmp1, &tmp1, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_log(tuple x, int prec, str rnd='d'): -- """ -- Compute log(x) with mpf value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpf_log, from_float, to_float -- sage: x = from_float(2) -- sage: y = mpf_log(x, 53, 'n') -- sage: to_float(y) -- 0.6931471805599453 -- """ -- if x[0]: -- import mpmath.libmp as libmp -- raise libmp.ComplexResult("logarithm of a negative number") -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_log(&tmp1, &tmp1, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_exp(tuple x, int prec, str rnd='d'): -- """ -- Compute exp(x) with mpf value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpf_exp, from_float, to_float -- sage: x = from_float(2) -- sage: z = mpf_exp(x, 53, 'n') -- sage: to_float(z) -- 7.38905609893065 -- """ -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_exp(&tmp1, &tmp1, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_cos(tuple x, int prec, str rnd='d'): -- """ -- Compute cos(x) with mpf value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpf_cos, from_float, to_float -- sage: x = from_float(1) -- sage: y = mpf_cos(x, 53, 'n') -- sage: to_float(y) -- 0.5403023058681398 -- """ -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_cos(&tmp1, &tmp1, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpf_sin(tuple x, int prec, str rnd='d'): -- """ -- Compute sin(x) with mpf value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpf_sin, from_float, to_float -- sage: x = from_float(1) -- sage: y = mpf_sin(x, 53, 'n') -- sage: to_float(y) -- 0.8414709848078965 -- """ -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_sin(&tmp1, &tmp1, opts) -- return MPF_to_tuple(&tmp1) -- -- --def mpc_sqrt(tuple z, int prec, str rnd='d'): -- """ -- Compute sqrt(z) with mpc value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpc_sqrt, from_float, to_float -- sage: z = from_float(-2), from_float(0) -- sage: re, im = mpc_sqrt(z, 53, 'n') -- sage: to_float(re), to_float(im) -- (0.0, 1.4142135623730951) -- """ -- cdef tuple a, b -- cdef MPopts opts -- a, b = z -- MPF_set_tuple(&tmp1, a) -- MPF_set_tuple(&tmp2, b) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_complex_sqrt(&tmp1, &tmp2, &tmp1, &tmp2, opts) -- return MPF_to_tuple(&tmp1), MPF_to_tuple(&tmp2) -- -- --def mpc_exp(tuple z, int prec, str rnd='d'): -- """ -- Compute exp(z) with mpc value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpc_exp, from_float, to_float -- sage: z = from_float(0), from_float(1) -- sage: re, im = mpc_exp(z, 53, 'n') -- sage: to_float(re), to_float(im) -- (0.5403023058681398, 0.8414709848078965) -- """ -- cdef tuple a, b -- cdef MPopts opts -- a, b = z -- MPF_set_tuple(&tmp1, a) -- MPF_set_tuple(&tmp2, b) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- MPF_complex_exp(&tmp1, &tmp2, &tmp1, &tmp2, opts) -- return MPF_to_tuple(&tmp1), MPF_to_tuple(&tmp2) -- -- --def mpf_pow(tuple x, tuple y, int prec, str rnd='d'): -- """ -- Compute x ^ y with mpf value tuples. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import mpf_pow, from_float, to_float -- sage: x = from_float(2) -- sage: y = from_float(3) -- sage: z = mpf_pow(x, y, 53, 'n') -- sage: to_float(z) -- 8.0 -- """ -- cdef MPopts opts -- MPF_set_tuple(&tmp1, x) -- MPF_set_tuple(&tmp2, y) -- opts.rounding = rndmode_from_python(rnd) -- opts.prec = prec -- if MPF_pow(&tmp1, &tmp1, &tmp2, opts): -- import mpmath.libmp as libmp -- raise libmp.ComplexResult("negative number raised to a fractional power") -- return MPF_to_tuple(&tmp1) -diff --git a/src/sage/libs/mpmath/ext_main.pxd b/src/sage/libs/mpmath/ext_main.pxd -deleted file mode 100644 -index 8a3bf740b0e..00000000000 ---- a/src/sage/libs/mpmath/ext_main.pxd -+++ /dev/null -@@ -1 +0,0 @@ --from sage.libs.mpmath.ext_impl cimport * -diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx -deleted file mode 100644 -index f8c4420f2f4..00000000000 ---- a/src/sage/libs/mpmath/ext_main.pyx -+++ /dev/null -@@ -1,2638 +0,0 @@ --""" --mpmath floating-point numbers -- --Implements mpf and mpc types, with binary operations and support --for interaction with other types. Also implements the main --context class, and related utilities. --""" -- --#***************************************************************************** --# 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 2 of the License, or --# (at your option) any later version. --# http://www.gnu.org/licenses/ --#***************************************************************************** -- --from cpython.long cimport * --from cpython.float cimport * --from cpython.complex cimport * --from cpython.number cimport * -- --from cysignals.signals cimport sig_check -- --from sage.ext.stdsage cimport PY_NEW -- --from sage.libs.gmp.all cimport * --from sage.rings.integer cimport Integer -- --DEF ROUND_N = 0 --DEF ROUND_F = 1 --DEF ROUND_C = 2 --DEF ROUND_D = 3 --DEF ROUND_U = 4 --DEF S_NORMAL = 0 --DEF S_ZERO = 1 --DEF S_NZERO = 2 --DEF S_INF = 3 --DEF S_NINF = 4 --DEF S_NAN = 5 -- --from sage.libs.mpmath.ext_impl cimport * -- --import mpmath.rational as rationallib --import mpmath.libmp as libmp --import mpmath.function_docs as function_docs --from mpmath.libmp import to_str --from mpmath.libmp import repr_dps, prec_to_dps, dps_to_prec -- --DEF OP_ADD = 0 --DEF OP_SUB = 1 --DEF OP_MUL = 2 --DEF OP_DIV = 3 --DEF OP_POW = 4 --DEF OP_MOD = 5 --DEF OP_RICHCMP = 6 --DEF OP_EQ = (OP_RICHCMP + 2) --DEF OP_NE = (OP_RICHCMP + 3) --DEF OP_LT = (OP_RICHCMP + 0) --DEF OP_GT = (OP_RICHCMP + 4) --DEF OP_LE = (OP_RICHCMP + 1) --DEF OP_GE = (OP_RICHCMP + 5) -- --cdef MPopts opts_exact --cdef MPopts opts_double_precision --cdef MPopts opts_mini_prec -- --opts_exact.prec = 0 --opts_exact.rounding = ROUND_N --opts_double_precision.prec = 53 --opts_double_precision.rounding = ROUND_N --opts_mini_prec.prec = 5 --opts_mini_prec.rounding = ROUND_D -- --cdef MPF MPF_C_0 --cdef MPF MPF_C_1 --cdef MPF MPF_C_2 -- --MPF_init(&MPF_C_0) --MPF_set_zero(&MPF_C_0) --MPF_init(&MPF_C_1) --MPF_set_si(&MPF_C_1, 1) --MPF_init(&MPF_C_2) --MPF_set_si(&MPF_C_2, 2) -- --# Temporaries used for operands in binary operations --cdef mpz_t tmp_mpz --mpz_init(tmp_mpz) -- --cdef MPF tmp1 --cdef MPF tmp2 --cdef MPF tmp_opx_re --cdef MPF tmp_opx_im --cdef MPF tmp_opy_re --cdef MPF tmp_opy_im -- --MPF_init(&tmp1) --MPF_init(&tmp2) --MPF_init(&tmp_opx_re) --MPF_init(&tmp_opx_im) --MPF_init(&tmp_opy_re) --MPF_init(&tmp_opy_im) -- --cdef class Context --cdef class mpnumber --cdef class mpf_base --cdef class mpf --cdef class mpc --cdef class constant --cdef class wrapped_libmp_function --cdef class wrapped_specfun -- --cdef __isint(MPF *v): -- return v.special == S_ZERO or (v.special == S_NORMAL and mpz_sgn(v.exp) >= 0) -- --cdef int MPF_set_any(MPF *re, MPF *im, x, MPopts opts, bint str_tuple_ok) except -1: -- """ -- Set re + im*i = x, where x is any Python number. -- -- Returns 0 if unable to coerce x; 1 if x is real and re was set; -- 2 if x is complex and both re and im were set. -- -- If str_tuple_ok=True, strings and tuples are accepted and converted -- (useful for parsing arguments, but not for arithmetic operands). -- """ -- if isinstance(x, mpf): -- MPF_set(re, &(x).value) -- return 1 -- if isinstance(x, mpc): -- MPF_set(re, &(x).re) -- MPF_set(im, &(x).im) -- return 2 -- if isinstance(x, (int, Integer)): -- MPF_set_int(re, x) -- return 1 -- if isinstance(x, float): -- MPF_set_double(re, x) -- return 1 -- if isinstance(x, complex): -- MPF_set_double(re, x.real) -- MPF_set_double(im, x.imag) -- return 2 -- if isinstance(x, constant): -- MPF_set_tuple(re, x.func(opts.prec, rndmode_to_python(opts.rounding))) -- return 1 -- if hasattr(x, "_mpf_"): -- MPF_set_tuple(re, x._mpf_) -- return 1 -- if hasattr(x, "_mpc_"): -- r, i = x._mpc_ -- MPF_set_tuple(re, r) -- MPF_set_tuple(im, i) -- return 2 -- if hasattr(x, "_mpmath_"): -- return MPF_set_any(re, im, x._mpmath_(opts.prec, -- rndmode_to_python(opts.rounding)), opts, False) -- if isinstance(x, rationallib.mpq): -- p, q = x._mpq_ -- MPF_set_int(re, p) -- MPF_set_int(im, q) -- MPF_div(re, re, im, opts) -- #MPF_set_tuple(re, libmp.from_rational(p, q, opts.prec, -- # rndmode_to_python(opts.rounding))) -- return 1 -- if hasattr(x, '_mpi_'): -- a, b = x._mpi_ -- if a == b: -- MPF_set_tuple(re, a) -- return 1 -- raise ValueError("can only create mpf from zero-width interval") -- if str_tuple_ok: -- if isinstance(x, tuple): -- if len(x) == 2: -- MPF_set_man_exp(re, x[0], x[1]) -- return 1 -- elif len(x) == 4: -- MPF_set_tuple(re, x) -- return 1 -- if isinstance(x, str): -- try: -- st = libmp.from_str(x, opts.prec, -- rndmode_to_python(opts.rounding)) -- except ValueError: -- return 0 -- MPF_set_tuple(re, st) -- return 1 -- return 0 -- --cdef binop(int op, x, y, MPopts opts): -- cdef int typx -- cdef int typy -- cdef MPF xre, xim, yre, yim -- cdef mpf rr -- cdef mpc rc -- cdef MPopts altopts -- -- if isinstance(x, mpf): -- xre = (x).value -- typx = 1 -- elif isinstance(x, mpc): -- xre = (x).re -- xim = (x).im -- typx = 2 -- else: -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, False) -- if typx == 0: -- return NotImplemented -- xre = tmp_opx_re -- xim = tmp_opx_im -- -- if isinstance(y, mpf): -- yre = (y).value -- typy = 1 -- elif isinstance(y, mpc): -- yre = (y).re -- yim = (y).im -- typy = 2 -- else: -- typy = MPF_set_any(&tmp_opy_re, &tmp_opy_im, y, opts, False) -- if typy == 0: -- return NotImplemented -- yre = tmp_opy_re -- yim = tmp_opy_im -- -- if op == OP_ADD: -- if typx == 1 and typy == 1: -- # Real result -- rr = mpf.__new__(mpf) -- MPF_add(&rr.value, &xre, &yre, opts) -- return rr -- else: -- # Complex result -- rc = mpc.__new__(mpc) -- MPF_add(&rc.re, &xre, &yre, opts) -- if typx == 1: -- MPF_set(&rc.im, &yim) -- #MPF_normalize(&rc.im, opts) -- elif typy == 1: -- MPF_set(&rc.im, &xim) -- #MPF_normalize(&rc.im, opts) -- else: -- MPF_add(&rc.im, &xim, &yim, opts) -- return rc -- -- elif op == OP_SUB: -- if typx == 1 and typy == 1: -- # Real result -- rr = mpf.__new__(mpf) -- MPF_sub(&rr.value, &xre, &yre, opts) -- return rr -- else: -- # Complex result -- rc = mpc.__new__(mpc) -- MPF_sub(&rc.re, &xre, &yre, opts) -- if typx == 1: -- MPF_neg(&rc.im, &yim) -- MPF_normalize(&rc.im, opts) -- elif typy == 1: -- MPF_set(&rc.im, &xim) -- MPF_normalize(&rc.im, opts) -- else: -- MPF_sub(&rc.im, &xim, &yim, opts) -- return rc -- -- elif op == OP_MUL: -- if typx == 1 and typy == 1: -- # Real result -- rr = mpf.__new__(mpf) -- MPF_mul(&rr.value, &xre, &yre, opts) -- return rr -- else: -- # Complex result -- rc = mpc.__new__(mpc) -- if typx == 1: -- MPF_mul(&rc.re, &yre, &xre, opts) -- MPF_mul(&rc.im, &yim, &xre, opts) -- elif typy == 1: -- MPF_mul(&rc.re, &xre, &yre, opts) -- MPF_mul(&rc.im, &xim, &yre, opts) -- else: -- # a*c - b*d -- MPF_mul(&rc.re, &xre, &yre, opts_exact) -- MPF_mul(&tmp1, &xim, &yim, opts_exact) -- MPF_sub(&rc.re, &rc.re, &tmp1, opts) -- # a*d + b*c -- MPF_mul(&rc.im, &xre, &yim, opts_exact) -- MPF_mul(&tmp1, &xim, &yre, opts_exact) -- MPF_add(&rc.im, &rc.im, &tmp1, opts) -- return rc -- -- elif op == OP_DIV: -- if typx == 1 and typy == 1: -- # Real result -- rr = mpf.__new__(mpf) -- MPF_div(&rr.value, &xre, &yre, opts) -- return rr -- else: -- rc = mpc.__new__(mpc) -- if typy == 1: -- MPF_div(&rc.re, &xre, &yre, opts) -- MPF_div(&rc.im, &xim, &yre, opts) -- else: -- if typx == 1: -- xim = MPF_C_0 -- altopts = opts -- altopts.prec += 10 -- # m = c*c + d*d -- MPF_mul(&tmp1, &yre, &yre, opts_exact) -- MPF_mul(&tmp2, &yim, &yim, opts_exact) -- MPF_add(&tmp1, &tmp1, &tmp2, altopts) -- # (a*c+b*d)/m -- MPF_mul(&rc.re, &xre, &yre, opts_exact) -- MPF_mul(&tmp2, &xim, &yim, opts_exact) -- MPF_add(&rc.re, &rc.re, &tmp2, altopts) -- MPF_div(&rc.re, &rc.re, &tmp1, opts) -- # (b*c-a*d)/m -- MPF_mul(&rc.im, &xim, &yre, opts_exact) -- MPF_mul(&tmp2, &xre, &yim, opts_exact) -- MPF_sub(&rc.im, &rc.im, &tmp2, altopts) -- MPF_div(&rc.im, &rc.im, &tmp1, opts) -- return rc -- -- elif op == OP_POW: -- if typx == 1 and typy == 1: -- rr = mpf.__new__(mpf) -- if not MPF_pow(&rr.value, &xre, &yre, opts): -- return rr -- if typx == 1: xim = MPF_C_0 -- if typy == 1: yim = MPF_C_0 -- rc = mpc.__new__(mpc) -- MPF_complex_pow(&rc.re, &rc.im, &xre, &xim, &yre, &yim, opts) -- return rc -- -- elif op == OP_MOD: -- if typx != 1 or typx != 1: -- raise TypeError("mod for complex numbers") -- xret = MPF_to_tuple(&xre) -- yret = MPF_to_tuple(&yre) -- v = libmp.mpf_mod(xret, yret, opts.prec, rndmode_to_python(opts.rounding)) -- rr = mpf.__new__(mpf) -- MPF_set_tuple(&rr.value, v) -- return rr -- -- elif op == OP_EQ: -- if typx == 1 and typy == 1: -- return MPF_eq(&xre, &yre) -- if typx == 1: -- return MPF_eq(&xre, &yre) and MPF_eq(&yim, &MPF_C_0) -- if typy == 1: -- return MPF_eq(&xre, &yre) and MPF_eq(&xim, &MPF_C_0) -- return MPF_eq(&xre, &yre) and MPF_eq(&xim, &yim) -- -- elif op == OP_NE: -- if typx == 1 and typy == 1: -- return MPF_ne(&xre, &yre) -- if typx == 1: -- return MPF_ne(&xre, &yre) or MPF_ne(&yim, &MPF_C_0) -- if typy == 1: -- return MPF_ne(&xre, &yre) or MPF_ne(&xim, &MPF_C_0) -- return MPF_ne(&xre, &yre) or MPF_ne(&xim, &yim) -- -- elif op == OP_LT: -- if typx != 1 or typy != 1: -- raise ValueError("cannot compare complex numbers") -- return MPF_lt(&xre, &yre) -- -- elif op == OP_GT: -- if typx != 1 or typy != 1: -- raise ValueError("cannot compare complex numbers") -- return MPF_gt(&xre, &yre) -- -- elif op == OP_LE: -- if typx != 1 or typy != 1: -- raise ValueError("cannot compare complex numbers") -- return MPF_le(&xre, &yre) -- -- elif op == OP_GE: -- if typx != 1 or typy != 1: -- raise ValueError("cannot compare complex numbers") -- return MPF_ge(&xre, &yre) -- -- return NotImplemented -- -- --cdef MPopts global_opts -- --global_context = None -- --cdef class Context: -- cdef public mpf, mpc, constant # , def_mp_function -- cdef public trap_complex -- cdef public pretty -- -- def __cinit__(ctx): -- """ -- At present, only a single global context should exist:: -- -- sage: from mpmath import mp -- sage: type(mp) -- -- """ -- global global_opts, global_context -- global_opts = opts_double_precision -- global_context = ctx -- ctx.mpf = mpf -- ctx.mpc = mpc -- ctx.constant = constant -- #ctx.def_mp_function = def_mp_function -- ctx._mpq = rationallib.mpq -- -- def default(ctx): -- """ -- Set defaults. -- -- TESTS:: -- -- sage: import mpmath -- sage: mpmath.mp.prec = 100 -- sage: mpmath.mp.default() -- sage: mpmath.mp.prec -- 53 -- """ -- global global_opts -- global_opts = opts_double_precision -- ctx.trap_complex = False -- ctx.pretty = False -- -- def _get_prec(ctx): -- """ -- Controls the working precision in bits:: -- -- sage: from mpmath import mp -- sage: mp.prec = 100 -- sage: mp.prec -- 100 -- sage: mp.dps -- 29 -- sage: mp.prec = 53 -- """ -- return global_opts.prec -- -- def _set_prec(ctx, prec): -- """ -- Controls the working precision in bits:: -- -- sage: from mpmath import mp -- sage: mp.prec = 100 -- sage: mp.prec -- 100 -- sage: mp.dps -- 29 -- sage: mp.prec = 53 -- """ -- global_opts.prec = prec -- -- def _set_dps(ctx, n): -- """ -- Controls the working precision in decimal digits:: -- -- sage: from mpmath import mp -- sage: mp.dps = 100 -- sage: mp.prec -- 336 -- sage: mp.dps -- 100 -- sage: mp.prec = 53 -- """ -- global_opts.prec = dps_to_prec(int(n)) -- -- def _get_dps(ctx): -- """ -- Controls the working precision in decimal digits:: -- -- sage: from mpmath import mp -- sage: mp.dps = 100 -- sage: mp.prec -- 336 -- sage: mp.dps -- 100 -- sage: mp.prec = 53 -- """ -- return prec_to_dps(global_opts.prec) -- -- dps = property(_get_dps, _set_dps, doc=_get_dps.__doc__) -- prec = property(_get_prec, _set_prec, doc=_get_dps.__doc__) -- _dps = property(_get_dps, _set_dps, doc=_get_dps.__doc__) -- _prec = property(_get_prec, _set_prec, doc=_get_dps.__doc__) -- -- def _get_prec_rounding(ctx): -- """ -- Return the precision and rounding mode:: -- -- sage: from mpmath import mp -- sage: mp._get_prec_rounding() -- (53, 'n') -- """ -- return global_opts.prec, rndmode_to_python(global_opts.rounding) -- -- _prec_rounding = property(_get_prec_rounding) -- -- cpdef mpf make_mpf(ctx, tuple v): -- """ -- Create an mpf from tuple data:: -- -- sage: import mpmath -- sage: float(mpmath.mp.make_mpf((0,1,-1,1))) -- 0.5 -- """ -- cdef mpf x -- x = mpf.__new__(mpf) -- MPF_set_tuple(&x.value, v) -- return x -- -- cpdef mpc make_mpc(ctx, tuple v): -- """ -- Create an mpc from tuple data:: -- -- sage: import mpmath -- sage: complex(mpmath.mp.make_mpc(((0,1,-1,1), (1,1,-2,1)))) -- (0.5-0.25j) -- """ -- cdef mpc x -- x = mpc.__new__(mpc) -- MPF_set_tuple(&x.re, v[0]) -- MPF_set_tuple(&x.im, v[1]) -- return x -- -- def convert(ctx, x, strings=True): -- """ -- Convert *x* to an ``mpf``, ``mpc`` or ``mpi``. If *x* is of type ``mpf``, -- ``mpc``, ``int``, ``float``, ``complex``, the conversion -- will be performed losslessly. -- -- If *x* is a string, the result will be rounded to the present -- working precision. Strings representing fractions or complex -- numbers are permitted. -- -- TESTS:: -- -- sage: from mpmath import mp, convert -- sage: mp.dps = 15; mp.pretty = False -- sage: convert(3.5) -- mpf('3.5') -- sage: convert('2.1') -- mpf('2.1000000000000001') -- sage: convert('3/4') -- mpf('0.75') -- sage: convert('2+3j') -- mpc(real='2.0', imag='3.0') -- """ -- cdef mpf rr -- cdef mpc rc -- if isinstance(x, mpnumber): -- return x -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, strings) -- if typx == 1: -- rr = mpf.__new__(mpf) -- MPF_set(&rr.value, &tmp_opx_re) -- return rr -- if typx == 2: -- rc = mpc.__new__(mpc) -- MPF_set(&rc.re, &tmp_opx_re) -- MPF_set(&rc.im, &tmp_opx_im) -- return rc -- return ctx._convert_fallback(x, strings) -- -- def isnan(ctx, x): -- """ -- For an ``mpf`` *x*, determines whether *x* is not-a-number (nan). -- -- TESTS:: -- -- sage: from mpmath import isnan, nan -- sage: isnan(nan), isnan(3) -- (True, False) -- """ -- cdef int s, t, typ -- if isinstance(x, mpf): -- return (x).value.special == S_NAN -- if isinstance(x, mpc): -- s = (x).re.special -- t = (x).im.special -- return s == S_NAN or t == S_NAN -- if isinstance(x, (int, Integer, rationallib.mpq)): -- return False -- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0) -- if typ == 1: -- s = tmp_opx_re.special -- return s == S_NAN -- if typ == 2: -- s = tmp_opx_re.special -- t = tmp_opx_im.special -- return s == S_NAN or t == S_NAN -- raise TypeError("isnan() needs a number as input") -- -- def isinf(ctx, x): -- """ -- Return *True* if the absolute value of *x* is infinite; -- otherwise return *False*. -- -- TESTS:: -- -- sage: from mpmath import isinf, inf, mpc -- sage: isinf(inf) -- True -- sage: isinf(-inf) -- True -- sage: isinf(3) -- False -- sage: isinf(3+4j) -- False -- sage: isinf(mpc(3,inf)) -- True -- sage: isinf(mpc(inf,3)) -- True -- """ -- cdef int s, t, typ -- if isinstance(x, mpf): -- s = (x).value.special -- return s == S_INF or s == S_NINF -- if isinstance(x, mpc): -- s = (x).re.special -- t = (x).im.special -- return s == S_INF or s == S_NINF or t == S_INF or t == S_NINF -- if isinstance(x, (int, Integer, rationallib.mpq)): -- return False -- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0) -- if typ == 1: -- s = tmp_opx_re.special -- return s == S_INF or s == S_NINF -- if typ == 2: -- s = tmp_opx_re.special -- t = tmp_opx_im.special -- return s == S_INF or s == S_NINF or t == S_INF or t == S_NINF -- raise TypeError("isinf() needs a number as input") -- -- def isnormal(ctx, x): -- """ -- Determine whether *x* is "normal" in the sense of floating-point -- representation; that is, return *False* if *x* is zero, an -- infinity or NaN; otherwise return *True*. By extension, a -- complex number *x* is considered "normal" if its magnitude is -- normal. -- -- TESTS:: -- -- sage: from mpmath import isnormal, inf, nan, mpc -- sage: isnormal(3) -- True -- sage: isnormal(0) -- False -- sage: isnormal(inf); isnormal(-inf); isnormal(nan) -- False -- False -- False -- sage: isnormal(0+0j) -- False -- sage: isnormal(0+3j) -- True -- sage: isnormal(mpc(2,nan)) -- False -- """ -- # TODO: optimize this -- if hasattr(x, "_mpf_"): -- return bool(x._mpf_[1]) -- if hasattr(x, "_mpc_"): -- re, im = x._mpc_ -- re_normal = bool(re[1]) -- im_normal = bool(im[1]) -- if re == libmp.fzero: return im_normal -- if im == libmp.fzero: return re_normal -- return re_normal and im_normal -- if isinstance(x, (int, Integer, rationallib.mpq)): -- return bool(x) -- x = ctx.convert(x) -- if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'): -- return ctx.isnormal(x) -- raise TypeError("isnormal() needs a number as input") -- -- def isint(ctx, x, gaussian=False): -- """ -- Return *True* if *x* is integer-valued; otherwise return -- *False*. -- -- TESTS:: -- -- sage: from mpmath import isint, mpf, inf -- sage: isint(3) -- True -- sage: isint(mpf(3)) -- True -- sage: isint(3.2) -- False -- sage: isint(inf) -- False -- -- Optionally, Gaussian integers can be checked for:: -- -- sage: isint(3+0j) -- True -- sage: isint(3+2j) -- False -- sage: isint(3+2j, gaussian=True) -- True -- """ -- cdef MPF v -- cdef MPF w -- cdef int typ -- if isinstance(x, (int, Integer)): -- return True -- if isinstance(x, mpf): -- v = (x).value -- return __isint(&v) -- if isinstance(x, mpc): -- v = (x).re -- w = (x).im -- if gaussian: -- return __isint(&v) and __isint(&w) -- return (w.special == S_ZERO) and __isint(&v) -- if isinstance(x, rationallib.mpq): -- p, q = x._mpq_ -- return not (p % q) -- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0) -- if typ == 1: -- return __isint(&tmp_opx_re) -- if typ == 2: -- v = tmp_opx_re -- w = tmp_opx_im -- if gaussian: -- return __isint(&v) and __isint(&w) -- return (w.special == S_ZERO) and __isint(&v) -- raise TypeError("isint() needs a number as input") -- -- def fsum(ctx, terms, bint absolute=False, bint squared=False): -- """ -- Calculate a sum containing a finite number of terms (for infinite -- series, see :func:`nsum`). The terms will be converted to -- mpmath numbers. For len(terms) > 2, this function is generally -- faster and produces more accurate results than the builtin -- Python function :func:`sum`. -- -- With ``squared=True`` each term is squared, and with ``absolute=True`` -- the absolute value of each term is used. -- -- TESTS:: -- -- sage: from mpmath import mp, fsum -- sage: mp.dps = 15; mp.pretty = False -- sage: fsum([1, 2, 0.5, 7]) -- mpf('10.5') -- -- Check that the regression from `mpmath/issues/723 `__ -- has been fixed:: -- -- sage: from mpmath import * -- sage: mp.dps=16 -- sage: zeta(-0.01 + 1000j) -- mpc(real='-8.9714595...', imag='8.7321793...') -- """ -- cdef MPF sre, sim, tre, tim, tmp -- cdef mpf rr -- cdef mpc rc -- cdef MPopts workopts -- cdef int styp, ttyp -- workopts = global_opts -- workopts.prec = workopts.prec * 2 + 50 -- workopts.rounding = ROUND_D -- unknown = global_context.zero -- try: -- sig_check() -- MPF_init(&sre) -- MPF_init(&sim) -- MPF_init(&tre) -- MPF_init(&tim) -- MPF_init(&tmp) -- styp = 1 -- for term in terms: -- ttyp = MPF_set_any(&tre, &tim, term, workopts, 0) -- if ttyp == 0: -- if absolute: term = ctx.absmax(term) -- if squared: term = term**2 -- unknown += term -- continue -- if absolute: -- if squared: -- if ttyp == 1: -- MPF_mul(&tre, &tre, &tre, opts_exact) -- MPF_add(&sre, &sre, &tre, workopts) -- elif ttyp == 2: -- # |(a+bi)^2| = a^2+b^2 -- MPF_mul(&tre, &tre, &tre, opts_exact) -- MPF_add(&sre, &sre, &tre, workopts) -- MPF_mul(&tim, &tim, &tim, opts_exact) -- MPF_add(&sre, &sre, &tim, workopts) -- else: -- if ttyp == 1: -- MPF_abs(&tre, &tre) -- MPF_add(&sre, &sre, &tre, workopts) -- elif ttyp == 2: -- # |a+bi| = sqrt(a^2+b^2) -- MPF_mul(&tre, &tre, &tre, opts_exact) -- MPF_mul(&tim, &tim, &tim, opts_exact) -- MPF_add(&tre, &tre, &tim, workopts) -- MPF_sqrt(&tre, &tre, workopts) -- MPF_add(&sre, &sre, &tre, workopts) -- elif squared: -- if ttyp == 1: -- MPF_mul(&tre, &tre, &tre, opts_exact) -- MPF_add(&sre, &sre, &tre, workopts) -- elif ttyp == 2: -- # (a+bi)^2 = a^2-b^2 + 2i*ab -- MPF_mul(&tmp, &tre, &tim, opts_exact) -- MPF_mul(&tmp, &tmp, &MPF_C_2, opts_exact) -- MPF_add(&sim, &sim, &tmp, workopts) -- MPF_mul(&tre, &tre, &tre, opts_exact) -- MPF_add(&sre, &sre, &tre, workopts) -- MPF_mul(&tim, &tim, &tim, opts_exact) -- MPF_sub(&sre, &sre, &tim, workopts) -- styp = 2 -- else: -- if ttyp == 1: -- MPF_add(&sre, &sre, &tre, workopts) -- elif ttyp == 2: -- MPF_add(&sre, &sre, &tre, workopts) -- MPF_add(&sim, &sim, &tim, workopts) -- styp = 2 -- MPF_clear(&tre) -- MPF_clear(&tim) -- if styp == 1: -- rr = mpf.__new__(mpf) -- MPF_set(&rr.value, &sre) -- MPF_clear(&sre) -- MPF_clear(&sim) -- MPF_normalize(&rr.value, global_opts) -- if unknown is not global_context.zero: -- return ctx._stupid_add(rr, unknown) -- return rr -- elif styp == 2: -- rc = mpc.__new__(mpc) -- MPF_set(&rc.re, &sre) -- MPF_set(&rc.im, &sim) -- MPF_clear(&sre) -- MPF_clear(&sim) -- MPF_normalize(&rc.re, global_opts) -- MPF_normalize(&rc.im, global_opts) -- if unknown is not global_context.zero: -- return ctx._stupid_add(rc, unknown) -- return rc -- else: -- MPF_clear(&sre) -- MPF_clear(&sim) -- return +unknown -- except KeyboardInterrupt: -- raise KeyboardInterrupt('Ctrl-C pressed while running fsum') -- -- def fdot(ctx, A, B=None, bint conjugate=False): -- r""" -- Compute the dot product of the iterables `A` and `B`. -- -- .. MATH:: -- -- \sum_{k=0} A_k B_k. -- -- Alternatively, :func:`fdot` accepts a single iterable of pairs. -- In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent. -- -- The elements are automatically converted to mpmath numbers. -- -- TESTS:: -- -- sage: from mpmath import mp, fdot -- sage: mp.dps = 15; mp.pretty = False -- sage: A = [2, 1.5r, 3] -- sage: B = [1, -1, 2] -- sage: fdot(A, B) -- mpf('6.5') -- sage: list(zip(A, B)) -- [(2, 1), (1.5, -1), (3, 2)] -- sage: fdot(_) -- mpf('6.5') -- """ -- if B: -- A = zip(A, B) -- cdef MPF sre, sim, tre, tim, ure, uim, tmp -- cdef mpf rr -- cdef mpc rc -- cdef MPopts workopts -- cdef int styp, ttyp, utyp -- MPF_init(&sre) -- MPF_init(&sim) -- MPF_init(&tre) -- MPF_init(&tim) -- MPF_init(&ure) -- MPF_init(&uim) -- MPF_init(&tmp) -- workopts = global_opts -- workopts.prec = workopts.prec * 2 + 50 -- workopts.rounding = ROUND_D -- unknown = global_context.zero -- styp = 1 -- for a, b in A: -- ttyp = MPF_set_any(&tre, &tim, a, workopts, 0) -- utyp = MPF_set_any(&ure, &uim, b, workopts, 0) -- if utyp == 2 and conjugate: -- MPF_neg(&uim, &uim) -- if ttyp == 0 or utyp == 0: -- if conjugate: -- b = b.conj() -- unknown += a * b -- continue -- styp = max(styp, ttyp) -- styp = max(styp, utyp) -- if ttyp == 1: -- if utyp == 1: -- MPF_mul(&tre, &tre, &ure, opts_exact) -- MPF_add(&sre, &sre, &tre, workopts) -- elif utyp == 2: -- MPF_mul(&ure, &ure, &tre, opts_exact) -- MPF_mul(&uim, &uim, &tre, opts_exact) -- MPF_add(&sre, &sre, &ure, workopts) -- MPF_add(&sim, &sim, &uim, workopts) -- styp = 2 -- elif ttyp == 2: -- styp = 2 -- if utyp == 1: -- MPF_mul(&tre, &tre, &ure, opts_exact) -- MPF_mul(&tim, &tim, &ure, opts_exact) -- MPF_add(&sre, &sre, &tre, workopts) -- MPF_add(&sim, &sim, &tim, workopts) -- elif utyp == 2: -- MPF_mul(&tmp, &tre, &ure, opts_exact) -- MPF_add(&sre, &sre, &tmp, workopts) -- MPF_mul(&tmp, &tim, &uim, opts_exact) -- MPF_sub(&sre, &sre, &tmp, workopts) -- MPF_mul(&tmp, &tim, &ure, opts_exact) -- MPF_add(&sim, &sim, &tmp, workopts) -- MPF_mul(&tmp, &tre, &uim, opts_exact) -- MPF_add(&sim, &sim, &tmp, workopts) -- MPF_clear(&tre) -- MPF_clear(&tim) -- MPF_clear(&ure) -- MPF_clear(&uim) -- MPF_clear(&tmp) -- if styp == 1: -- rr = mpf.__new__(mpf) -- MPF_set(&rr.value, &sre) -- MPF_clear(&sre) -- MPF_clear(&sim) -- MPF_normalize(&rr.value, global_opts) -- if unknown is not global_context.zero: -- return ctx._stupid_add(rr, unknown) -- return rr -- elif styp == 2: -- rc = mpc.__new__(mpc) -- MPF_set(&rc.re, &sre) -- MPF_set(&rc.im, &sim) -- MPF_clear(&sre) -- MPF_clear(&sim) -- MPF_normalize(&rc.re, global_opts) -- MPF_normalize(&rc.im, global_opts) -- if unknown is not global_context.zero: -- return ctx._stupid_add(rc, unknown) -- return rc -- else: -- MPF_clear(&sre) -- MPF_clear(&sim) -- return +unknown -- -- # Doing a+b directly doesn't work with mpi, presumably due to -- # Cython trying to be clever with the operation resolution -- cdef _stupid_add(ctx, a, b): -- return a + b -- -- def _convert_param(ctx, x): -- """ -- Internal function for parsing a hypergeometric function parameter. -- -- This returns (T, x) where T = 'Z', 'Q', 'R', 'C' depending on the -- type of the parameter, and with x converted to the canonical -- mpmath type. -- -- TESTS:: -- -- sage: from mpmath import mp -- sage: x, T = mp._convert_param(3) -- sage: (x, type(x).__name__, T) -- (3, 'int', 'Z') -- sage: x, T = mp._convert_param(2.5) -- sage: (x, type(x).__name__, T) -- (mpq(5,2), 'mpq', 'Q') -- sage: x, T = mp._convert_param(2.3) -- sage: (str(x), type(x).__name__, T) -- ('2.3', 'mpf', 'R') -- sage: x, T = mp._convert_param(2+3j) -- sage: (x, type(x).__name__, T) -- (mpc(real='2.0', imag='3.0'), 'mpc', 'C') -- sage: mp.pretty = False -- """ -- cdef MPF v -- cdef bint ismpf, ismpc -- if isinstance(x, (int, Integer)): -- return int(x), 'Z' -- if isinstance(x, tuple): -- p, q = x -- p = int(p) -- q = int(q) -- if not p % q: -- return p // q, 'Z' -- return rationallib.mpq((p,q)), 'Q' -- if isinstance(x, str) and '/' in x: -- p, q = x.split('/') -- p = int(p) -- q = int(q) -- if not p % q: -- return p // q, 'Z' -- return rationallib.mpq((p,q)), 'Q' -- if isinstance(x, constant): -- return x, 'R' -- ismpf = isinstance(x, mpf) -- ismpc = isinstance(x, mpc) -- if not (ismpf or ismpc): -- x = global_context.convert(x) -- ismpf = isinstance(x, mpf) -- ismpc = isinstance(x, mpc) -- if not (ismpf or ismpc): -- return x, 'U' -- if ismpf: -- v = (x).value -- elif ismpc: -- if (x).im.special != S_ZERO: -- return x, 'C' -- x = (x).real -- v = (x).re -- # A real number -- if v.special == S_ZERO: -- return 0, 'Z' -- if v.special != S_NORMAL: -- return x, 'U' -- if mpz_sgn(v.exp) >= 0: -- return (mpzi(v.man) << mpzi(v.exp)), 'Z' -- if mpz_cmp_si(v.exp, -4) > 0: -- p = mpzi(v.man) -- q = 1 << (-mpzi(v.exp)) -- return rationallib.mpq((p,q)), 'Q' -- return x, 'R' -- -- def mag(ctx, x): -- """ -- Quick logarithmic magnitude estimate of a number. Returns an -- integer or infinity `m` such that `|x| <= 2^m`. It is not -- guaranteed that `m` is an optimal bound, but it will never -- be too large by more than 2 (and probably not more than 1). -- -- TESTS:: -- -- sage: from mpmath import * -- sage: mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2))) -- (4, 4, 4, 4) -- sage: mag(10j), mag(10+10j) -- (4, 5) -- sage: mag(0.01), int(ceil(log(0.01,2))) -- (-6, -6) -- sage: mag(0), mag(inf), mag(-inf), mag(nan) -- (mpf('-inf'), mpf('+inf'), mpf('+inf'), mpf('nan')) -- -- :: -- -- sage: class MyInt(int): -- ....: pass -- sage: class MyFloat(float): -- ....: pass -- sage: mag(MyInt(10)) -- 4 -- """ -- cdef int typ -- if isinstance(x, (int, Integer)): -- mpz_set_integer(tmp_opx_re.man, x) -- if mpz_sgn(tmp_opx_re.man) == 0: -- return global_context.ninf -- else: -- return mpz_sizeinbase(tmp_opx_re.man,2) -- if isinstance(x, rationallib.mpq): -- p, q = x._mpq_ -- mpz_set_integer(tmp_opx_re.man, int(p)) -- if mpz_sgn(tmp_opx_re.man) == 0: -- return global_context.ninf -- mpz_set_integer(tmp_opx_re.exp, int(q)) -- return 1 + mpz_sizeinbase(tmp_opx_re.man,2) + mpz_sizeinbase(tmp_opx_re.exp,2) -- typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, False) -- if typ == 1: -- if tmp_opx_re.special == S_ZERO: -- return global_context.ninf -- if tmp_opx_re.special == S_INF or tmp_opx_re.special == S_NINF: -- return global_context.inf -- if tmp_opx_re.special != S_NORMAL: -- return global_context.nan -- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2)) -- return mpzi(tmp_opx_re.exp) -- if typ == 2: -- if tmp_opx_re.special == S_NAN or tmp_opx_im.special == S_NAN: -- return global_context.nan -- if tmp_opx_re.special == S_INF or tmp_opx_im.special == S_NINF or \ -- tmp_opx_im.special == S_INF or tmp_opx_im.special == S_NINF: -- return global_context.inf -- if tmp_opx_re.special == S_ZERO: -- if tmp_opx_im.special == S_ZERO: -- return global_context.ninf -- else: -- mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, mpz_sizeinbase(tmp_opx_im.man, 2)) -- return mpzi(tmp_opx_im.exp) -- elif tmp_opx_im.special == S_ZERO: -- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2)) -- return mpzi(tmp_opx_re.exp) -- mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, mpz_sizeinbase(tmp_opx_im.man, 2)) -- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2)) -- if mpz_cmp(tmp_opx_re.exp, tmp_opx_im.exp) >= 0: -- mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, 1) -- return mpzi(tmp_opx_re.exp) -- else: -- mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, 1) -- return mpzi(tmp_opx_im.exp) -- raise TypeError("requires an mpf/mpc") -- -- def _wrap_libmp_function(ctx, mpf_f, mpc_f=None, mpi_f=None, doc=""): -- """ -- Create a high-level mpmath function from base functions working -- on mpf, mpc and mpi tuple data. -- -- TESTS:: -- -- sage: from mpmath import mp -- sage: mp.pretty = False -- sage: f = lambda x, prec, rnd: x -- sage: g = mp._wrap_libmp_function(f) -- sage: g(mp.mpf(2)) -- mpf('2.0') -- """ -- name = mpf_f.__name__[4:] -- doc = function_docs.__dict__.get(name, "Computes the %s of x" % doc) -- # workaround lack of closures in Cython -- f_cls = type(name, (wrapped_libmp_function,), {'__doc__':doc}) -- f = f_cls(mpf_f, mpc_f, mpi_f, doc) -- return f -- -- @classmethod -- def _wrap_specfun(cls, name, f, wrap): -- """ -- Add the given function as a method to the context object, -- optionally wrapping it to do automatic conversions and -- allocating a small number of guard bits to suppress -- typical roundoff error. -- -- TESTS:: -- -- sage: from mpmath import mp -- sage: mp._wrap_specfun("foo", lambda ctx, x: ctx.prec + x, True) -- sage: mp.pretty = False; mp.prec = 53 -- sage: mp.foo(5) # 53 + 10 guard bits + 5 -- mpf('68.0') -- """ -- doc = function_docs.__dict__.get(name, getattr(f, '__doc__', '')) -- if wrap: -- # workaround lack of closures in Cython -- f_wrapped_cls = type(name, (wrapped_specfun,), {'__doc__':doc}) -- f_wrapped = f_wrapped_cls(name, f) -- else: -- f_wrapped = f -- f_wrapped.__doc__ = doc -- setattr(cls, name, f_wrapped) -- -- cdef MPopts _fun_get_opts(ctx, kwargs) noexcept: -- """ -- Helper function that extracts precision and rounding information -- from kwargs, or returns the global working precision and rounding -- if no options are specified. -- """ -- cdef MPopts opts -- opts.prec = global_opts.prec -- opts.rounding = global_opts.rounding -- if kwargs: -- if 'prec' in kwargs: -- opts.prec = int(kwargs['prec']) -- if 'dps' in kwargs: -- opts.prec = libmp.dps_to_prec(int(kwargs['dps'])) -- if 'rounding' in kwargs: -- opts.rounding = rndmode_from_python(kwargs['rounding']) -- return opts -- -- def _sage_sqrt(ctx, x, **kwargs): -- """ -- Square root of an mpmath number x, using the Sage mpmath backend. -- -- TESTS:: -- -- sage: from mpmath import mp -- sage: mp.dps = 15 -- sage: print(mp.sqrt(2)) # indirect doctest -- 1.4142135623731 -- sage: print(mp.sqrt(-2)) -- (0.0 + 1.4142135623731j) -- sage: print(mp.sqrt(2+2j)) -- (1.55377397403004 + 0.643594252905583j) -- """ -- cdef MPopts opts -- cdef int typx -- cdef mpf rr -- cdef mpc rc -- cdef tuple rev, imv -- opts = ctx._fun_get_opts(kwargs) -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1) -- if typx == 1: -- rr = mpf.__new__(mpf) -- if MPF_sqrt(&rr.value, &tmp_opx_re, opts): -- rc = mpc.__new__(mpc) -- MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &MPF_C_0, opts) -- return rc -- return rr -- elif typx == 2: -- rc = mpc.__new__(mpc) -- MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) -- return rc -- else: -- raise NotImplementedError("unknown argument") -- -- def _sage_exp(ctx, x, **kwargs): -- """ -- Exponential function of an mpmath number x, using the Sage -- mpmath backend. -- -- EXAMPLES:: -- -- sage: from mpmath import mp -- sage: mp.dps = 15 -- sage: print(mp.exp(2)) # indirect doctest -- 7.38905609893065 -- sage: print(mp.exp(2+2j)) -- (-3.07493232063936 + 6.71884969742825j) -- """ -- cdef MPopts opts -- cdef int typx -- cdef mpf rr -- cdef mpc rc -- cdef tuple rev, imv -- opts = ctx._fun_get_opts(kwargs) -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1) -- if typx == 1: -- rr = mpf.__new__(mpf) -- MPF_exp(&rr.value, &tmp_opx_re, opts) -- return rr -- elif typx == 2: -- rc = mpc.__new__(mpc) -- MPF_complex_exp(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) -- return rc -- else: -- raise NotImplementedError("unknown argument") -- -- def _sage_cos(ctx, x, **kwargs): -- """ -- Cosine of an mpmath number x, using the Sage mpmath backend. -- -- EXAMPLES:: -- -- sage: from mpmath import mp -- sage: mp.dps = 15 -- sage: print(mp.cos(2)) # indirect doctest -- -0.416146836547142 -- sage: print(mp.cos(2+2j)) -- (-1.56562583531574 - 3.29789483631124j) -- """ -- cdef MPopts opts -- cdef int typx -- cdef mpf rr -- cdef mpc rc -- cdef tuple rev, imv -- opts = ctx._fun_get_opts(kwargs) -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) -- if typx == 1: -- rr = mpf.__new__(mpf) -- MPF_cos(&rr.value, &tmp_opx_re, opts) -- return rr -- elif typx == 2: -- rev = MPF_to_tuple(&tmp_opx_re) -- imv = MPF_to_tuple(&tmp_opx_im) -- cxu = libmp.mpc_cos((rev, imv), opts.prec, -- rndmode_to_python(opts.rounding)) -- rc = mpc.__new__(mpc) -- MPF_set_tuple(&rc.re, cxu[0]) -- MPF_set_tuple(&rc.im, cxu[1]) -- return rc -- else: -- raise NotImplementedError("unknown argument") -- -- def _sage_sin(ctx, x, **kwargs): -- """ -- Sine of an mpmath number x, using the Sage mpmath backend. -- -- EXAMPLES:: -- -- sage: from mpmath import mp -- sage: mp.dps = 15 -- sage: print(mp.sin(2)) # indirect doctest -- 0.909297426825682 -- sage: print(mp.sin(2+2j)) -- (3.42095486111701 - 1.50930648532362j) -- """ -- cdef MPopts opts -- cdef int typx -- cdef mpf rr -- cdef mpc rc -- cdef tuple rev, imv -- opts = ctx._fun_get_opts(kwargs) -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) -- if typx == 1: -- rr = mpf.__new__(mpf) -- MPF_sin(&rr.value, &tmp_opx_re, opts) -- return rr -- elif typx == 2: -- rev = MPF_to_tuple(&tmp_opx_re) -- imv = MPF_to_tuple(&tmp_opx_im) -- cxu = libmp.mpc_sin((rev, imv), opts.prec, -- rndmode_to_python(opts.rounding)) -- rc = mpc.__new__(mpc) -- MPF_set_tuple(&rc.re, cxu[0]) -- MPF_set_tuple(&rc.im, cxu[1]) -- return rc -- else: -- raise NotImplementedError("unknown argument") -- -- def _sage_ln(ctx, x, **kwargs): -- """ -- Natural logarithm of an mpmath number x, using the Sage mpmath backend. -- -- EXAMPLES:: -- -- sage: from mpmath import mp -- sage: print(mp.ln(2)) # indirect doctest -- 0.693147180559945 -- sage: print(mp.ln(-2)) -- (0.693147180559945 + 3.14159265358979j) -- sage: print(mp.ln(2+2j)) -- (1.03972077083992 + 0.785398163397448j) -- """ -- cdef MPopts opts -- cdef int typx -- cdef mpf rr -- cdef mpc rc -- cdef tuple rev, imv -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) -- prec = global_opts.prec -- rounding = rndmode_to_python(global_opts.rounding) -- opts.prec = global_opts.prec -- opts.rounding = global_opts.rounding -- if kwargs: -- if 'prec' in kwargs: opts.prec = int(kwargs['prec']) -- if 'dps' in kwargs: opts.prec = libmp.dps_to_prec(int(kwargs['dps'])) -- if 'rounding' in kwargs: opts.rounding = rndmode_from_python(kwargs['rounding']) -- if typx == 1: -- if MPF_sgn(&tmp_opx_re) < 0: -- rc = mpc.__new__(mpc) -- MPF_log(&rc.re, &tmp_opx_re, opts) -- MPF_set_pi(&rc.im, opts) -- return rc -- else: -- rr = mpf.__new__(mpf) -- MPF_log(&rr.value, &tmp_opx_re, opts) -- return rr -- elif typx == 2: -- rev = MPF_to_tuple(&tmp_opx_re) -- imv = MPF_to_tuple(&tmp_opx_im) -- cxu = libmp.mpc_log((rev, imv), opts.prec, rndmode_to_python(opts.rounding)) -- rc = mpc.__new__(mpc) -- MPF_set_tuple(&rc.re, cxu[0]) -- MPF_set_tuple(&rc.im, cxu[1]) -- return rc -- -- #rc = mpc.__new__(mpc) -- #MPF_complex_log(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) -- #return rc -- else: -- raise NotImplementedError("unknown argument") -- -- --cdef class wrapped_libmp_function: -- -- cdef public mpf_f, mpc_f, mpi_f, name, __name__, __doc__ -- -- def __init__(self, mpf_f, mpc_f=None, mpi_f=None, doc=""): -- """ -- Create a high-level mpmath function from base functions working -- on mpf, mpc and mpi tuple data. -- -- TESTS:: -- -- sage: from sage.libs.mpmath.ext_main import wrapped_libmp_function -- sage: from mpmath import mp -- sage: from mpmath.libmp import mpf_exp, mpf_sqrt -- sage: f = lambda x, prec, rnd: mpf_exp(mpf_sqrt(x, prec, rnd), prec, rnd) -- sage: g = wrapped_libmp_function(f) -- sage: g(mp.mpf(3)) -- mpf('5.6522336740340915') -- sage: mp.exp(mp.sqrt(3)) -- mpf('5.6522336740340915') -- sage: g(mp.mpf(3), prec=10) -- mpf('5.65625') -- sage: g(mp.mpf(3), prec=10, rounding='u') -- mpf('5.65625') -- sage: g(mp.mpf(3), prec=10, rounding='d') -- mpf('5.640625') -- """ -- self.mpf_f = mpf_f -- self.mpc_f = mpc_f -- self.mpi_f = mpi_f -- self.name = self.__name__ = mpf_f.__name__[4:] -- self.__doc__ = function_docs.__dict__.get(self.name, "Computes the %s of x" % doc) -- -- def __call__(self, x, **kwargs): -- """ -- A wrapped mpmath library function performs automatic -- conversions and uses the default working precision -- unless overridden:: -- -- sage: from mpmath import mp -- sage: mp.sinh(2) -- mpf('3.6268604078470186') -- sage: mp.sinh(2, prec=10) -- mpf('3.625') -- sage: mp.sinh(2, prec=10, rounding='d') -- mpf('3.625') -- sage: mp.sinh(2, prec=10, rounding='u') -- mpf('3.62890625') -- """ -- cdef int typx -- cdef tuple rev, imv, reu, cxu -- cdef mpf rr -- cdef mpc rc -- prec = global_opts.prec -- rounding = rndmode_to_python(global_opts.rounding) -- if kwargs: -- if 'prec' in kwargs: prec = int(kwargs['prec']) -- if 'dps' in kwargs: prec = libmp.dps_to_prec(int(kwargs['dps'])) -- if 'rounding' in kwargs: rounding = kwargs['rounding'] -- typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) -- if typx == 1: -- rev = MPF_to_tuple(&tmp_opx_re) -- try: -- reu = self.mpf_f(rev, prec, rounding) -- rr = mpf.__new__(mpf) -- MPF_set_tuple(&rr.value, reu) -- return rr -- except libmp.ComplexResult: -- if global_context.trap_complex: -- raise -- cxu = self.mpc_f((rev, libmp.fzero), prec, rounding) -- rc = mpc.__new__(mpc) -- MPF_set_tuple(&rc.re, cxu[0]) -- MPF_set_tuple(&rc.im, cxu[1]) -- return rc -- if typx == 2: -- rev = MPF_to_tuple(&tmp_opx_re) -- imv = MPF_to_tuple(&tmp_opx_im) -- cxu = self.mpc_f((rev, imv), prec, rounding) -- rc = mpc.__new__(mpc) -- MPF_set_tuple(&rc.re, cxu[0]) -- MPF_set_tuple(&rc.im, cxu[1]) -- return rc -- x = global_context.convert(x) -- if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): -- return self(x, **kwargs) -- #if hasattr(x, "_mpi_"): -- # if self.mpi_f: -- # return global_context.make_mpi(self.mpi_f(x._mpi_, prec)) -- raise NotImplementedError("%s of a %s" % (self.name, type(x))) -- -- --cdef class wrapped_specfun: -- cdef public f, name, __name__, __doc__ -- -- def __init__(self, name, f): -- """ -- Create an object holding a wrapped mpmath function -- along with metadata (name and documentation). -- -- TESTS:: -- -- sage: import mpmath -- sage: from sage.libs.mpmath.ext_main import wrapped_specfun -- sage: f = wrapped_specfun("f", lambda ctx, x: x) -- sage: f.name -- 'f' -- """ -- self.name = self.__name__ = name -- self.f = f -- self.__doc__ = function_docs.__dict__.get(name, "") -- -- def __call__(self, *args, **kwargs): -- """ -- Call wrapped mpmath function. Arguments are automatically converted -- to mpmath number, and the internal working precision is increased -- by a few bits to suppress typical rounding errors:: -- -- sage: from mpmath import mp -- sage: from sage.libs.mpmath.ext_main import wrapped_specfun -- sage: f = wrapped_specfun("f", lambda ctx, x: x + ctx.prec) -- sage: f("1") # 53 + 10 guard bits + 1 -- mpf('64.0') -- """ -- cdef int origprec -- args = [global_context.convert(a) for a in args] -- origprec = global_opts.prec -- global_opts.prec += 10 -- try: -- retval = self.f(global_context, *args, **kwargs) -- finally: -- global_opts.prec = origprec -- return +retval -- -- --cdef class mpnumber: -- -- def __richcmp__(self, other, int op): -- """ -- Comparison of mpmath numbers. Compatible numerical types -- are automatically converted to mpmath numbers:: -- -- sage: from mpmath import mpf, mpc -- sage: mpf(3) == mpc(3) -- True -- sage: mpf(3) == mpc(4) -- False -- sage: mpf(3) == float(3) -- True -- sage: mpf(3) < float(2.5) -- False -- sage: mpc(3) < mpc(4) -- Traceback (most recent call last): -- ... -- ValueError: cannot compare complex numbers -- """ -- return binop(OP_RICHCMP+op, self, other, global_opts) -- -- def __add__(self, other): -- """ -- Addition of mpmath numbers. Compatible numerical types -- are automatically converted to mpmath numbers:: -- -- sage: from mpmath import mpf, mpc -- sage: mpf(3) + mpc(3) -- mpc(real='6.0', imag='0.0') -- sage: float(4) + mpf(3) -- mpf('7.0') -- """ -- return binop(OP_ADD, self, other, global_opts) -- -- def __sub__(self, other): -- """ -- Subtraction of mpmath numbers. Compatible numerical types -- are automatically converted to mpmath numbers:: -- -- sage: from mpmath import mpf, mpc -- sage: mpf(5) - mpc(3) -- mpc(real='2.0', imag='0.0') -- sage: float(4) - mpf(3) -- mpf('1.0') -- """ -- return binop(OP_SUB, self, other, global_opts) -- -- def __mul__(self, other): -- """ -- Multiplication of mpmath numbers. Compatible numerical types -- are automatically converted to mpmath numbers:: -- -- sage: from mpmath import mpf, mpc -- sage: mpf(5) * mpc(3) -- mpc(real='15.0', imag='0.0') -- sage: float(4) * mpf(3) -- mpf('12.0') -- """ -- return binop(OP_MUL, self, other, global_opts) -- -- def __truediv__(self, other): -- """ -- Division of mpmath numbers. Compatible numerical types -- are automatically converted to mpmath numbers:: -- -- sage: from mpmath import mpf, mpc -- sage: mpf(10) / mpc(5) -- mpc(real='2.0', imag='0.0') -- sage: float(9) / mpf(3) -- mpf('3.0') -- """ -- return binop(OP_DIV, self, other, global_opts) -- -- def __mod__(self, other): -- """ -- Remainder of mpmath numbers. Compatible numerical types -- are automatically converted to mpmath numbers:: -- -- sage: from mpmath import mpf -- sage: mpf(12) % float(7) -- mpf('5.0') -- """ -- return binop(OP_MOD, self, other, global_opts) -- -- def __pow__(self, other, mod): -- """ -- Exponentiation of mpmath numbers. Compatible numerical types -- are automatically converted to mpmath numbers:: -- -- sage: from mpmath import mpf, mpc -- sage: mpf(10) ** mpc(3) -- mpc(real='1000.0', imag='0.0') -- sage: mpf(3) ** float(2) -- mpf('9.0') -- """ -- if mod is not None: -- raise ValueError("three-argument pow not supported") -- return binop(OP_POW, self, other, global_opts) -- -- def ae(s, t, rel_eps=None, abs_eps=None): -- """ -- Check if two numbers are approximately equal to within the specified -- tolerance (see mp.almosteq for documentation):: -- -- sage: from mpmath import mpf, mpc -- sage: mpf(3).ae(mpc(3,1e-10)) -- False -- sage: mpf(3).ae(mpc(3,1e-10), rel_eps=1e-5) -- True -- """ -- return global_context.almosteq(s, t, rel_eps, abs_eps) -- -- --cdef class mpf_base(mpnumber): -- -- # Shared methods for mpf, constant. However, somehow some methods -- # (hash?, __richcmp__?) are not inherited, so they have to -- # be defined multiple times. TODO: fix this. -- -- def __hash__(self): -- """ -- Support hashing of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: hash(X()) == hash(float(X())) -- True -- """ -- return libmp.mpf_hash(self._mpf_) -- -- def __repr__(self): -- """ -- Support repr() of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: repr(X()) -- "mpf('3.25')" -- """ -- if global_context.pretty: -- return str(self) -- n = repr_dps(global_opts.prec) -- return "mpf('%s')" % to_str(self._mpf_, n) -- -- def __str__(self): -- """ -- Support str() of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: str(X()) -- '3.25' -- """ -- return to_str(self._mpf_, global_context._str_digits) -- -- @property -- def real(self): -- """ -- Support real part of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: X().real -- mpf('3.25') -- """ -- return self -- -- @property -- def imag(self): -- """ -- Support imaginary part of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: X().imag -- mpf('0.0') -- """ -- return global_context.zero -- -- def conjugate(self): -- """ -- Support complex conjugate of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: X().conjugate() -- mpf('3.25') -- """ -- return self -- -- @property -- def man(self): -- """ -- Support mantissa extraction of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: X().man -- 13 -- """ -- return self._mpf_[1] -- -- @property -- def exp(self): -- """ -- Support exponent extraction of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: X().exp -- -2 -- """ -- return self._mpf_[2] -- -- @property -- def bc(self): -- """ -- Support bitcount extraction of derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: X().bc -- 4 -- """ -- return self._mpf_[3] -- -- # XXX: optimize -- def __int__(self): -- """ -- Support integer conversion for derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: int(X()) -- 3 -- """ -- return int(libmp.to_int(self._mpf_)) -- -- def __float__(self): -- """ -- Support float conversion for derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: float(X()) -- 3.25 -- """ -- return libmp.to_float(self._mpf_) -- -- def __complex__(self): -- """ -- Support complex conversion for derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: complex(X()) -- (3.25+0j) -- """ -- return complex(float(self)) -- -- def to_fixed(self, prec): -- """ -- Support conversion to a fixed-point integer for derived classes:: -- -- sage: from mpmath import mpf -- sage: from sage.libs.mpmath.ext_main import mpf_base -- sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_ -- sage: X().to_fixed(30) -- 3489660928 -- """ -- return libmp.to_fixed(self._mpf_, prec) -- -- def __getstate__(self): -- return libmp.to_pickable(self._mpf_) -- -- def __setstate__(self, val): -- self._mpf_ = libmp.from_pickable(val) -- -- --cdef class mpf(mpf_base): -- """ -- An mpf instance holds a real-valued floating-point number. mpf:s -- work analogously to Python floats, but support arbitrary-precision -- arithmetic. -- """ -- -- cdef MPF value -- -- def __init__(self, x=0, **kwargs): -- """ -- Create an mpf from a recognized type, optionally rounding -- to a precision and in a direction different from the default. -- -- TESTS:: -- -- sage: from mpmath import mpf -- sage: mpf() -- mpf('0.0') -- sage: mpf(5) -- mpf('5.0') -- sage: mpf('inf') -- mpf('+inf') -- sage: mpf('nan') -- mpf('nan') -- sage: mpf(float(2.5)) -- mpf('2.5') -- sage: mpf("2.5") -- mpf('2.5') -- sage: mpf("0.3") -- mpf('0.29999999999999999') -- sage: mpf("0.3", prec=10) -- mpf('0.2998046875') -- sage: mpf("0.3", prec=10, rounding='u') -- mpf('0.30029296875') -- """ -- cdef MPopts opts -- opts = global_opts -- if kwargs: -- if 'prec' in kwargs: opts.prec = int(kwargs['prec']) -- if 'dps' in kwargs: opts.prec = libmp.dps_to_prec(int(kwargs['dps'])) -- if 'rounding' in kwargs: opts.rounding = rndmode_from_python(kwargs['rounding']) -- if MPF_set_any(&self.value, &self.value, x, opts, 1) != 1: -- raise TypeError -- -- def __reduce__(self): -- """ -- Support pickling:: -- -- sage: from mpmath import mpf -- sage: loads(dumps(mpf(0.5))) == mpf(0.5) -- True -- """ -- return (mpf, (), self._mpf_) -- -- def _get_mpf(self): -- """ -- Return internal representation of ``self`` as a tuple -- of (sign bit, mantissa, exponent, bitcount):: -- -- sage: from mpmath import mp -- sage: mp.mpf(-3)._mpf_ -- (1, 3, 0, 2) -- """ -- return MPF_to_tuple(&self.value) -- -- def _set_mpf(self, v): -- """ -- Set tuple value of ``self`` (warning: unsafe):: -- -- sage: from mpmath import mp -- sage: x = mp.mpf(-3) -- sage: x._mpf_ = (1, 3, -1, 2) -- sage: x -- mpf('-1.5') -- """ -- MPF_set_tuple(&self.value, v) -- -- _mpf_ = property(_get_mpf, _set_mpf, doc=_get_mpf.__doc__) -- -- def __bool__(self): -- """ -- Return whether the number is nonzero:: -- -- sage: from mpmath import mpf -- sage: bool(mpf(3.5)) -- True -- sage: bool(mpf(0.0)) -- False -- """ -- return self.value.special != S_ZERO -- -- def __hash__(self): -- """ -- Hash values are compatible with builtin Python floats -- when the precision is small enough:: -- -- sage: from mpmath import mpf -- sage: hash(mpf(2.5)) == hash(float(2.5)) -- True -- sage: hash(mpf('inf')) == hash(float(Infinity)) -- True -- """ -- return libmp.mpf_hash(self._mpf_) -- -- @property -- def real(self): -- """ -- Real part, leaves ``self`` unchanged:: -- -- sage: from mpmath import mpf -- sage: mpf(2.5).real -- mpf('2.5') -- """ -- return self -- -- @property -- def imag(self): -- """ -- Imaginary part, equal to zero:: -- -- sage: from mpmath import mpf -- sage: mpf(2.5).imag -- mpf('0.0') -- """ -- return global_context.zero -- -- def conjugate(self): -- """ -- Complex conjugate, leaves ``self`` unchanged:: -- -- sage: from mpmath import mpf -- sage: mpf(2.5).conjugate() -- mpf('2.5') -- """ -- return self -- -- @property -- def man(self): -- """ -- Return the binary mantissa of ``self``. The result is a Sage -- integer:: -- -- sage: from mpmath import mpf -- sage: mpf(-500.5).man -- 1001 -- sage: type(_) -- -- """ -- return self._mpf_[1] -- -- @property -- def exp(self): -- """ -- Return the binary exponent of ``self``:: -- -- sage: from mpmath import mpf -- sage: mpf(1/64.).exp -- -6 -- """ -- return self._mpf_[2] -- -- @property -- def bc(self): -- """ -- Return the number of bits in the mantissa of ``self``:: -- -- sage: from mpmath import mpf -- sage: mpf(-256).bc -- 1 -- sage: mpf(-255).bc -- 8 -- """ -- return self._mpf_[3] -- -- def to_fixed(self, long prec): -- """ -- Convert to a fixed-point integer of the given precision:: -- -- sage: from mpmath import mpf -- sage: mpf(7.25).to_fixed(30) -- 7784628224 -- sage: ZZ(7.25 * 2**30) -- 7784628224 -- """ -- # return libmp.to_fixed(self._mpf_, prec) -- MPF_to_fixed(tmp_mpz, &self.value, prec, False) -- cdef Integer r -- r = PY_NEW(Integer) -- mpz_set(r.value, tmp_mpz) -- return r -- -- def __int__(self): -- """ -- Convert to a Python integer (truncating if necessary):: -- -- sage: from mpmath import mpf -- sage: int(mpf(2.5)) -- 2 -- sage: type(_) -- <... 'int'> -- """ -- MPF_to_fixed(tmp_mpz, &self.value, 0, True) -- return mpzi(tmp_mpz) -- -- def __float__(self): -- """ -- Convert to a double-precision Python float:: -- -- sage: from mpmath import mpf -- sage: float(mpf(2.5)) -- 2.5 -- sage: type(_) -- <... 'float'> -- """ -- return MPF_to_double(&self.value, False) -- -- def __getstate__(self): -- """ -- Support pickling:: -- -- sage: from mpmath import mpf -- sage: loads(dumps(mpf(3))) == mpf(3) -- True -- """ -- return libmp.to_pickable(self._mpf_) -- -- def __setstate__(self, val): -- """ -- Support pickling:: -- -- sage: from mpmath import mpf -- sage: loads(dumps(mpf(3))) == mpf(3) -- True -- """ -- self._mpf_ = libmp.from_pickable(val) -- -- def __cinit__(self): -- """ -- Create a new mpf:: -- -- sage: from mpmath import mpf -- sage: x = mpf() -- """ -- MPF_init(&self.value) -- -- def __dealloc__(self): -- MPF_clear(&self.value) -- -- def __neg__(s): -- """ -- Negate ``self``, rounded to the current working precision:: -- -- sage: from mpmath import mpf -- sage: -mpf(2) -- mpf('-2.0') -- """ -- cdef mpf r = mpf.__new__(mpf) -- MPF_neg(&r.value, &s.value) -- MPF_normalize(&r.value, global_opts) -- return r -- -- def __pos__(s): -- """ -- Round the number to the current working precision:: -- -- sage: from mpmath import mp, mpf -- sage: mp.prec = 200 -- sage: x = mpf(1) / 3 -- sage: x.man -- 1071292029505993517027974728227441735014801995855195223534251 -- sage: mp.prec = 53 -- sage: (+x).man -- 6004799503160661 -- sage: print(+x) -- 0.333333333333333 -- """ -- cdef mpf r = mpf.__new__(mpf) -- MPF_set(&r.value, &s.value) -- MPF_normalize(&r.value, global_opts) -- return r -- -- def __abs__(s): -- """ -- Compute the absolute value, rounded to the current -- working precision:: -- -- sage: from mpmath import mpf -- sage: abs(mpf(-2)) -- mpf('2.0') -- """ -- cdef mpf r = mpf.__new__(mpf) -- MPF_abs(&r.value, &s.value) -- MPF_normalize(&r.value, global_opts) -- return r -- -- def sqrt(s): -- """ -- Compute the square root, rounded to the current -- working precision:: -- -- sage: from mpmath import mpf -- sage: mpf(2).sqrt() -- mpf('1.4142135623730951') -- """ -- cdef mpf r = mpf.__new__(mpf) -- MPF_sqrt(&r.value, &s.value, global_opts) -- return r -- -- def __round__(self, *args): -- return round(float(self), *args) -- -- def __richcmp__(self, other, int op): -- """ -- Compare numbers:: -- -- sage: from mpmath import mpf -- sage: mpf(3) > 2 -- True -- sage: mpf(3) == 3 -- True -- sage: mpf(3) == 4 -- False -- """ -- return binop(OP_RICHCMP+op, self, other, global_opts) -- -- def _mpfr_(self, RR): -- """ -- Return a Sage ``RealNumber``. -- -- EXAMPLES:: -- -- sage: from mpmath import mpf -- sage: mpf(3)._mpfr_(RealField(53)) -- 3.00000000000000 -- sage: RR(mpf(3)) # indirect doctest -- 3.00000000000000 -- """ -- signbit, man, exp, bc = self._mpf_ -- result = RR(man) << exp -- if signbit: -- result = -result -- return result -- -- --cdef class constant(mpf_base): -- """ -- Represent a mathematical constant with dynamic precision. -- When printed or used in an arithmetic operation, a constant -- is converted to a regular mpf at the working precision. A -- regular mpf can also be obtained using the operation +x. -- """ -- -- cdef public name, func, __doc__ -- -- def __init__(self, func, name, docname=''): -- """ -- Create a constant from a function computing an mpf -- tuple value:: -- -- sage: from mpmath import mp, mpf -- sage: q = mp.constant(lambda prec, rnd: mpf(0.25)._mpf_, "quarter", "q") -- sage: q -- -- sage: q + 1 -- mpf('1.25') -- """ -- self.name = name -- self.func = func -- self.__doc__ = getattr(function_docs, docname, '') -- -- def __call__(self, prec=None, dps=None, rounding=None): -- """ -- Calling a constant is equivalent to rounding it. A -- custom precision and rounding direction can also be passed:: -- -- sage: from mpmath import pi -- sage: print(pi(dps=5, rounding='d')) -- 3.1415901184082 -- sage: print(pi(dps=5, rounding='u')) -- 3.14159393310547 -- """ -- prec2 = global_opts.prec -- rounding2 = rndmode_to_python(global_opts.rounding) -- if not prec: prec = prec2 -- if not rounding: rounding = rounding2 -- if dps: prec = dps_to_prec(dps) -- return global_context.make_mpf(self.func(prec, rounding)) -- -- @property -- def _mpf_(self): -- """ -- Return the tuple value of the constant as if rounded -- to an mpf at the present working precision:: -- -- sage: from mpmath import pi -- sage: pi._mpf_ -- (0, 884279719003555, -48, 50) -- sage: 884279719003555 / 2.0**48 -- 3.14159265358979 -- """ -- prec = global_opts.prec -- rounding = rndmode_to_python(global_opts.rounding) -- return self.func(prec, rounding) -- -- def __repr__(self): -- """ -- Represent ``self`` as a string. With mp.pretty=False, the -- representation differs from that of an ordinary mpf:: -- -- sage: from mpmath import mp -- sage: mp2 = mp.clone() -- sage: mp2.pretty = True -- sage: repr(mp2.pi) -- '3.14159265358979' -- sage: mp2.pretty = False -- sage: repr(mp2.pi) -- '' -- """ -- if global_context.pretty: -- return str(self) -- return "<%s: %s~>" % (self.name, global_context.nstr(self)) -- -- def __bool__(self): -- """ -- Return whether the constant is nonzero:: -- -- sage: from mpmath import pi -- sage: bool(pi) -- True -- """ -- return self._mpf_ != libmp.fzero -- -- def __neg__(self): -- """ -- Negate the constant:: -- -- sage: from mpmath import pi -- sage: -pi -- mpf('-3.1415926535897931') -- """ -- return -mpf(self) -- -- def __pos__(self): -- """ -- Instantiate the constant as an mpf:: -- -- sage: from mpmath import pi -- sage: +pi -- mpf('3.1415926535897931') -- """ -- return mpf(self) -- -- def __abs__(self): -- """ -- Compute the absolute value of the constant:: -- -- sage: from mpmath import pi -- sage: abs(pi) -- mpf('3.1415926535897931') -- """ -- return abs(mpf(self)) -- -- def sqrt(self): -- """ -- Compute the square root of the constant:: -- -- sage: from mpmath import pi -- sage: print(pi.sqrt()) -- 1.77245385090552 -- """ -- return mpf(self).sqrt() -- -- # XXX: optimize -- def to_fixed(self, prec): -- """ -- Convert to a fixed-point integer:: -- -- sage: from mpmath import pi -- sage: float(pi.to_fixed(10) / 2.0**10) -- 3.140625 -- """ -- return libmp.to_fixed(self._mpf_, prec) -- -- def __getstate__(self): -- return libmp.to_pickable(self._mpf_) -- -- def __setstate__(self, val): -- self._mpf_ = libmp.from_pickable(val) -- -- # WHY is this method not inherited from the base class by Cython? -- def __hash__(self): -- """ -- A constant hashes as if instantiated to a number:: -- -- sage: from mpmath import pi -- sage: hash(pi) == hash(+pi) -- True -- """ -- return libmp.mpf_hash(self._mpf_) -- -- def __richcmp__(self, other, int op): -- """ -- A constant hashes as if instantiated to a number:: -- -- sage: from mpmath import pi -- sage: pi == pi -- True -- sage: pi > 3.14 -- True -- sage: pi < 3.14 -- False -- """ -- return binop(OP_RICHCMP+op, self, other, global_opts) -- -- --cdef class mpc(mpnumber): -- """ -- An mpc represents a complex number using a pair of mpf:s (one -- for the real part and another for the imaginary part.) The mpc -- class behaves fairly similarly to Python's complex type. -- """ -- -- cdef MPF re -- cdef MPF im -- -- def __init__(self, real=0, imag=0): -- """ -- Create a new mpc:: -- -- sage: from mpmath import mpc -- sage: mpc() == mpc(0,0) == mpc(1,0)-1 == 0 -- True -- """ -- cdef int typx, typy -- typx = MPF_set_any(&self.re, &self.im, real, global_opts, 1) -- if typx == 2: -- typy = 1 -- else: -- typy = MPF_set_any(&self.im, &self.im, imag, global_opts, 1) -- if typx == 0 or typy != 1: -- raise TypeError -- -- def __cinit__(self): -- """ -- Create a new mpc:: -- -- sage: from mpmath import mpc -- sage: x = mpc() -- """ -- MPF_init(&self.re) -- MPF_init(&self.im) -- -- def __dealloc__(self): -- MPF_clear(&self.re) -- MPF_clear(&self.im) -- -- def __reduce__(self): -- """ -- Support pickling:: -- -- sage: from mpmath import mpc -- sage: loads(dumps(mpc(1,3))) == mpc(1,3) -- True -- """ -- return (mpc, (), self._mpc_) -- -- def __setstate__(self, val): -- """ -- Support pickling:: -- -- sage: from mpmath import mpc -- sage: loads(dumps(mpc(1,3))) == mpc(1,3) -- True -- """ -- self._mpc_ = val[0], val[1] -- -- def __repr__(self): -- """ -- TESTS:: -- -- sage: from mpmath import mp -- sage: mp2 = mp.clone() -- sage: mp2.pretty = True -- sage: repr(mp2.mpc(2,3)) -- '(2.0 + 3.0j)' -- sage: mp2.pretty = False -- sage: repr(mp2.mpc(2,3)) -- "mpc(real='2.0', imag='3.0')" -- """ -- if global_context.pretty: -- return str(self) -- re, im = self._mpc_ -- n = repr_dps(global_opts.prec) -- return "mpc(real='%s', imag='%s')" % (to_str(re, n), to_str(im, n)) -- -- def __str__(s): -- """ -- TESTS:: -- -- sage: from mpmath import mp -- sage: str(mp.mpc(2,3)) -- '(2.0 + 3.0j)' -- """ -- return "(%s)" % libmp.mpc_to_str(s._mpc_, global_context._str_digits) -- -- def __bool__(self): -- """ -- TESTS:: -- -- sage: from mpmath import mp -- sage: bool(mp.mpc(0,1)) -- True -- sage: bool(mp.mpc(1,0)) -- True -- sage: bool(mp.mpc(0,0)) -- False -- """ -- return self.re.special != S_ZERO or self.im.special != S_ZERO -- -- #def __complex__(self): -- # a, b = self._mpc_ -- # return complex(libmp.to_float(a), libmp.to_float(b)) -- -- def __complex__(self): -- """ -- TESTS:: -- -- sage: from mpmath import mp -- sage: complex(mp.mpc(1,2)) == complex(1,2) -- True -- """ -- return complex(MPF_to_double(&self.re, False), MPF_to_double(&self.im, False)) -- -- def _get_mpc(self): -- """ -- Return tuple value of ``self``:: -- -- sage: from mpmath import mp -- sage: mp.mpc(2,3)._mpc_ -- ((0, 1, 1, 1), (0, 3, 0, 2)) -- """ -- return MPF_to_tuple(&self.re), MPF_to_tuple(&self.im) -- -- def _set_mpc(self, tuple v): -- """ -- Set tuple value of ``self`` (warning: unsafe):: -- -- sage: from mpmath import mp -- sage: x = mp.mpc(2,3) -- sage: x._mpc_ = (x._mpc_[1], x._mpc_[0]) -- sage: x -- mpc(real='3.0', imag='2.0') -- """ -- MPF_set_tuple(&self.re, v[0]) -- MPF_set_tuple(&self.im, v[1]) -- -- _mpc_ = property(_get_mpc, _set_mpc, doc=_get_mpc.__doc__) -- -- @property -- def real(self): -- """ -- Return the real part of ``self`` as an mpf:: -- -- sage: from mpmath import mp -- sage: mp.mpc(1,2).real -- mpf('1.0') -- """ -- cdef mpf r = mpf.__new__(mpf) -- MPF_set(&r.value, &self.re) -- return r -- -- @property -- def imag(self): -- """ -- Return the imaginary part of ``self`` as an mpf:: -- -- sage: from mpmath import mp -- sage: mp.mpc(1,2).imag -- mpf('2.0') -- """ -- cdef mpf r = mpf.__new__(mpf) -- MPF_set(&r.value, &self.im) -- return r -- -- def __hash__(self): -- """ -- Return the hash value of ``self``:: -- -- EXAMPLES:: -- -- sage: from mpmath import mp -- sage: hash(mp.mpc(2,3)) == hash(complex(2,3)) -- True -- -- TESTS: -- -- Check that :issue:`31676` is fixed:: -- -- sage: from mpmath import mpc -- sage: hash(mpc(1, -1)) == hash(mpc(-1, -1)) # should not return OverflowError: Python int too large to convert to C ssize_t -- False -- """ -- return hash(libmp.mpc_hash(self._mpc_)) -- -- def __neg__(s): -- """ -- Negate the number:: -- -- sage: from mpmath import mpc -- sage: -mpc(1,2) -- mpc(real='-1.0', imag='-2.0') -- """ -- cdef mpc r = mpc.__new__(mpc) -- MPF_neg(&r.re, &s.re) -- MPF_neg(&r.im, &s.im) -- MPF_normalize(&r.re, global_opts) -- MPF_normalize(&r.im, global_opts) -- return r -- -- def conjugate(s): -- """ -- Return the complex conjugate:: -- -- sage: from mpmath import mpc -- sage: mpc(1,2).conjugate() -- mpc(real='1.0', imag='-2.0') -- """ -- cdef mpc r = mpc.__new__(mpc) -- MPF_set(&r.re, &s.re) -- MPF_neg(&r.im, &s.im) -- MPF_normalize(&r.re, global_opts) -- MPF_normalize(&r.im, global_opts) -- return r -- -- def __pos__(s): -- """ -- Round the number to the current working precision:: -- -- sage: from mpmath import mp -- sage: mp.prec = 200 -- sage: x = mp.mpc(1) / 3 -- sage: x.real.man -- 1071292029505993517027974728227441735014801995855195223534251 -- sage: mp.prec = 53 -- sage: +x -- mpc(real='0.33333333333333331', imag='0.0') -- sage: (+x).real.man -- 6004799503160661 -- """ -- cdef mpc r = mpc.__new__(mpc) -- MPF_set(&r.re, &s.re) -- MPF_set(&r.im, &s.im) -- MPF_normalize(&r.re, global_opts) -- MPF_normalize(&r.im, global_opts) -- return r -- -- def __abs__(s): -- """ -- Return the absolute value of ``self``:: -- -- sage: from mpmath import mpc -- sage: abs(mpc(3,4)) -- mpf('5.0') -- """ -- cdef mpf r = mpf.__new__(mpf) -- MPF_hypot(&r.value, &s.re, &s.im, global_opts) -- return r -- -- def __richcmp__(self, other, int op): -- """ -- Complex numbers can be compared for equality:: -- -- sage: from mpmath import mpc -- sage: mpc(2,3) == complex(2,3) -- True -- sage: mpc(-2,3) == complex(2,3) -- False -- sage: mpc(-2,3) != complex(2,3) -- True -- """ -- return binop(OP_RICHCMP+op, self, other, global_opts) -- -- def _complex_mpfr_field_(self, CC): -- """ -- Return a Sage complex number. -- -- EXAMPLES:: -- -- sage: from mpmath import mpc -- sage: CC(mpc(1,2)) # indirect doctest -- 1.00000000000000 + 2.00000000000000*I -- sage: mpc(1,2)._complex_mpfr_field_(CC) -- 1.00000000000000 + 2.00000000000000*I -- """ -- RR = CC._real_field() -- return CC((self.real._mpfr_(RR), self.imag._mpfr_(RR))) -- -- --def hypsum_internal(int p, int q, param_types, str ztype, coeffs, z, -- long prec, long wp, long epsshift, dict magnitude_check, kwargs): -- """ -- Internal summation routine for hypergeometric series (wraps -- extension function MPF_hypsum to handle mpf/mpc types). -- -- EXAMPLES:: -- -- sage: from mpmath import mp # indirect doctest -- sage: mp.dps = 15 -- sage: print(mp.hyp1f1(1,2,3)) -- 6.36184564106256 -- -- .. TODO:: -- -- convert mpf/mpc parameters to fixed-point numbers here -- instead of converting to tuples within MPF_hypsum. -- """ -- cdef mpf f -- cdef mpc c -- c = mpc.__new__(mpc) -- have_complex, magn = MPF_hypsum(&c.re, &c.im, p, q, param_types, -- ztype, coeffs, z, prec, wp, epsshift, magnitude_check, kwargs) -- if have_complex: -- v = c -- else: -- f = mpf.__new__(mpf) -- MPF_set(&f.value, &c.re) -- v = f -- return v, have_complex, magn -diff --git a/src/sage/libs/mpmath/meson.build b/src/sage/libs/mpmath/meson.build -index cc8cdc84e98..e1d76c0c130 100644 ---- a/src/sage/libs/mpmath/meson.build -+++ b/src/sage/libs/mpmath/meson.build -@@ -1,20 +1,12 @@ - py.install_sources( - '__init__.py', - 'all.py', -- 'ext_impl.pxd', -- 'ext_impl.pyx', -- 'ext_libmp.pyx', -- 'ext_main.pxd', -- 'ext_main.pyx', - 'utils.pxd', - 'utils.pyx', - subdir: 'sage/libs/mpmath', - ) - - extension_data = { -- 'ext_impl': files('ext_impl.pyx'), -- 'ext_libmp': files('ext_libmp.pyx'), -- 'ext_main': files('ext_main.pyx'), - 'utils': files('utils.pyx'), - } - -@@ -25,7 +17,7 @@ foreach name, pyx : extension_data - subdir: 'sage/libs/mpmath', - install: true, - include_directories: [inc_cpython, inc_ext, inc_rings], -- dependencies: [py_dep, cysignals, gmp, mpfr], -+ dependencies: [py_dep, cysignals, gmp, gmpy2, mpfr], - ) - endforeach - -diff --git a/src/sage/libs/mpmath/utils.pyx b/src/sage/libs/mpmath/utils.pyx -index 1acf14ea540..a88884d148e 100644 ---- a/src/sage/libs/mpmath/utils.pyx -+++ b/src/sage/libs/mpmath/utils.pyx -@@ -1,9 +1,9 @@ - """ - Utilities for Sage-mpmath interaction -- --Also patches some mpmath functions for speed - """ - -+cimport gmpy2 -+ - from sage.ext.stdsage cimport PY_NEW - - from sage.rings.integer cimport Integer -@@ -16,145 +16,7 @@ from sage.libs.gmp.all cimport * - - from sage.rings.real_mpfr cimport RealField - --cpdef int bitcount(n) noexcept: -- """ -- Bitcount of a Sage Integer or Python int/long. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import bitcount -- sage: bitcount(0) -- 0 -- sage: bitcount(1) -- 1 -- sage: bitcount(100) -- 7 -- sage: bitcount(-100) -- 7 -- sage: bitcount(2r) -- 2 -- sage: bitcount(2L) -- 2 -- """ -- cdef Integer m -- if isinstance(n, Integer): -- m = n -- else: -- m = Integer(n) -- if mpz_sgn(m.value) == 0: -- return 0 -- return mpz_sizeinbase(m.value, 2) -- --cpdef isqrt(n): -- """ -- Square root (rounded to floor) of a Sage Integer or Python int/long. -- The result is a Sage Integer. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import isqrt -- sage: isqrt(0) -- 0 -- sage: isqrt(100) -- 10 -- sage: isqrt(10) -- 3 -- sage: isqrt(10r) -- 3 -- sage: isqrt(10L) -- 3 -- """ -- cdef Integer m, y -- if isinstance(n, Integer): -- m = n -- else: -- m = Integer(n) -- if mpz_sgn(m.value) < 0: -- raise ValueError("square root of negative integer not defined.") -- y = PY_NEW(Integer) -- mpz_sqrt(y.value, m.value) -- return y -- --cpdef from_man_exp(man, exp, long prec=0, str rnd='d'): -- """ -- Create normalized mpf value tuple from mantissa and exponent. -- -- With prec > 0, rounds the result in the desired direction -- if necessary. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import from_man_exp -- sage: from_man_exp(-6, -1) -- (1, 3, 0, 2) -- sage: from_man_exp(-6, -1, 1, 'd') -- (1, 1, 1, 1) -- sage: from_man_exp(-6, -1, 1, 'u') -- (1, 1, 2, 1) -- """ -- cdef Integer res -- cdef long bc -- res = Integer(man) -- bc = mpz_sizeinbase(res.value, 2) -- if not prec: -- prec = bc -- if mpz_sgn(res.value) < 0: -- mpz_neg(res.value, res.value) -- return normalize(1, res, exp, bc, prec, rnd) -- else: -- return normalize(0, res, exp, bc, prec, rnd) -- --cpdef normalize(long sign, Integer man, exp, long bc, long prec, str rnd): -- """ -- Create normalized mpf value tuple from full list of components. -- -- EXAMPLES:: -- -- sage: from mpmath.libmp import normalize -- sage: normalize(0, 4, 5, 3, 53, 'n') -- (0, 1, 7, 1) -- """ -- cdef long shift -- cdef Integer res -- cdef unsigned long trail -- if mpz_sgn(man.value) == 0: -- from mpmath.libmp import fzero -- return fzero -- if bc <= prec and mpz_odd_p(man.value): -- return (sign, man, exp, bc) -- shift = bc - prec -- res = PY_NEW(Integer) -- if shift > 0: -- if rnd == 'n': -- if mpz_tstbit(man.value, shift-1) and (mpz_tstbit(man.value, shift) -- or (mpz_scan1(man.value, 0) < (shift-1))): -- mpz_cdiv_q_2exp(res.value, man.value, shift) -- else: -- mpz_fdiv_q_2exp(res.value, man.value, shift) -- elif rnd == 'd': -- mpz_fdiv_q_2exp(res.value, man.value, shift) -- elif rnd == 'f': -- if sign: -- mpz_cdiv_q_2exp(res.value, man.value, shift) -- else: -- mpz_fdiv_q_2exp(res.value, man.value, shift) -- elif rnd == 'c': -- if sign: -- mpz_fdiv_q_2exp(res.value, man.value, shift) -- else: -- mpz_cdiv_q_2exp(res.value, man.value, shift) -- elif rnd == 'u': -- mpz_cdiv_q_2exp(res.value, man.value, shift) -- exp += shift -- else: -- mpz_set(res.value, man.value) -- # Strip trailing bits -- trail = mpz_scan1(res.value, 0) -- if 0 < trail < bc: -- mpz_tdiv_q_2exp(res.value, res.value, trail) -- exp += trail -- bc = mpz_sizeinbase(res.value, 2) -- return (sign, res, int(exp), bc) -+gmpy2.import_gmpy2() - - cdef mpfr_from_mpfval(mpfr_t res, tuple x): - """ -@@ -162,11 +24,11 @@ cdef mpfr_from_mpfval(mpfr_t res, tuple x): - data tuple. - """ - cdef int sign -- cdef Integer man -+ cdef gmpy2.mpz man - cdef long exp - sign, man, exp, _ = x - if man: -- mpfr_set_z(res, man.value, MPFR_RNDZ) -+ mpfr_set_z(res, man.z, MPFR_RNDZ) - if sign: - mpfr_neg(res, res, MPFR_RNDZ) - mpfr_mul_2si(res, res, exp, MPFR_RNDZ) -@@ -210,7 +72,7 @@ cdef mpfr_to_mpfval(mpfr_t value): - mpz_tdiv_q_2exp(man.value, man.value, trailing) - exp += trailing - bc = mpz_sizeinbase(man.value, 2) -- return (sign, man, int(exp), bc) -+ return (sign, man.__mpz__(), int(exp), bc) - - - def mpmath_to_sage(x, prec): -@@ -305,7 +167,7 @@ def sage_to_mpmath(x, prec): - sage: print(a.sage_to_mpmath(1+pi, 53)) - 4.14159265358979 - sage: a.sage_to_mpmath(infinity, 53) -- mpf('+inf') -+ mpf('...inf') - sage: a.sage_to_mpmath(-infinity, 53) - mpf('-inf') - sage: a.sage_to_mpmath(NaN, 53) -@@ -414,7 +276,7 @@ def call(func, *args, **kwargs): - Check that :issue:`11885` is fixed:: - - sage: a.call(a.ei, 1.0r, parent=float) -- 1.8951178163559366 -+ 1.8951178163559368 - - Check that :issue:`14984` is fixed:: - -diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx -index 11f58008fcf..ba26d194b1f 100644 ---- a/src/sage/rings/complex_mpfr.pyx -+++ b/src/sage/rings/complex_mpfr.pyx -@@ -54,6 +54,7 @@ from sage.rings.integer_ring import ZZ - - cimport gmpy2 - gmpy2.import_gmpy2() -+from mpmath import mp - - try: - from cypari2.gen import Gen as pari_gen -@@ -984,7 +985,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): - real, imag = real - elif isinstance(real, complex): - real, imag = real.real, real.imag -- elif type(real) is gmpy2.mpc: -+ elif isinstance(real, (gmpy2.mpc, mp.mpc)): - real, imag = (real).real, (real).imag - else: - imag = 0 -diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx -index f0b5b713fe1..1ed67bfb906 100644 ---- a/src/sage/rings/real_mpfr.pyx -+++ b/src/sage/rings/real_mpfr.pyx -@@ -152,8 +152,6 @@ from sage.structure.richcmp cimport rich_to_bool_sgn - cdef bin_op - from sage.structure.element import bin_op - --from sage.libs.mpmath.utils cimport mpfr_to_mpfval -- - from sage.rings.integer cimport Integer - from sage.rings.rational cimport Rational - from sage.rings.real_double cimport RealDoubleElement -diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx -index 98ffac46406..0450eeccbaf 100644 ---- a/src/sage/structure/coerce.pyx -+++ b/src/sage/structure/coerce.pyx -@@ -143,6 +143,12 @@ cpdef py_scalar_parent(py_type): - Real Double Field - sage: py_scalar_parent(gmpy2.mpc) # needs sage.rings.complex_double - Complex Double Field -+ -+ sage: import mpmath -+ sage: py_scalar_parent(mpmath.mpf) -+ Real Double Field -+ sage: py_scalar_parent(mpmath.mpc) # needs sage.rings.complex_double -+ Complex Double Field - """ - if issubclass(py_type, int): - import sage.rings.integer_ring -@@ -150,39 +156,46 @@ cpdef py_scalar_parent(py_type): - if py_type is FractionType: - import sage.rings.rational_field - return sage.rings.rational_field.QQ -- elif issubclass(py_type, float): -+ if issubclass(py_type, float): - import sage.rings.real_double - return sage.rings.real_double.RDF -- elif issubclass(py_type, complex): -+ if issubclass(py_type, complex): - import sage.rings.complex_double - return sage.rings.complex_double.CDF -- elif is_numpy_type(py_type): -+ if is_numpy_type(py_type): - import numpy - if issubclass(py_type, numpy.integer): - import sage.rings.integer_ring - return sage.rings.integer_ring.ZZ -- elif issubclass(py_type, numpy.floating): -+ if issubclass(py_type, numpy.floating): - import sage.rings.real_double - return sage.rings.real_double.RDF -- elif issubclass(py_type, numpy.complexfloating): -+ if issubclass(py_type, numpy.complexfloating): - import sage.rings.complex_double - return sage.rings.complex_double.CDF -- else: -- return None -- elif issubclass(py_type, gmpy2.mpz): -+ return None -+ if issubclass(py_type, gmpy2.mpz): - import sage.rings.integer_ring - return sage.rings.integer_ring.ZZ -- elif issubclass(py_type, gmpy2.mpq): -+ if issubclass(py_type, gmpy2.mpq): - import sage.rings.rational_field - return sage.rings.rational_field.QQ -- elif issubclass(py_type, gmpy2.mpfr): -+ if issubclass(py_type, gmpy2.mpfr): - import sage.rings.real_double - return sage.rings.real_double.RDF -- elif issubclass(py_type, gmpy2.mpc): -+ if issubclass(py_type, gmpy2.mpc): - import sage.rings.complex_double - return sage.rings.complex_double.CDF -- else: -+ if is_mpmath_type(py_type): -+ import mpmath -+ if issubclass(py_type, mpmath.mpf): -+ from sage.rings.real_double import RDF -+ return RDF -+ if issubclass(py_type, mpmath.mpc): -+ from sage.rings.complex_double import CDF -+ return CDF - return None -+ return None - - cpdef py_scalar_to_element(x): - """ -@@ -468,14 +481,13 @@ cpdef bint is_numpy_type(t) noexcept: - return True - return False - -+ - cpdef bint is_mpmath_type(t) noexcept: - r""" -- Check whether the type ``t`` is a type whose name starts with either -- ``mpmath.`` or ``sage.libs.mpmath.``. -+ Check whether the type ``t`` is a type whose name starts with ``mpmath.`` - - EXAMPLES:: - -- sage: # needs mpmath - sage: from sage.structure.coerce import is_mpmath_type - sage: is_mpmath_type(int) - False -@@ -488,7 +500,7 @@ cpdef bint is_mpmath_type(t) noexcept: - True - """ - return isinstance(t, type) and \ -- strncmp((t).tp_name, "sage.libs.mpmath.", 17) == 0 -+ t.__module__.startswith("mpmath.") - - - cdef class CoercionModel: -diff --git a/src/sage/tests/books/computational_mathematics_with_sagemath/integration_doctest.py b/src/sage/tests/books/computational_mathematics_with_sagemath/integration_doctest.py -index cdb0aceb956..02d01cc8305 100644 ---- a/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py -+++ b/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py -@@ -154,7 +154,7 @@ - sage: mpmath.quad(f, [0, 1]) - Traceback (most recent call last): - ... -- TypeError: no canonical coercion from to ... -+ TypeError: no canonical coercion from to ... - - Sage example in ./integration.tex, line 866:: - diff --git a/srcpkgs/sagemath/patches/fix-doctest-ipython-9.10.patch b/srcpkgs/sagemath/patches/fix-doctest-ipython-9.10.patch deleted file mode 100644 index 98d917bf2c1f19..00000000000000 --- a/srcpkgs/sagemath/patches/fix-doctest-ipython-9.10.patch +++ /dev/null @@ -1,12 +0,0 @@ -remove a test that breaks with ipython 9.10 - ---- a/src/sage/repl/interpreter.py -+++ b/src/sage/repl/interpreter.py -@@ -119,7 +119,6 @@ line:: - sage: from sage.repl.interpreter import get_test_shell - sage: shell = get_test_shell() - sage: shell.run_cell('sage: a = 123') # single line -- sage: shell.run_cell('sage: a = [\n... 123]') # old-style multi-line - sage: shell.run_cell('sage: a = [\n....: 123]') # new-style multi-line - - We test that :issue:`16196` is resolved:: diff --git a/srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch b/srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch deleted file mode 100644 index 393bb5a79b0bc5..00000000000000 --- a/srcpkgs/sagemath/patches/fix-doctest-maxima-5.49.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/sage/calculus/calculus.py -+++ b/src/sage/calculus/calculus.py -@@ -1824,7 +1824,7 @@ def laplace(ex, t, s, algorithm='maxima'): - sage: f = exp (2*t + a) * sin(t) * t; f - t*e^(a + 2*t)*sin(t) - sage: L = laplace(f, t, s); L -- 2*(s - 2)*e^a/(s^2 - 4*s + 5)^2 -+ 2*(s - 2)*e^a/(s^4 - 8*s^3 + 26*s^2 - 40*s + 25) - sage: inverse_laplace(L, s, t) - t*e^(a + 2*t)*sin(t) - diff --git a/srcpkgs/sagemath/patches/sphinx.patch b/srcpkgs/sagemath/patches/sphinx.patch deleted file mode 100644 index 6c5d5799d5294f..00000000000000 --- a/srcpkgs/sagemath/patches/sphinx.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/pyproject.toml -+++ b/pyproject.toml -@@ -68,7 +68,7 @@ - 'ptyprocess > 0.5', - 'requests >=2.13.0', - 'scipy >=1.11', -- 'sphinx >=6.2, <9', -+ 'sphinx >=6.2, <10', - 'sympy >=1.6, <2.0', - # TODO: Remove this once the migration to meson is complete - 'pkgconfig', diff --git a/srcpkgs/sagemath/patches/workaround-embed-positions.patch b/srcpkgs/sagemath/patches/workaround-embed-positions.patch index 1aa4e77dc687bd..fdd69c04b108dc 100644 --- a/srcpkgs/sagemath/patches/workaround-embed-positions.patch +++ b/srcpkgs/sagemath/patches/workaround-embed-positions.patch @@ -6,10 +6,10 @@ This should fix https://github.com/sagemath/sage/issues/39872#issuecomment-37377 --- a/src/sage/config.py.in +++ b/src/sage/config.py.in -@@ -11,6 +11,7 @@ VERSION = "@PACKAGE_VERSION@" +@@ -8,6 +8,7 @@ VERSION = "@PACKAGE_VERSION@" + # These variables come first so that other substituted variable values can refer # to it. SAGE_LOCAL = "@prefix@" - SAGE_ROOT = "@SAGE_ROOT@" +SAGE_BUILD_SRC = "@EDITABLE_SRC@/src" # The semicolon-separated list of GAP root paths. This is the list of diff --git a/srcpkgs/sagemath/template b/srcpkgs/sagemath/template index 87f906d87e1a26..26079ec9bd0ae3 100644 --- a/srcpkgs/sagemath/template +++ b/srcpkgs/sagemath/template @@ -1,7 +1,7 @@ # Template file for 'sagemath' pkgname=sagemath -version=10.8 -revision=2 +version=10.9 +revision=1 _pypi_version=${version/.beta/b} _pypi_version=${_pypi_version/.rc/rc} build_style=python3-pep517 @@ -38,7 +38,7 @@ license="GPL-2.0-or-later" homepage="https://www.sagemath.org/" changelog="https://github.com/sagemath/sage/releases" distfiles="${PYPI_SITE}/s/sagemath/sagemath-${_pypi_version}.tar.gz" -checksum=864c21a84bfad05f586ccdc45bf685552cd87a236bf56bc30163de474569f82c +checksum=5855626668197958372403dc6fa1878750b90ac7f113f49a5bc43ddaafd60591 nocross="due to fflas-ffpack, givaro, linbox, sympow, maxima" # parallel build @@ -51,6 +51,10 @@ do_check() { # this makes for nicer (shorter) relative paths in output cd ${testdir}/${py3_sitelib} + # there is a conflict between this conftest.py and the one in our builddir + # see https://github.com/sagemath/sage/pull/41709#issuecomment-4425750767 + rm "sage/conftest.py" + if [ -f ${XBPS_DISTDIR}/sagemath-check ] ; then _sed='s|#.*||;/^\s*$/d;s|^\s*\([^ ]*/\)\?sage/|sage/|g' \ _test_files=$(sed -e "$_sed" ${XBPS_DISTDIR}/sagemath-check)