passagemath-flint 10.6.1rc10__cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
- passagemath_flint-10.6.1rc10.dist-info/RECORD +361 -0
- passagemath_flint-10.6.1rc10.dist-info/WHEEL +6 -0
- passagemath_flint-10.6.1rc10.dist-info/top_level.txt +2 -0
- passagemath_flint.libs/libflint-aecb9cc5.so.21.0.0 +0 -0
- passagemath_flint.libs/libgf2x-a4cdec90.so.3.0.0 +0 -0
- passagemath_flint.libs/libgfortran-8f1e9814.so.5.0.0 +0 -0
- passagemath_flint.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_flint.libs/libgsl-cda90e79.so.28.0.0 +0 -0
- passagemath_flint.libs/libmpfi-e3c25853.so.0.0.0 +0 -0
- passagemath_flint.libs/libmpfr-82690d50.so.6.2.1 +0 -0
- passagemath_flint.libs/libntl-74e7d9a3.so.44.0.1 +0 -0
- passagemath_flint.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
- passagemath_flint.libs/libquadmath-828275a7.so.0.0.0 +0 -0
- sage/all__sagemath_flint.py +29 -0
- sage/combinat/all__sagemath_flint.py +1 -0
- sage/combinat/posets/all__sagemath_flint.py +1 -0
- sage/combinat/posets/hasse_cython_flint.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython_flint.pyx +194 -0
- sage/data_structures/all__sagemath_flint.py +1 -0
- sage/data_structures/bounded_integer_sequences.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/data_structures/bounded_integer_sequences.pxd +62 -0
- sage/data_structures/bounded_integer_sequences.pyx +1418 -0
- sage/graphs/all__sagemath_flint.py +1 -0
- sage/graphs/chrompoly.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/graphs/chrompoly.pyx +555 -0
- sage/graphs/matchpoly.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/graphs/matchpoly.pyx +412 -0
- sage/libs/all__sagemath_flint.py +17 -0
- sage/libs/arb/__init__.py +1 -0
- sage/libs/arb/acb.pxd +154 -0
- sage/libs/arb/acb_calc.pxd +9 -0
- sage/libs/arb/acb_elliptic.pxd +25 -0
- sage/libs/arb/acb_hypgeom.pxd +74 -0
- sage/libs/arb/acb_mat.pxd +62 -0
- sage/libs/arb/acb_modular.pxd +17 -0
- sage/libs/arb/acb_poly.pxd +216 -0
- sage/libs/arb/arb.pxd +240 -0
- sage/libs/arb/arb_fmpz_poly.pxd +21 -0
- sage/libs/arb/arb_hypgeom.pxd +83 -0
- sage/libs/arb/arb_wrap.h +34 -0
- sage/libs/arb/arf.pxd +131 -0
- sage/libs/arb/arith.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/arb/arith.pyx +87 -0
- sage/libs/arb/bernoulli.pxd +6 -0
- sage/libs/arb/mag.pxd +77 -0
- sage/libs/arb/types.pxd +37 -0
- sage/libs/flint/__init__.py +1 -0
- sage/libs/flint/acb.pxd +270 -0
- sage/libs/flint/acb_calc.pxd +22 -0
- sage/libs/flint/acb_dft.pxd +51 -0
- sage/libs/flint/acb_dirichlet.pxd +112 -0
- sage/libs/flint/acb_elliptic.pxd +42 -0
- sage/libs/flint/acb_hypgeom.pxd +169 -0
- sage/libs/flint/acb_macros.pxd +9 -0
- sage/libs/flint/acb_mat.pxd +136 -0
- sage/libs/flint/acb_mat_macros.pxd +10 -0
- sage/libs/flint/acb_modular.pxd +62 -0
- sage/libs/flint/acb_poly.pxd +251 -0
- sage/libs/flint/acb_poly_macros.pxd +8 -0
- sage/libs/flint/acb_theta.pxd +124 -0
- sage/libs/flint/acf.pxd +32 -0
- sage/libs/flint/aprcl.pxd +84 -0
- sage/libs/flint/arb.pxd +382 -0
- sage/libs/flint/arb_calc.pxd +31 -0
- sage/libs/flint/arb_fmpz_poly.pxd +34 -0
- sage/libs/flint/arb_fpwrap.pxd +215 -0
- sage/libs/flint/arb_hypgeom.pxd +147 -0
- sage/libs/flint/arb_macros.pxd +9 -0
- sage/libs/flint/arb_mat.pxd +140 -0
- sage/libs/flint/arb_mat_macros.pxd +10 -0
- sage/libs/flint/arb_poly.pxd +237 -0
- sage/libs/flint/arf.pxd +167 -0
- sage/libs/flint/arith.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/arith.pxd +76 -0
- sage/libs/flint/arith.pyx +77 -0
- sage/libs/flint/arith_sage.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/arith_sage.pyx +308 -0
- sage/libs/flint/bernoulli.pxd +28 -0
- sage/libs/flint/bool_mat.pxd +52 -0
- sage/libs/flint/ca.pxd +203 -0
- sage/libs/flint/ca_ext.pxd +34 -0
- sage/libs/flint/ca_field.pxd +32 -0
- sage/libs/flint/ca_mat.pxd +117 -0
- sage/libs/flint/ca_poly.pxd +104 -0
- sage/libs/flint/ca_vec.pxd +46 -0
- sage/libs/flint/calcium.pxd +27 -0
- sage/libs/flint/d_mat.pxd +39 -0
- sage/libs/flint/d_vec.pxd +32 -0
- sage/libs/flint/dirichlet.pxd +57 -0
- sage/libs/flint/dlog.pxd +53 -0
- sage/libs/flint/double_extras.pxd +24 -0
- sage/libs/flint/double_interval.pxd +36 -0
- sage/libs/flint/fexpr.pxd +104 -0
- sage/libs/flint/fexpr_builtin.pxd +20 -0
- sage/libs/flint/fft.pxd +66 -0
- sage/libs/flint/flint.pxd +36 -0
- sage/libs/flint/flint_ntl_wrap.h +35 -0
- sage/libs/flint/flint_sage.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/flint_sage.pyx +163 -0
- sage/libs/flint/flint_wrap.h +190 -0
- sage/libs/flint/fmpq.pxd +137 -0
- sage/libs/flint/fmpq_mat.pxd +105 -0
- sage/libs/flint/fmpq_mat_macros.pxd +10 -0
- sage/libs/flint/fmpq_mpoly.pxd +165 -0
- sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
- sage/libs/flint/fmpq_poly.pxd +241 -0
- sage/libs/flint/fmpq_poly_macros.pxd +9 -0
- sage/libs/flint/fmpq_poly_sage.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpq_poly_sage.pxd +31 -0
- sage/libs/flint/fmpq_poly_sage.pyx +48 -0
- sage/libs/flint/fmpq_vec.pxd +27 -0
- sage/libs/flint/fmpz.pxd +256 -0
- sage/libs/flint/fmpz_extras.pxd +32 -0
- sage/libs/flint/fmpz_factor.pxd +42 -0
- sage/libs/flint/fmpz_factor_sage.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_factor_sage.pxd +4 -0
- sage/libs/flint/fmpz_factor_sage.pyx +29 -0
- sage/libs/flint/fmpz_lll.pxd +49 -0
- sage/libs/flint/fmpz_macros.pxd +8 -0
- sage/libs/flint/fmpz_mat.pxd +184 -0
- sage/libs/flint/fmpz_mat_macros.pxd +10 -0
- sage/libs/flint/fmpz_mod.pxd +46 -0
- sage/libs/flint/fmpz_mod_mat.pxd +71 -0
- sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
- sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fmpz_mod_poly.pxd +249 -0
- sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
- sage/libs/flint/fmpz_mod_vec.pxd +27 -0
- sage/libs/flint/fmpz_mpoly.pxd +224 -0
- sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
- sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
- sage/libs/flint/fmpz_poly.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly.pxd +407 -0
- sage/libs/flint/fmpz_poly.pyx +19 -0
- sage/libs/flint/fmpz_poly_factor.pxd +33 -0
- sage/libs/flint/fmpz_poly_macros.pxd +8 -0
- sage/libs/flint/fmpz_poly_mat.pxd +71 -0
- sage/libs/flint/fmpz_poly_q.pxd +55 -0
- sage/libs/flint/fmpz_poly_sage.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly_sage.pxd +20 -0
- sage/libs/flint/fmpz_poly_sage.pyx +500 -0
- sage/libs/flint/fmpz_vec.pxd +80 -0
- sage/libs/flint/fmpzi.pxd +52 -0
- sage/libs/flint/fq.pxd +97 -0
- sage/libs/flint/fq_default.pxd +84 -0
- sage/libs/flint/fq_default_mat.pxd +70 -0
- sage/libs/flint/fq_default_poly.pxd +97 -0
- sage/libs/flint/fq_default_poly_factor.pxd +39 -0
- sage/libs/flint/fq_embed.pxd +28 -0
- sage/libs/flint/fq_mat.pxd +83 -0
- sage/libs/flint/fq_nmod.pxd +95 -0
- sage/libs/flint/fq_nmod_embed.pxd +28 -0
- sage/libs/flint/fq_nmod_mat.pxd +83 -0
- sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
- sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fq_nmod_poly.pxd +202 -0
- sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
- sage/libs/flint/fq_nmod_vec.pxd +33 -0
- sage/libs/flint/fq_poly.pxd +204 -0
- sage/libs/flint/fq_poly_factor.pxd +47 -0
- sage/libs/flint/fq_vec.pxd +33 -0
- sage/libs/flint/fq_zech.pxd +99 -0
- sage/libs/flint/fq_zech_embed.pxd +28 -0
- sage/libs/flint/fq_zech_mat.pxd +78 -0
- sage/libs/flint/fq_zech_poly.pxd +198 -0
- sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
- sage/libs/flint/fq_zech_vec.pxd +33 -0
- sage/libs/flint/gr.pxd +174 -0
- sage/libs/flint/gr_generic.pxd +215 -0
- sage/libs/flint/gr_mat.pxd +161 -0
- sage/libs/flint/gr_mpoly.pxd +68 -0
- sage/libs/flint/gr_poly.pxd +276 -0
- sage/libs/flint/gr_special.pxd +237 -0
- sage/libs/flint/gr_vec.pxd +120 -0
- sage/libs/flint/hypgeom.pxd +24 -0
- sage/libs/flint/long_extras.pxd +23 -0
- sage/libs/flint/mag.pxd +131 -0
- sage/libs/flint/mag_macros.pxd +8 -0
- sage/libs/flint/mpf_mat.pxd +36 -0
- sage/libs/flint/mpf_vec.pxd +34 -0
- sage/libs/flint/mpfr_mat.pxd +27 -0
- sage/libs/flint/mpfr_vec.pxd +25 -0
- sage/libs/flint/mpn_extras.pxd +41 -0
- sage/libs/flint/mpoly.pxd +72 -0
- sage/libs/flint/nf.pxd +19 -0
- sage/libs/flint/nf_elem.pxd +74 -0
- sage/libs/flint/nmod.pxd +35 -0
- sage/libs/flint/nmod_mat.pxd +104 -0
- sage/libs/flint/nmod_mpoly.pxd +144 -0
- sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/nmod_poly.pxd +339 -0
- sage/libs/flint/nmod_poly_factor.pxd +44 -0
- sage/libs/flint/nmod_poly_linkage.pxi +710 -0
- sage/libs/flint/nmod_poly_mat.pxd +76 -0
- sage/libs/flint/nmod_vec.pxd +40 -0
- sage/libs/flint/ntl_interface.pxd +17 -0
- sage/libs/flint/padic.pxd +93 -0
- sage/libs/flint/padic_mat.pxd +64 -0
- sage/libs/flint/padic_poly.pxd +88 -0
- sage/libs/flint/partitions.pxd +23 -0
- sage/libs/flint/perm.pxd +26 -0
- sage/libs/flint/profiler.pxd +24 -0
- sage/libs/flint/qadic.pxd +77 -0
- sage/libs/flint/qfb.pxd +44 -0
- sage/libs/flint/qqbar.pxd +172 -0
- sage/libs/flint/qsieve.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve.pxd +41 -0
- sage/libs/flint/qsieve.pyx +21 -0
- sage/libs/flint/qsieve_sage.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve_sage.pyx +67 -0
- sage/libs/flint/thread_pool.pxd +25 -0
- sage/libs/flint/types.pxd +2076 -0
- sage/libs/flint/ulong_extras.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras.pxd +141 -0
- sage/libs/flint/ulong_extras.pyx +21 -0
- sage/libs/flint/ulong_extras_sage.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras_sage.pyx +21 -0
- sage/matrix/all__sagemath_flint.py +1 -0
- sage/matrix/change_ring.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/change_ring.pyx +43 -0
- sage/matrix/matrix_complex_ball_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_complex_ball_dense.pxd +14 -0
- sage/matrix/matrix_complex_ball_dense.pyx +973 -0
- sage/matrix/matrix_cyclo_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_cyclo_dense.pxd +16 -0
- sage/matrix/matrix_cyclo_dense.pyx +1761 -0
- sage/matrix/matrix_integer_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_dense.pxd +32 -0
- sage/matrix/matrix_integer_dense.pyx +5801 -0
- sage/matrix/matrix_integer_dense_hnf.py +1294 -0
- sage/matrix/matrix_integer_dense_saturation.py +346 -0
- sage/matrix/matrix_integer_sparse.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_sparse.pxd +9 -0
- sage/matrix/matrix_integer_sparse.pyx +1090 -0
- sage/matrix/matrix_rational_dense.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_dense.pxd +23 -0
- sage/matrix/matrix_rational_dense.pyx +2995 -0
- sage/matrix/matrix_rational_sparse.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_sparse.pxd +11 -0
- sage/matrix/matrix_rational_sparse.pyx +789 -0
- sage/matrix/misc_flint.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/matrix/misc_flint.pyx +109 -0
- sage/modular/all__sagemath_flint.py +1 -0
- sage/modular/modform/all__sagemath_flint.py +1 -0
- sage/modular/modform/eis_series_cython.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/modular/modform/eis_series_cython.pyx +226 -0
- sage/modular/modsym/all__sagemath_flint.py +1 -0
- sage/modular/modsym/apply.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/modular/modsym/apply.pxd +6 -0
- sage/modular/modsym/apply.pyx +113 -0
- sage/modular/modsym/heilbronn.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/modular/modsym/heilbronn.pyx +966 -0
- sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
- sage/modular/pollack_stevens/dist.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/modular/pollack_stevens/dist.pxd +38 -0
- sage/modular/pollack_stevens/dist.pyx +1439 -0
- sage/quivers/algebra.py +691 -0
- sage/quivers/algebra_elements.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/quivers/algebra_elements.pxd +97 -0
- sage/quivers/algebra_elements.pxi +1324 -0
- sage/quivers/algebra_elements.pyx +1424 -0
- sage/quivers/all.py +1 -0
- sage/quivers/ar_quiver.py +917 -0
- sage/quivers/homspace.py +640 -0
- sage/quivers/morphism.py +1282 -0
- sage/quivers/path_semigroup.py +1155 -0
- sage/quivers/paths.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/quivers/paths.pxd +13 -0
- sage/quivers/paths.pyx +809 -0
- sage/quivers/representation.py +2975 -0
- sage/rings/all__sagemath_flint.py +37 -0
- sage/rings/cif.py +4 -0
- sage/rings/complex_arb.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_arb.pxd +29 -0
- sage/rings/complex_arb.pyx +5176 -0
- sage/rings/complex_interval.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_interval.pxd +30 -0
- sage/rings/complex_interval.pyx +2475 -0
- sage/rings/complex_interval_field.py +711 -0
- sage/rings/convert/all.py +1 -0
- sage/rings/convert/mpfi.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/convert/mpfi.pxd +6 -0
- sage/rings/convert/mpfi.pyx +576 -0
- sage/rings/factorint_flint.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/factorint_flint.pyx +99 -0
- sage/rings/fraction_field_FpT.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/fraction_field_FpT.pxd +28 -0
- sage/rings/fraction_field_FpT.pyx +2043 -0
- sage/rings/imaginary_unit.py +5 -0
- sage/rings/monomials.py +73 -0
- sage/rings/number_field/S_unit_solver.py +2870 -0
- sage/rings/number_field/all__sagemath_flint.py +7 -0
- sage/rings/number_field/bdd_height.py +664 -0
- sage/rings/number_field/class_group.py +762 -0
- sage/rings/number_field/galois_group.py +1307 -0
- sage/rings/number_field/homset.py +612 -0
- sage/rings/number_field/maps.py +687 -0
- sage/rings/number_field/morphism.py +272 -0
- sage/rings/number_field/number_field.py +12820 -0
- sage/rings/number_field/number_field_element.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element.pxd +59 -0
- sage/rings/number_field/number_field_element.pyx +5735 -0
- sage/rings/number_field/number_field_element_quadratic.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
- sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
- sage/rings/number_field/number_field_ideal_rel.py +925 -0
- sage/rings/number_field/number_field_morphisms.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_morphisms.pyx +781 -0
- sage/rings/number_field/number_field_rel.py +2734 -0
- sage/rings/number_field/order.py +2981 -0
- sage/rings/number_field/order_ideal.py +804 -0
- sage/rings/number_field/selmer_group.py +715 -0
- sage/rings/number_field/small_primes_of_degree_one.py +242 -0
- sage/rings/number_field/splitting_field.py +606 -0
- sage/rings/number_field/structure.py +380 -0
- sage/rings/number_field/unit_group.py +721 -0
- sage/rings/padics/all__sagemath_flint.py +3 -0
- sage/rings/polynomial/all__sagemath_flint.py +1 -0
- sage/rings/polynomial/complex_roots.py +312 -0
- sage/rings/polynomial/evaluation_flint.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/evaluation_flint.pxd +7 -0
- sage/rings/polynomial/evaluation_flint.pyx +68 -0
- sage/rings/polynomial/hilbert.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/hilbert.pyx +602 -0
- sage/rings/polynomial/polynomial_complex_arb.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
- sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
- sage/rings/polynomial/polynomial_number_field.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_number_field.pyx +345 -0
- sage/rings/polynomial/polynomial_rational_flint.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
- sage/rings/polynomial/polynomial_zmod_flint.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
- sage/rings/polynomial/real_roots.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/real_roots.pxd +81 -0
- sage/rings/polynomial/real_roots.pyx +4704 -0
- sage/rings/polynomial/refine_root.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/refine_root.pyx +142 -0
- sage/rings/polynomial/weil/all.py +4 -0
- sage/rings/polynomial/weil/power_sums.h +46 -0
- sage/rings/polynomial/weil/weil_polynomials.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
- sage/rings/qqbar.py +9025 -0
- sage/rings/real_arb.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/real_arb.pxd +21 -0
- sage/rings/real_arb.pyx +4065 -0
- sage/rings/real_interval_absolute.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/real_interval_absolute.pyx +1073 -0
- sage/rings/real_mpfi.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/rings/real_mpfi.pyx +5428 -0
- sage/schemes/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.cpython-313-x86_64-linux-gnu.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,2475 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
2
|
+
"""
|
3
|
+
Arbitrary precision complex intervals
|
4
|
+
|
5
|
+
This is a simple complex interval package, using intervals which are
|
6
|
+
axis-aligned rectangles in the complex plane. It has very few special
|
7
|
+
functions, and it does not use any special tricks to keep the size of
|
8
|
+
the intervals down.
|
9
|
+
|
10
|
+
AUTHORS:
|
11
|
+
|
12
|
+
These authors wrote ``complex_mpfr.pyx`` (renamed from ``complex_number.pyx``)::
|
13
|
+
|
14
|
+
- William Stein (2006-01-26): complete rewrite
|
15
|
+
- Joel B. Mohler (2006-12-16): naive rewrite into pyrex
|
16
|
+
- William Stein(2007-01): rewrite of Mohler's rewrite
|
17
|
+
|
18
|
+
Then ``complex_number.pyx`` was copied to ``complex_interval.pyx`` and
|
19
|
+
heavily modified:
|
20
|
+
|
21
|
+
- Carl Witty (2007-10-24): rewrite to become a complex interval package
|
22
|
+
|
23
|
+
- Travis Scrimshaw (2012-10-18): Added documentation to get full coverage.
|
24
|
+
|
25
|
+
|
26
|
+
.. WARNING::
|
27
|
+
|
28
|
+
Mixing symbolic expressions with intervals (in particular, converting
|
29
|
+
constant symbolic expressions to intervals), can lead to incorrect
|
30
|
+
results::
|
31
|
+
|
32
|
+
sage: ref = ComplexIntervalField(100)(ComplexBallField(100).one().airy_ai())
|
33
|
+
sage: ref
|
34
|
+
0.135292416312881415524147423515?
|
35
|
+
sage: val = CIF(airy_ai(1)); val # known bug
|
36
|
+
0.13529241631288142?
|
37
|
+
sage: val.overlaps(ref) # known bug
|
38
|
+
False
|
39
|
+
|
40
|
+
.. TODO::
|
41
|
+
|
42
|
+
Implement :class:`ComplexIntervalFieldElement` multiplicative
|
43
|
+
order similar to :class:`ComplexNumber` multiplicative
|
44
|
+
order with ``_set_multiplicative_order(n)`` and
|
45
|
+
:meth:`ComplexNumber.multiplicative_order()` methods.
|
46
|
+
"""
|
47
|
+
|
48
|
+
# ****************************************************************************
|
49
|
+
# Copyright (C) 2006 William Stein <wstein@gmail.com>
|
50
|
+
#
|
51
|
+
# This program is free software: you can redistribute it and/or modify
|
52
|
+
# it under the terms of the GNU General Public License as published by
|
53
|
+
# the Free Software Foundation, either version 2 of the License, or
|
54
|
+
# (at your option) any later version.
|
55
|
+
# https://www.gnu.org/licenses/
|
56
|
+
# ****************************************************************************
|
57
|
+
|
58
|
+
from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE
|
59
|
+
from cysignals.signals cimport sig_on, sig_off
|
60
|
+
|
61
|
+
from sage.libs.gmp.mpz cimport mpz_sgn, mpz_cmpabs_ui
|
62
|
+
from sage.libs.mpfr cimport *
|
63
|
+
from sage.libs.mpfi cimport *
|
64
|
+
from sage.libs.flint.fmpz cimport *
|
65
|
+
from sage.libs.mpfr cimport MPFR_RNDU
|
66
|
+
from sage.arith.constants cimport LOG_TEN_TWO_PLUS_EPSILON
|
67
|
+
|
68
|
+
from sage.structure.element cimport FieldElement
|
69
|
+
from sage.structure.parent cimport Parent
|
70
|
+
from sage.rings.complex_mpfr cimport ComplexNumber
|
71
|
+
from sage.rings.integer cimport Integer
|
72
|
+
cimport sage.rings.real_mpfi as real_mpfi
|
73
|
+
from sage.rings.real_mpfr cimport RealNumber
|
74
|
+
from sage.rings.convert.mpfi cimport mpfi_set_sage
|
75
|
+
from sage.rings.infinity import infinity
|
76
|
+
|
77
|
+
|
78
|
+
def is_ComplexIntervalFieldElement(x):
|
79
|
+
"""
|
80
|
+
Check if ``x`` is a :class:`ComplexIntervalFieldElement`.
|
81
|
+
|
82
|
+
EXAMPLES::
|
83
|
+
|
84
|
+
sage: from sage.rings.complex_interval import is_ComplexIntervalFieldElement as is_CIFE
|
85
|
+
sage: is_CIFE(CIF(2))
|
86
|
+
doctest:warning...
|
87
|
+
DeprecationWarning: The function is_ComplexIntervalFieldElement is deprecated;
|
88
|
+
use 'isinstance(..., ComplexIntervalFieldElement)' instead.
|
89
|
+
See https://github.com/sagemath/sage/issues/38128 for details.
|
90
|
+
True
|
91
|
+
sage: is_CIFE(CC(2))
|
92
|
+
False
|
93
|
+
"""
|
94
|
+
from sage.misc.superseded import deprecation_cython
|
95
|
+
deprecation_cython(38128,
|
96
|
+
"The function is_ComplexIntervalFieldElement is deprecated; "
|
97
|
+
"use 'isinstance(..., ComplexIntervalFieldElement)' instead.")
|
98
|
+
return isinstance(x, ComplexIntervalFieldElement)
|
99
|
+
|
100
|
+
|
101
|
+
cdef class ComplexIntervalFieldElement(FieldElement):
|
102
|
+
"""
|
103
|
+
A complex interval.
|
104
|
+
|
105
|
+
EXAMPLES::
|
106
|
+
|
107
|
+
sage: I = CIF.gen()
|
108
|
+
sage: b = 3/2 + 5/2*I
|
109
|
+
sage: TestSuite(b).run()
|
110
|
+
"""
|
111
|
+
def __cinit__(self, parent, *args):
|
112
|
+
"""
|
113
|
+
TESTS::
|
114
|
+
|
115
|
+
sage: from sage.rings.complex_interval import ComplexIntervalFieldElement
|
116
|
+
sage: ComplexIntervalFieldElement.__new__(ComplexIntervalFieldElement)
|
117
|
+
Traceback (most recent call last):
|
118
|
+
...
|
119
|
+
TypeError: ...__cinit__() takes at least 1 positional argument (0 given)
|
120
|
+
sage: ComplexIntervalFieldElement.__new__(ComplexIntervalFieldElement, CIF)
|
121
|
+
[.. NaN ..] + [.. NaN ..]*I
|
122
|
+
"""
|
123
|
+
self._parent = <Parent?>parent
|
124
|
+
self._prec = parent._prec
|
125
|
+
self._multiplicative_order = None
|
126
|
+
mpfi_init2(self.__re, self._prec)
|
127
|
+
mpfi_init2(self.__im, self._prec)
|
128
|
+
|
129
|
+
def __init__(self, parent, real, imag=None, int base=10):
|
130
|
+
"""
|
131
|
+
Initialize a complex number (interval).
|
132
|
+
|
133
|
+
EXAMPLES::
|
134
|
+
|
135
|
+
sage: CIF(1.5, 2.5)
|
136
|
+
1.5000000000000000? + 2.5000000000000000?*I
|
137
|
+
sage: CIF((1.5, 2.5))
|
138
|
+
1.5000000000000000? + 2.5000000000000000?*I
|
139
|
+
sage: CIF(1.5 + 2.5*I)
|
140
|
+
1.5000000000000000? + 2.5000000000000000?*I
|
141
|
+
"""
|
142
|
+
self._multiplicative_order = None
|
143
|
+
if real is None:
|
144
|
+
mpfi_set_ui(self.__re, 0)
|
145
|
+
mpfi_set_ui(self.__im, 0)
|
146
|
+
elif imag is None:
|
147
|
+
# "real" may be real or complex
|
148
|
+
mpfi_set_sage(self.__re, self.__im, real, parent, base)
|
149
|
+
else:
|
150
|
+
# Set real and imaginary parts separately
|
151
|
+
mpfi_set_sage(self.__re, NULL, real, parent, base)
|
152
|
+
mpfi_set_sage(self.__im, NULL, imag, parent, base)
|
153
|
+
|
154
|
+
def __dealloc__(self):
|
155
|
+
if self._parent is not None:
|
156
|
+
mpfi_clear(self.__re)
|
157
|
+
mpfi_clear(self.__im)
|
158
|
+
|
159
|
+
def _repr_(self):
|
160
|
+
"""
|
161
|
+
Return a string representation of ``self``.
|
162
|
+
|
163
|
+
EXAMPLES::
|
164
|
+
|
165
|
+
sage: CIF(1.5) # indirect doctest
|
166
|
+
1.5000000000000000?
|
167
|
+
sage: CIF(1.5, 2.5) # indirect doctest
|
168
|
+
1.5000000000000000? + 2.5000000000000000?*I
|
169
|
+
"""
|
170
|
+
return self.str(10)
|
171
|
+
|
172
|
+
def __hash__(self):
|
173
|
+
"""
|
174
|
+
Return the hash value of ``self``.
|
175
|
+
|
176
|
+
EXAMPLES::
|
177
|
+
|
178
|
+
sage: C = ComplexIntervalField()
|
179
|
+
sage: hash(CIF(1.5)) == hash(C(1.5))
|
180
|
+
True
|
181
|
+
sage: hash(CIF(1.5, 2.5)) != hash(CIF(2,3))
|
182
|
+
True
|
183
|
+
"""
|
184
|
+
return hash(self.str())
|
185
|
+
|
186
|
+
def __getitem__(self, i):
|
187
|
+
"""
|
188
|
+
Return either the real or imaginary component of ``self`` depending
|
189
|
+
on the choice of ``i``: real (``i=0``), imaginary (``i=1``)
|
190
|
+
|
191
|
+
INPUT:
|
192
|
+
|
193
|
+
- ``i`` -- 0 or 1
|
194
|
+
|
195
|
+
- ``0`` -- will return the real component of ``self``
|
196
|
+
- ``1`` -- will return the imaginary component of ``self``
|
197
|
+
|
198
|
+
EXAMPLES::
|
199
|
+
|
200
|
+
sage: z = CIF(1.5, 2.5)
|
201
|
+
sage: z[0]
|
202
|
+
1.5000000000000000?
|
203
|
+
sage: z[1]
|
204
|
+
2.5000000000000000?
|
205
|
+
"""
|
206
|
+
if i == 0:
|
207
|
+
return self.real()
|
208
|
+
elif i == 1:
|
209
|
+
return self.imag()
|
210
|
+
raise IndexError("i must be between 0 and 1.")
|
211
|
+
|
212
|
+
def __reduce__(self):
|
213
|
+
"""
|
214
|
+
Pickling support.
|
215
|
+
|
216
|
+
TESTS::
|
217
|
+
|
218
|
+
sage: a = CIF(1 + I)
|
219
|
+
sage: loads(dumps(a)) == a
|
220
|
+
True
|
221
|
+
"""
|
222
|
+
# TODO: This is potentially slow -- make a 1 version that
|
223
|
+
# is native and much faster -- doesn't use .real()/.imag()
|
224
|
+
return (make_ComplexIntervalFieldElement0, (self._parent, self.real(), self.imag()))
|
225
|
+
|
226
|
+
def str(self, base=10, style=None):
|
227
|
+
"""
|
228
|
+
Return a string representation of ``self``.
|
229
|
+
|
230
|
+
EXAMPLES::
|
231
|
+
|
232
|
+
sage: CIF(1.5).str()
|
233
|
+
'1.5000000000000000?'
|
234
|
+
sage: CIF(1.5, 2.5).str()
|
235
|
+
'1.5000000000000000? + 2.5000000000000000?*I'
|
236
|
+
sage: CIF(1.5, -2.5).str()
|
237
|
+
'1.5000000000000000? - 2.5000000000000000?*I'
|
238
|
+
sage: CIF(0, -2.5).str()
|
239
|
+
'-2.5000000000000000?*I'
|
240
|
+
sage: CIF(1.5).str(base=3)
|
241
|
+
'1.1111111111111111111111111111111112?'
|
242
|
+
sage: CIF(1, pi).str(style='brackets') # needs sage.symbolic
|
243
|
+
'[1.0000000000000000 .. 1.0000000000000000] + [3.1415926535897931 .. 3.1415926535897936]*I'
|
244
|
+
|
245
|
+
.. SEEALSO::
|
246
|
+
|
247
|
+
- :meth:`RealIntervalFieldElement.str`
|
248
|
+
"""
|
249
|
+
s = ""
|
250
|
+
if not self.real().is_zero():
|
251
|
+
s = self.real().str(base=base, style=style)
|
252
|
+
if not self.imag().is_zero():
|
253
|
+
y = self.imag()
|
254
|
+
if s:
|
255
|
+
if y < 0:
|
256
|
+
s += " - "
|
257
|
+
y = -y
|
258
|
+
else:
|
259
|
+
s += " + "
|
260
|
+
s += "%s*I" % y.str(base=base, style=style)
|
261
|
+
if not s:
|
262
|
+
s = "0"
|
263
|
+
return s
|
264
|
+
|
265
|
+
def _mpfr_(self, parent):
|
266
|
+
r"""
|
267
|
+
If the imaginary part is zero, convert this interval field element
|
268
|
+
to a real number.
|
269
|
+
|
270
|
+
Fail if the imaginary part is not exactly zero.
|
271
|
+
|
272
|
+
INPUT:
|
273
|
+
|
274
|
+
- ``parent`` -- :class:`~sage.rings.real_mpfr.RealField_class`,
|
275
|
+
target parent
|
276
|
+
|
277
|
+
EXAMPLES::
|
278
|
+
|
279
|
+
sage: RR(CIF(1/3))
|
280
|
+
0.333333333333333
|
281
|
+
sage: RR(CIF(1, 1/3) - CIF(0, 1/3))
|
282
|
+
Traceback (most recent call last):
|
283
|
+
...
|
284
|
+
TypeError: unable to convert complex interval 1 + 0.?e-16*I to real number
|
285
|
+
"""
|
286
|
+
if self.imag() == 0:
|
287
|
+
return parent(self.real())
|
288
|
+
else:
|
289
|
+
raise TypeError(f"unable to convert complex interval {self} to real number")
|
290
|
+
|
291
|
+
def plot(self, pointsize=10, **kwds):
|
292
|
+
r"""
|
293
|
+
Plot a complex interval as a rectangle.
|
294
|
+
|
295
|
+
EXAMPLES::
|
296
|
+
|
297
|
+
sage: sum(plot(CIF(RIF(1/k, 1/k), RIF(-k, k))) for k in [1..10]) # needs sage.plot
|
298
|
+
Graphics object consisting of 20 graphics primitives
|
299
|
+
|
300
|
+
Exact and nearly exact points are still visible::
|
301
|
+
|
302
|
+
sage: # needs sage.plot sage.symbolic
|
303
|
+
sage: plot(CIF(pi, 1), color='red') + plot(CIF(1, e), color='purple') + plot(CIF(-1, -1))
|
304
|
+
Graphics object consisting of 6 graphics primitives
|
305
|
+
|
306
|
+
A demonstration that `z \mapsto z^2` acts chaotically on `|z|=1`::
|
307
|
+
|
308
|
+
sage: # needs sage.plot sage.symbolic
|
309
|
+
sage: z = CIF(0, 2*pi/1000).exp()
|
310
|
+
sage: g = Graphics()
|
311
|
+
sage: for i in range(40):
|
312
|
+
....: z = z^2
|
313
|
+
....: g += z.plot(color=(1./(40-i), 0, 1))
|
314
|
+
...
|
315
|
+
sage: g
|
316
|
+
Graphics object consisting of 80 graphics primitives
|
317
|
+
"""
|
318
|
+
from sage.plot.polygon import polygon2d
|
319
|
+
x, y = self.real(), self.imag()
|
320
|
+
x0, y0 = x.lower(), y.lower()
|
321
|
+
x1, y1 = x.upper(), y.upper()
|
322
|
+
g = polygon2d([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)],
|
323
|
+
thickness=pointsize/4, **kwds)
|
324
|
+
# Nearly empty polygons don't show up.
|
325
|
+
g += self.center().plot(pointsize=pointsize, **kwds)
|
326
|
+
return g
|
327
|
+
|
328
|
+
def _latex_(self):
|
329
|
+
"""
|
330
|
+
Return a latex representation of ``self``.
|
331
|
+
|
332
|
+
EXAMPLES::
|
333
|
+
|
334
|
+
sage: latex(CIF(1.5, -2.5)) # indirect doctest
|
335
|
+
1.5000000000000000? - 2.5000000000000000?i
|
336
|
+
sage: latex(CIF(0, 3e200)) # indirect doctest
|
337
|
+
3.0000000000000000? \times 10^{200}i
|
338
|
+
"""
|
339
|
+
import re
|
340
|
+
s = self.str().replace('*I', 'i')
|
341
|
+
return re.sub(r"e(-?\d+)", r" \\times 10^{\1}", s)
|
342
|
+
|
343
|
+
def bisection(self):
|
344
|
+
"""
|
345
|
+
Return the bisection of ``self`` into four intervals whose union is
|
346
|
+
``self`` and intersection is :meth:`center()`.
|
347
|
+
|
348
|
+
EXAMPLES::
|
349
|
+
|
350
|
+
sage: z = CIF(RIF(2, 3), RIF(-5, -4))
|
351
|
+
sage: z.bisection()
|
352
|
+
(3.? - 5.?*I, 3.? - 5.?*I, 3.? - 5.?*I, 3.? - 5.?*I)
|
353
|
+
sage: for z in z.bisection():
|
354
|
+
....: print(z.real().endpoints())
|
355
|
+
....: print(z.imag().endpoints())
|
356
|
+
(2.00000000000000, 2.50000000000000)
|
357
|
+
(-5.00000000000000, -4.50000000000000)
|
358
|
+
(2.50000000000000, 3.00000000000000)
|
359
|
+
(-5.00000000000000, -4.50000000000000)
|
360
|
+
(2.00000000000000, 2.50000000000000)
|
361
|
+
(-4.50000000000000, -4.00000000000000)
|
362
|
+
(2.50000000000000, 3.00000000000000)
|
363
|
+
(-4.50000000000000, -4.00000000000000)
|
364
|
+
|
365
|
+
sage: # needs sage.symbolic
|
366
|
+
sage: z = CIF(RIF(sqrt(2), sqrt(3)), RIF(e, pi))
|
367
|
+
sage: a, b, c, d = z.bisection()
|
368
|
+
sage: a.intersection(b).intersection(c).intersection(d) == CIF(z.center())
|
369
|
+
True
|
370
|
+
sage: zz = a.union(b).union(c).union(c)
|
371
|
+
sage: zz.real().endpoints() == z.real().endpoints()
|
372
|
+
True
|
373
|
+
sage: zz.imag().endpoints() == z.imag().endpoints()
|
374
|
+
True
|
375
|
+
"""
|
376
|
+
a00 = self._new()
|
377
|
+
mpfr_set(&a00.__re.left, &self.__re.left, MPFR_RNDN)
|
378
|
+
mpfi_mid(&a00.__re.right, self.__re)
|
379
|
+
mpfr_set(&a00.__im.left, &self.__im.left, MPFR_RNDN)
|
380
|
+
mpfi_mid(&a00.__im.right, self.__im)
|
381
|
+
|
382
|
+
a01 = self._new()
|
383
|
+
mpfr_set(&a01.__re.left, &a00.__re.right, MPFR_RNDN)
|
384
|
+
mpfr_set(&a01.__re.right, &self.__re.right, MPFR_RNDN)
|
385
|
+
mpfi_set(a01.__im, a00.__im)
|
386
|
+
|
387
|
+
a10 = self._new()
|
388
|
+
mpfi_set(a10.__re, a00.__re)
|
389
|
+
mpfi_mid(&a10.__im.left, self.__im)
|
390
|
+
mpfr_set(&a10.__im.right, &self.__im.right, MPFR_RNDN)
|
391
|
+
|
392
|
+
a11 = self._new()
|
393
|
+
mpfi_set(a11.__re, a01.__re)
|
394
|
+
mpfi_set(a11.__im, a10.__im)
|
395
|
+
|
396
|
+
return a00, a01, a10, a11
|
397
|
+
|
398
|
+
def is_exact(self):
|
399
|
+
"""
|
400
|
+
Return whether this complex interval is exact (i.e. contains exactly
|
401
|
+
one complex value).
|
402
|
+
|
403
|
+
EXAMPLES::
|
404
|
+
|
405
|
+
sage: CIF(3).is_exact()
|
406
|
+
True
|
407
|
+
sage: CIF(0, 2).is_exact()
|
408
|
+
True
|
409
|
+
sage: CIF(-4, 0).sqrt().is_exact()
|
410
|
+
True
|
411
|
+
sage: CIF(-5, 0).sqrt().is_exact()
|
412
|
+
False
|
413
|
+
sage: CIF(0, 2*pi).is_exact() # needs sage.symbolic
|
414
|
+
False
|
415
|
+
sage: CIF(e).is_exact() # needs sage.symbolic
|
416
|
+
False
|
417
|
+
sage: CIF(1e100).is_exact()
|
418
|
+
True
|
419
|
+
sage: (CIF(1e100) + 1).is_exact()
|
420
|
+
False
|
421
|
+
"""
|
422
|
+
return mpfr_equal_p(&self.__re.left, &self.__re.right) and \
|
423
|
+
mpfr_equal_p(&self.__im.left, &self.__im.right)
|
424
|
+
|
425
|
+
def endpoints(self):
|
426
|
+
"""
|
427
|
+
Return the 4 corners of the rectangle in the complex plane
|
428
|
+
defined by this interval.
|
429
|
+
|
430
|
+
OUTPUT: a 4-tuple of complex numbers
|
431
|
+
(lower left, upper right, upper left, lower right)
|
432
|
+
|
433
|
+
.. SEEALSO::
|
434
|
+
|
435
|
+
:meth:`edges` which returns the 4 edges of the rectangle.
|
436
|
+
|
437
|
+
EXAMPLES::
|
438
|
+
|
439
|
+
sage: CIF(RIF(1,2), RIF(3,4)).endpoints()
|
440
|
+
(1.00000000000000 + 3.00000000000000*I,
|
441
|
+
2.00000000000000 + 4.00000000000000*I,
|
442
|
+
1.00000000000000 + 4.00000000000000*I,
|
443
|
+
2.00000000000000 + 3.00000000000000*I)
|
444
|
+
sage: ComplexIntervalField(20)(-2).log().endpoints()
|
445
|
+
(0.69315 + 3.1416*I,
|
446
|
+
0.69315 + 3.1416*I,
|
447
|
+
0.69315 + 3.1416*I,
|
448
|
+
0.69315 + 3.1416*I)
|
449
|
+
"""
|
450
|
+
left, right = self.real().endpoints()
|
451
|
+
lower, upper = self.imag().endpoints()
|
452
|
+
CC = self._parent.middle_field()
|
453
|
+
return (CC(left, lower), CC(right, upper),
|
454
|
+
CC(left, upper), CC(right, lower))
|
455
|
+
|
456
|
+
def edges(self):
|
457
|
+
"""
|
458
|
+
Return the 4 edges of the rectangle in the complex plane
|
459
|
+
defined by this interval as intervals.
|
460
|
+
|
461
|
+
OUTPUT: a 4-tuple of complex intervals
|
462
|
+
(left edge, right edge, lower edge, upper edge)
|
463
|
+
|
464
|
+
.. SEEALSO::
|
465
|
+
|
466
|
+
:meth:`endpoints` which returns the 4 corners of the
|
467
|
+
rectangle.
|
468
|
+
|
469
|
+
EXAMPLES::
|
470
|
+
|
471
|
+
sage: CIF(RIF(1,2), RIF(3,4)).edges()
|
472
|
+
(1 + 4.?*I, 2 + 4.?*I, 2.? + 3*I, 2.? + 4*I)
|
473
|
+
sage: ComplexIntervalField(20)(-2).log().edges()
|
474
|
+
(0.69314671? + 3.14160?*I,
|
475
|
+
0.69314766? + 3.14160?*I,
|
476
|
+
0.693147? + 3.1415902?*I,
|
477
|
+
0.693147? + 3.1415940?*I)
|
478
|
+
"""
|
479
|
+
left = self._new()
|
480
|
+
right = self._new()
|
481
|
+
lower = self._new()
|
482
|
+
upper = self._new()
|
483
|
+
cdef mpfr_t x
|
484
|
+
mpfr_init2(x, self.prec())
|
485
|
+
|
486
|
+
# Set real parts
|
487
|
+
mpfi_get_left(x, self.__re)
|
488
|
+
mpfi_set_fr(left.__re, x)
|
489
|
+
mpfi_get_right(x, self.__re)
|
490
|
+
mpfi_set_fr(right.__re, x)
|
491
|
+
mpfi_set(lower.__re, self.__re)
|
492
|
+
mpfi_set(upper.__re, self.__re)
|
493
|
+
|
494
|
+
# Set imaginary parts
|
495
|
+
mpfi_get_left(x, self.__im)
|
496
|
+
mpfi_set_fr(lower.__im, x)
|
497
|
+
mpfi_get_right(x, self.__im)
|
498
|
+
mpfi_set_fr(upper.__im, x)
|
499
|
+
mpfi_set(left.__im, self.__im)
|
500
|
+
mpfi_set(right.__im, self.__im)
|
501
|
+
|
502
|
+
mpfr_clear(x)
|
503
|
+
|
504
|
+
return (left, right, lower, upper)
|
505
|
+
|
506
|
+
def diameter(self):
|
507
|
+
"""
|
508
|
+
Return a somewhat-arbitrarily defined "diameter" for this interval.
|
509
|
+
|
510
|
+
The diameter of an interval is the maximum of the diameter of the real
|
511
|
+
and imaginary components, where diameter on a real interval is defined
|
512
|
+
as absolute diameter if the interval contains zero, and relative
|
513
|
+
diameter otherwise.
|
514
|
+
|
515
|
+
EXAMPLES::
|
516
|
+
|
517
|
+
sage: CIF(RIF(-1, 1), RIF(13, 17)).diameter()
|
518
|
+
2.00000000000000
|
519
|
+
sage: CIF(RIF(-0.1, 0.1), RIF(13, 17)).diameter()
|
520
|
+
0.266666666666667
|
521
|
+
sage: CIF(RIF(-1, 1), 15).diameter()
|
522
|
+
2.00000000000000
|
523
|
+
"""
|
524
|
+
cdef RealNumber diam
|
525
|
+
diam = RealNumber(self._parent.real_field().middle_field(), None)
|
526
|
+
cdef mpfr_t tmp
|
527
|
+
mpfr_init2(tmp, self.prec())
|
528
|
+
mpfi_diam(diam.value, self.__re)
|
529
|
+
mpfi_diam(tmp, self.__im)
|
530
|
+
mpfr_max(diam.value, diam.value, tmp, MPFR_RNDU)
|
531
|
+
mpfr_clear(tmp)
|
532
|
+
return diam
|
533
|
+
|
534
|
+
def overlaps(self, ComplexIntervalFieldElement other):
|
535
|
+
"""
|
536
|
+
Return ``True`` if ``self`` and ``other`` are intervals with at least
|
537
|
+
one value in common.
|
538
|
+
|
539
|
+
EXAMPLES::
|
540
|
+
|
541
|
+
sage: CIF(0).overlaps(CIF(RIF(0, 1), RIF(-1, 0)))
|
542
|
+
True
|
543
|
+
sage: CIF(1).overlaps(CIF(1, 1))
|
544
|
+
False
|
545
|
+
"""
|
546
|
+
return mpfr_greaterequal_p(&self.__re.right, &other.__re.left) \
|
547
|
+
and mpfr_greaterequal_p(&other.__re.right, &self.__re.left) \
|
548
|
+
and mpfr_greaterequal_p(&self.__im.right, &other.__im.left) \
|
549
|
+
and mpfr_greaterequal_p(&other.__im.right, &self.__im.left)
|
550
|
+
|
551
|
+
def intersection(self, other):
|
552
|
+
"""
|
553
|
+
Return the intersection of the two complex intervals ``self`` and
|
554
|
+
``other``.
|
555
|
+
|
556
|
+
EXAMPLES::
|
557
|
+
|
558
|
+
sage: CIF(RIF(1, 3), RIF(1, 3)).intersection(CIF(RIF(2, 4), RIF(2, 4))).str(style='brackets')
|
559
|
+
'[2.0000000000000000 .. 3.0000000000000000] + [2.0000000000000000 .. 3.0000000000000000]*I'
|
560
|
+
sage: CIF(RIF(1, 2), RIF(1, 3)).intersection(CIF(RIF(3, 4), RIF(2, 4)))
|
561
|
+
Traceback (most recent call last):
|
562
|
+
...
|
563
|
+
ValueError: intersection of non-overlapping intervals
|
564
|
+
"""
|
565
|
+
x = self._new()
|
566
|
+
cdef ComplexIntervalFieldElement other_intv
|
567
|
+
if isinstance(other, ComplexIntervalFieldElement):
|
568
|
+
other_intv = other
|
569
|
+
else:
|
570
|
+
# Let type errors from _coerce_ propagate...
|
571
|
+
other_intv = self._parent(other)
|
572
|
+
|
573
|
+
mpfi_intersect(x.__re, self.__re, other_intv.__re)
|
574
|
+
mpfi_intersect(x.__im, self.__im, other_intv.__im)
|
575
|
+
if mpfr_less_p(&x.__re.right, &x.__re.left) \
|
576
|
+
or mpfr_less_p(&x.__im.right, &x.__im.left):
|
577
|
+
raise ValueError("intersection of non-overlapping intervals")
|
578
|
+
|
579
|
+
return x
|
580
|
+
|
581
|
+
def union(self, other):
|
582
|
+
"""
|
583
|
+
Return the smallest complex interval including the
|
584
|
+
two complex intervals ``self`` and ``other``.
|
585
|
+
|
586
|
+
EXAMPLES::
|
587
|
+
|
588
|
+
sage: CIF(0).union(CIF(5, 5)).str(style='brackets')
|
589
|
+
'[0.0000000000000000 .. 5.0000000000000000] + [0.0000000000000000 .. 5.0000000000000000]*I'
|
590
|
+
"""
|
591
|
+
x = self._new()
|
592
|
+
cdef ComplexIntervalFieldElement other_intv
|
593
|
+
if isinstance(other, ComplexIntervalFieldElement):
|
594
|
+
other_intv = other
|
595
|
+
else:
|
596
|
+
# Let type errors from _coerce_ propagate...
|
597
|
+
other_intv = self._parent(other)
|
598
|
+
|
599
|
+
mpfi_union(x.__re, self.__re, other_intv.__re)
|
600
|
+
mpfi_union(x.__im, self.__im, other_intv.__im)
|
601
|
+
return x
|
602
|
+
|
603
|
+
def magnitude(self):
|
604
|
+
"""
|
605
|
+
The largest absolute value of the elements of the interval, rounded
|
606
|
+
away from zero.
|
607
|
+
|
608
|
+
OUTPUT: a real number with rounding mode ``RNDU``
|
609
|
+
|
610
|
+
EXAMPLES::
|
611
|
+
|
612
|
+
sage: CIF(RIF(-1,1), RIF(-1,1)).magnitude()
|
613
|
+
1.41421356237310
|
614
|
+
sage: CIF(RIF(1,2), RIF(3,4)).magnitude()
|
615
|
+
4.47213595499958
|
616
|
+
sage: parent(CIF(1).magnitude())
|
617
|
+
Real Field with 53 bits of precision and rounding RNDU
|
618
|
+
"""
|
619
|
+
cdef real_mpfi.RealIntervalField_class RIF = self._parent.real_field()
|
620
|
+
cdef RealNumber x = RIF.__upper_field._new()
|
621
|
+
cdef RealNumber y = RIF.__upper_field._new()
|
622
|
+
mpfi_mag(x.value, self.__re)
|
623
|
+
mpfi_mag(y.value, self.__im)
|
624
|
+
mpfr_hypot(x.value, x.value, y.value, MPFR_RNDA)
|
625
|
+
return x
|
626
|
+
|
627
|
+
def mignitude(self):
|
628
|
+
"""
|
629
|
+
The smallest absolute value of the elements of the interval, rounded
|
630
|
+
towards zero.
|
631
|
+
|
632
|
+
OUTPUT: a real number with rounding mode ``RNDD``
|
633
|
+
|
634
|
+
EXAMPLES::
|
635
|
+
|
636
|
+
sage: CIF(RIF(-1,1), RIF(-1,1)).mignitude()
|
637
|
+
0.000000000000000
|
638
|
+
sage: CIF(RIF(1,2), RIF(3,4)).mignitude()
|
639
|
+
3.16227766016837
|
640
|
+
sage: parent(CIF(1).mignitude())
|
641
|
+
Real Field with 53 bits of precision and rounding RNDD
|
642
|
+
"""
|
643
|
+
cdef real_mpfi.RealIntervalField_class RIF = self._parent.real_field()
|
644
|
+
cdef RealNumber x = RIF.__lower_field._new()
|
645
|
+
cdef RealNumber y = RIF.__lower_field._new()
|
646
|
+
mpfi_mig(x.value, self.__re)
|
647
|
+
mpfi_mig(y.value, self.__im)
|
648
|
+
mpfr_hypot(x.value, x.value, y.value, MPFR_RNDZ)
|
649
|
+
return x
|
650
|
+
|
651
|
+
def center(self):
|
652
|
+
"""
|
653
|
+
Return the closest floating-point approximation to the center
|
654
|
+
of the interval.
|
655
|
+
|
656
|
+
EXAMPLES::
|
657
|
+
|
658
|
+
sage: CIF(RIF(1, 2), RIF(3, 4)).center()
|
659
|
+
1.50000000000000 + 3.50000000000000*I
|
660
|
+
"""
|
661
|
+
cdef ComplexNumber center
|
662
|
+
center = ComplexNumber(self._parent.middle_field(), None)
|
663
|
+
mpfi_mid(center.__re, self.__re)
|
664
|
+
mpfi_mid(center.__im, self.__im)
|
665
|
+
|
666
|
+
return center
|
667
|
+
|
668
|
+
def __contains__(self, other):
|
669
|
+
"""
|
670
|
+
Test whether ``other`` is totally contained in ``self``.
|
671
|
+
|
672
|
+
EXAMPLES::
|
673
|
+
|
674
|
+
sage: CIF(1, 1) in CIF(RIF(1, 2), RIF(1, 2))
|
675
|
+
True
|
676
|
+
"""
|
677
|
+
# This could be more efficient (and support more types for "other").
|
678
|
+
return (other.real() in self.real()) and (other.imag() in self.imag())
|
679
|
+
|
680
|
+
def contains_zero(self):
|
681
|
+
"""
|
682
|
+
Return ``True`` if ``self`` is an interval containing zero.
|
683
|
+
|
684
|
+
EXAMPLES::
|
685
|
+
|
686
|
+
sage: CIF(0).contains_zero()
|
687
|
+
True
|
688
|
+
sage: CIF(RIF(-1, 1), 1).contains_zero()
|
689
|
+
False
|
690
|
+
"""
|
691
|
+
return mpfi_has_zero(self.__re) and mpfi_has_zero(self.__im)
|
692
|
+
|
693
|
+
cpdef _add_(self, right):
|
694
|
+
"""
|
695
|
+
Add ``self`` and ``right``.
|
696
|
+
|
697
|
+
EXAMPLES::
|
698
|
+
|
699
|
+
sage: CIF(2,-3)._add_(CIF(1,-2))
|
700
|
+
3 - 5*I
|
701
|
+
"""
|
702
|
+
x = self._new()
|
703
|
+
mpfi_add(x.__re, self.__re, (<ComplexIntervalFieldElement>right).__re)
|
704
|
+
mpfi_add(x.__im, self.__im, (<ComplexIntervalFieldElement>right).__im)
|
705
|
+
return x
|
706
|
+
|
707
|
+
cpdef _sub_(self, right):
|
708
|
+
"""
|
709
|
+
Subtract ``self`` by ``right``.
|
710
|
+
|
711
|
+
EXAMPLES::
|
712
|
+
|
713
|
+
sage: CIF(2,-3)._sub_(CIF(1,-2))
|
714
|
+
1 - 1*I
|
715
|
+
"""
|
716
|
+
x = self._new()
|
717
|
+
mpfi_sub(x.__re, self.__re, (<ComplexIntervalFieldElement>right).__re)
|
718
|
+
mpfi_sub(x.__im, self.__im, (<ComplexIntervalFieldElement>right).__im)
|
719
|
+
return x
|
720
|
+
|
721
|
+
cpdef _mul_(self, right):
|
722
|
+
"""
|
723
|
+
Multiply ``self`` and ``right``.
|
724
|
+
|
725
|
+
EXAMPLES::
|
726
|
+
|
727
|
+
sage: CIF(2,-3)._mul_(CIF(1,-2))
|
728
|
+
-4 - 7*I
|
729
|
+
"""
|
730
|
+
x = self._new()
|
731
|
+
cdef mpfi_t t0, t1
|
732
|
+
mpfi_init2(t0, self._prec)
|
733
|
+
mpfi_init2(t1, self._prec)
|
734
|
+
mpfi_mul(t0, self.__re, (<ComplexIntervalFieldElement>right).__re)
|
735
|
+
mpfi_mul(t1, self.__im, (<ComplexIntervalFieldElement>right).__im)
|
736
|
+
mpfi_sub(x.__re, t0, t1)
|
737
|
+
mpfi_mul(t0, self.__re, (<ComplexIntervalFieldElement>right).__im)
|
738
|
+
mpfi_mul(t1, self.__im, (<ComplexIntervalFieldElement>right).__re)
|
739
|
+
mpfi_add(x.__im, t0, t1)
|
740
|
+
mpfi_clear(t0)
|
741
|
+
mpfi_clear(t1)
|
742
|
+
return x
|
743
|
+
|
744
|
+
def norm(self):
|
745
|
+
r"""
|
746
|
+
Return the norm of this complex number.
|
747
|
+
|
748
|
+
If `c = a + bi` is a complex number, then the norm of `c` is defined as
|
749
|
+
the product of `c` and its complex conjugate:
|
750
|
+
|
751
|
+
.. MATH::
|
752
|
+
|
753
|
+
\text{norm}(c)
|
754
|
+
=
|
755
|
+
\text{norm}(a + bi)
|
756
|
+
=
|
757
|
+
c \cdot \overline{c}
|
758
|
+
=
|
759
|
+
a^2 + b^2.
|
760
|
+
|
761
|
+
The norm of a complex number is different from its absolute value.
|
762
|
+
The absolute value of a complex number is defined to be the square
|
763
|
+
root of its norm. A typical use of the complex norm is in the
|
764
|
+
integral domain `\ZZ[i]` of Gaussian integers, where the norm of
|
765
|
+
each Gaussian integer `c = a + bi` is defined as its complex norm.
|
766
|
+
|
767
|
+
.. SEEALSO::
|
768
|
+
|
769
|
+
- :meth:`sage.rings.complex_double.ComplexDoubleElement.norm`
|
770
|
+
|
771
|
+
EXAMPLES::
|
772
|
+
|
773
|
+
sage: CIF(2, 1).norm()
|
774
|
+
5
|
775
|
+
sage: CIF(1, -2).norm()
|
776
|
+
5
|
777
|
+
"""
|
778
|
+
x = self._new_real()
|
779
|
+
|
780
|
+
cdef mpfi_t t
|
781
|
+
mpfi_init2(t, self._prec)
|
782
|
+
|
783
|
+
mpfi_sqr(x.value, self.__re)
|
784
|
+
mpfi_sqr(t, self.__im)
|
785
|
+
|
786
|
+
mpfi_add(x.value, x.value, t)
|
787
|
+
|
788
|
+
mpfi_clear(t)
|
789
|
+
return x
|
790
|
+
|
791
|
+
cpdef _div_(self, right):
|
792
|
+
"""
|
793
|
+
Divide ``self`` by ``right``.
|
794
|
+
|
795
|
+
EXAMPLES::
|
796
|
+
|
797
|
+
sage: CIF(2,-3)._div_(CIF(1,-2))
|
798
|
+
1.600000000000000? + 0.200000000000000?*I
|
799
|
+
sage: a = CIF((1, 2), (3, 4))
|
800
|
+
sage: b = CIF(-1, (2, 3))
|
801
|
+
sage: c = a/b
|
802
|
+
sage: c.endpoints()
|
803
|
+
(0.500000000000000 - 1.60000000000000*I,
|
804
|
+
1.50000000000000 - 0.600000000000000*I,
|
805
|
+
0.500000000000000 - 0.600000000000000*I,
|
806
|
+
1.50000000000000 - 1.60000000000000*I)
|
807
|
+
sage: c = b/a
|
808
|
+
sage: c.endpoints()
|
809
|
+
(0.246153846153846 + 0.317647058823529*I,
|
810
|
+
0.841176470588236 + 0.761538461538462*I,
|
811
|
+
0.246153846153846 + 0.761538461538462*I,
|
812
|
+
0.841176470588236 + 0.317647058823529*I)
|
813
|
+
"""
|
814
|
+
return self * right.__invert__()
|
815
|
+
|
816
|
+
def __pow__(self, right, modulus):
|
817
|
+
r"""
|
818
|
+
Compute `x^y`.
|
819
|
+
|
820
|
+
If `y` is an integer, uses multiplication;
|
821
|
+
otherwise, uses the standard definition `\exp(\log(x) \cdot y)`.
|
822
|
+
|
823
|
+
.. WARNING::
|
824
|
+
|
825
|
+
If the interval `x` crosses the negative real axis, then we use a
|
826
|
+
non-standard definition of `\log()` (see the docstring for
|
827
|
+
:meth:`argument()` for more details). This means that we will not
|
828
|
+
select the principal value of the power, for part of the input
|
829
|
+
interval (and that we violate the interval guarantees).
|
830
|
+
|
831
|
+
EXAMPLES::
|
832
|
+
|
833
|
+
sage: C.<i> = ComplexIntervalField(20)
|
834
|
+
sage: a = i^2; a
|
835
|
+
-1
|
836
|
+
sage: a.parent()
|
837
|
+
Complex Interval Field with 20 bits of precision
|
838
|
+
sage: a = (1+i)^7; a
|
839
|
+
8 - 8*I
|
840
|
+
sage: (1+i)^(1+i)
|
841
|
+
0.27396? + 0.58370?*I
|
842
|
+
sage: a.parent()
|
843
|
+
Complex Interval Field with 20 bits of precision
|
844
|
+
sage: (2+i)^(-39)
|
845
|
+
1.688?e-14 + 1.628?e-14*I
|
846
|
+
|
847
|
+
If the interval crosses the negative real axis, then we don't use the
|
848
|
+
standard branch cut (and we violate the interval guarantees)::
|
849
|
+
|
850
|
+
sage: (CIF(-7, RIF(-1, 1)) ^ CIF(0.3)).str(style='brackets')
|
851
|
+
'[0.99109735947126309 .. 1.1179269966896264] + [1.4042388462787560 .. 1.4984624123369835]*I'
|
852
|
+
sage: CIF(-7, -1) ^ CIF(0.3)
|
853
|
+
1.117926996689626? - 1.408500714575360?*I
|
854
|
+
|
855
|
+
Note that ``x^2`` is not the same as ``x*x``::
|
856
|
+
|
857
|
+
sage: a = CIF(RIF(-1,1))
|
858
|
+
sage: print((a^2).str(style='brackets'))
|
859
|
+
[0.0000000000000000 .. 1.0000000000000000]
|
860
|
+
sage: print((a*a).str(style='brackets'))
|
861
|
+
[-1.0000000000000000 .. 1.0000000000000000]
|
862
|
+
sage: a = CIF(0, RIF(-1,1))
|
863
|
+
sage: print((a^2).str(style='brackets'))
|
864
|
+
[-1.0000000000000000 .. -0.0000000000000000]
|
865
|
+
sage: print((a*a).str(style='brackets'))
|
866
|
+
[-1.0000000000000000 .. 1.0000000000000000]
|
867
|
+
sage: a = CIF(RIF(-1,1), RIF(-1,1))
|
868
|
+
sage: print((a^2).str(style='brackets'))
|
869
|
+
[-1.0000000000000000 .. 1.0000000000000000] + [-2.0000000000000000 .. 2.0000000000000000]*I
|
870
|
+
sage: print((a*a).str(style='brackets'))
|
871
|
+
[-2.0000000000000000 .. 2.0000000000000000] + [-2.0000000000000000 .. 2.0000000000000000]*I
|
872
|
+
|
873
|
+
We can take very high powers::
|
874
|
+
|
875
|
+
sage: RIF = RealIntervalField(27)
|
876
|
+
sage: CIF = ComplexIntervalField(27)
|
877
|
+
sage: s = RealField(27, rnd="RNDZ")(1/2)^(1/3)
|
878
|
+
sage: a = CIF(RIF(-s/2,s/2), RIF(-s, s))
|
879
|
+
sage: r = a^(10^10000)
|
880
|
+
sage: print(r.str(style='brackets'))
|
881
|
+
[-2.107553304e1028 .. 2.107553304e1028] + [-2.107553304e1028 .. 2.107553304e1028]*I
|
882
|
+
|
883
|
+
TESTS::
|
884
|
+
|
885
|
+
sage: CIF = ComplexIntervalField(7)
|
886
|
+
sage: [CIF(2) ^ RDF(i) for i in range(-5,6)]
|
887
|
+
[0.03125?, 0.06250?, 0.1250?, 0.2500?, 0.5000?, 1, 2, 4, 8, 16, 32]
|
888
|
+
sage: pow(CIF(1), CIF(1), CIF(1))
|
889
|
+
Traceback (most recent call last):
|
890
|
+
...
|
891
|
+
TypeError: pow() 3rd argument not allowed unless all arguments are integers
|
892
|
+
"""
|
893
|
+
if modulus is not None:
|
894
|
+
raise TypeError("pow() 3rd argument not allowed unless all arguments are integers")
|
895
|
+
|
896
|
+
cdef ComplexIntervalFieldElement z, z2, t = None
|
897
|
+
z = <ComplexIntervalFieldElement?>self
|
898
|
+
|
899
|
+
# Convert right to an integer
|
900
|
+
if not isinstance(right, Integer):
|
901
|
+
try:
|
902
|
+
right = Integer(right)
|
903
|
+
except (TypeError, ValueError):
|
904
|
+
# Exponent is really not an integer
|
905
|
+
return (z.log() * z._parent(right)).exp()
|
906
|
+
|
907
|
+
cdef int s = mpz_sgn((<Integer>right).value)
|
908
|
+
if s == 0:
|
909
|
+
return z._parent.one()
|
910
|
+
elif s < 0:
|
911
|
+
z = ~z
|
912
|
+
if not mpz_cmpabs_ui((<Integer>right).value, 1):
|
913
|
+
return z
|
914
|
+
|
915
|
+
# Convert exponent to fmpz_t
|
916
|
+
cdef fmpz_t e
|
917
|
+
fmpz_init(e)
|
918
|
+
fmpz_set_mpz(e, (<Integer>right).value)
|
919
|
+
fmpz_abs(e, e)
|
920
|
+
|
921
|
+
# Now we know that e >= 2.
|
922
|
+
# Use binary powering with special formula for squares.
|
923
|
+
|
924
|
+
# Handle first bit more efficiently:
|
925
|
+
if fmpz_tstbit(e, 0):
|
926
|
+
res = z
|
927
|
+
else:
|
928
|
+
res = z._parent.one()
|
929
|
+
fmpz_tdiv_q_2exp(e, e, 1) # e >>= 1
|
930
|
+
|
931
|
+
# Allocate a temporary ComplexIntervalFieldElement
|
932
|
+
z2 = z._new()
|
933
|
+
|
934
|
+
while True:
|
935
|
+
# Compute z2 = z^2 using the formula
|
936
|
+
# (a + bi)^2 = (a^2 - b^2) + 2abi
|
937
|
+
mpfi_sqr(z2.__re, z.__re) # a^2
|
938
|
+
mpfi_sqr(z2.__im, z.__im) # b^2
|
939
|
+
mpfi_sub(z2.__re, z2.__re, z2.__im) # a^2 - b^2
|
940
|
+
mpfi_mul(z2.__im, z.__re, z.__im) # ab
|
941
|
+
mpfi_mul_2ui(z2.__im, z2.__im, 1) # 2ab
|
942
|
+
z = z2
|
943
|
+
if fmpz_tstbit(e, 0):
|
944
|
+
res *= z
|
945
|
+
fmpz_tdiv_q_2exp(e, e, 1) # e >>= 1
|
946
|
+
if fmpz_is_zero(e):
|
947
|
+
break
|
948
|
+
|
949
|
+
# Swap temporary elements z2 and t (allocate t first if needed)
|
950
|
+
if t is not None:
|
951
|
+
z2 = t
|
952
|
+
else:
|
953
|
+
z2 = z2._new()
|
954
|
+
t = z
|
955
|
+
fmpz_clear(e)
|
956
|
+
return res
|
957
|
+
|
958
|
+
def _magma_init_(self, magma):
|
959
|
+
r"""
|
960
|
+
Return a string representation of ``self`` in the Magma language.
|
961
|
+
|
962
|
+
EXAMPLES::
|
963
|
+
|
964
|
+
sage: t = CIF((1, 1.1), 2.5); t
|
965
|
+
1.1? + 2.5000000000000000?*I
|
966
|
+
sage: magma(t) # optional - magma # indirect doctest
|
967
|
+
1.05000000000000 + 2.50000000000000*$.1
|
968
|
+
sage: t = ComplexIntervalField(100)((1, 4/3), 2.5); t
|
969
|
+
2.? + 2.5000000000000000000000000000000?*I
|
970
|
+
sage: magma(t) # optional - magma
|
971
|
+
1.16666666666666666666666666670 + 2.50000000000000000000000000000*$.1
|
972
|
+
"""
|
973
|
+
return "%s![%s, %s]" % (self.parent()._magma_init_(magma), self.center().real(), self.center().imag())
|
974
|
+
|
975
|
+
def _interface_init_(self, I=None):
|
976
|
+
"""
|
977
|
+
Raise a :exc:`TypeError`.
|
978
|
+
|
979
|
+
This function would return the string representation of ``self``
|
980
|
+
that makes sense as a default representation of a complex
|
981
|
+
interval in other computer algebra systems. But, most other
|
982
|
+
computer algebra systems do not support interval arithmetic,
|
983
|
+
so instead we just raise a :exc:`TypeError`.
|
984
|
+
|
985
|
+
Define the appropriate ``_cas_init_`` function if there is a
|
986
|
+
computer algebra system you would like to support.
|
987
|
+
|
988
|
+
EXAMPLES::
|
989
|
+
|
990
|
+
sage: n = CIF(1.3939494594)
|
991
|
+
sage: n._interface_init_()
|
992
|
+
Traceback (most recent call last):
|
993
|
+
...
|
994
|
+
TypeError
|
995
|
+
|
996
|
+
Here a conversion to Maxima happens, which results in a :exc:`TypeError`::
|
997
|
+
|
998
|
+
sage: a = CIF(2.3)
|
999
|
+
sage: maxima(a) # needs sage.symbolic
|
1000
|
+
Traceback (most recent call last):
|
1001
|
+
...
|
1002
|
+
TypeError
|
1003
|
+
"""
|
1004
|
+
raise TypeError
|
1005
|
+
|
1006
|
+
def _sage_input_(self, sib, coerce):
|
1007
|
+
r"""
|
1008
|
+
Produce an expression which will reproduce this value when evaluated.
|
1009
|
+
|
1010
|
+
EXAMPLES::
|
1011
|
+
|
1012
|
+
sage: sage_input(CIF(RIF(e, pi), RIF(sqrt(2), sqrt(3))), verify=True) # needs sage.symbolic
|
1013
|
+
# Verified
|
1014
|
+
CIF(RIF(RR(2.7182818284590451), RR(3.1415926535897936)), RIF(RR(1.4142135623730949), RR(1.7320508075688774)))
|
1015
|
+
sage: sage_input(ComplexIntervalField(64)(2)^I, preparse=False, verify=True)
|
1016
|
+
# Verified
|
1017
|
+
RIF64 = RealIntervalField(64)
|
1018
|
+
RR64 = RealField(64)
|
1019
|
+
ComplexIntervalField(64)(RIF64(RR64('0.769238901363972126565'), RR64('0.769238901363972126619')), RIF64(RR64('0.638961276313634801076'), RR64('0.638961276313634801184')))
|
1020
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1021
|
+
sage: sib = SageInputBuilder()
|
1022
|
+
sage: ComplexIntervalField(15)(3+I).log()._sage_input_(sib, False)
|
1023
|
+
{call: {call: {atomic:ComplexIntervalField}({atomic:15})}({call: {call: {atomic:RealIntervalField}({atomic:15})}({call: {call: {atomic:RealField}({atomic:15})}({atomic:1.15125})}, {call: {call: {atomic:RealField}({atomic:15})}({atomic:1.15137})})}, {call: {call: {atomic:RealIntervalField}({atomic:15})}({call: {call: {atomic:RealField}({atomic:15})}({atomic:0.321655})}, {call: {call: {atomic:RealField}({atomic:15})}({atomic:0.321777})})})}
|
1024
|
+
"""
|
1025
|
+
# Interval printing could often be much prettier,
|
1026
|
+
# but I'm feeling lazy :)
|
1027
|
+
return sib(self.parent())(sib(self.real()), sib(self.imag()))
|
1028
|
+
|
1029
|
+
def prec(self):
|
1030
|
+
"""
|
1031
|
+
Return precision of this complex number.
|
1032
|
+
|
1033
|
+
EXAMPLES::
|
1034
|
+
|
1035
|
+
sage: i = ComplexIntervalField(2000).0
|
1036
|
+
sage: i.prec()
|
1037
|
+
2000
|
1038
|
+
"""
|
1039
|
+
return self._parent.prec()
|
1040
|
+
|
1041
|
+
def real(self):
|
1042
|
+
"""
|
1043
|
+
Return real part of ``self``.
|
1044
|
+
|
1045
|
+
EXAMPLES::
|
1046
|
+
|
1047
|
+
sage: i = ComplexIntervalField(100).0
|
1048
|
+
sage: z = 2 + 3*i
|
1049
|
+
sage: x = z.real(); x
|
1050
|
+
2
|
1051
|
+
sage: x.parent()
|
1052
|
+
Real Interval Field with 100 bits of precision
|
1053
|
+
"""
|
1054
|
+
x = self._new_real()
|
1055
|
+
mpfi_set(x.value, self.__re)
|
1056
|
+
return x
|
1057
|
+
|
1058
|
+
def imag(self):
|
1059
|
+
"""
|
1060
|
+
Return imaginary part of ``self``.
|
1061
|
+
|
1062
|
+
EXAMPLES::
|
1063
|
+
|
1064
|
+
sage: i = ComplexIntervalField(100).0
|
1065
|
+
sage: z = 2 + 3*i
|
1066
|
+
sage: x = z.imag(); x
|
1067
|
+
3
|
1068
|
+
sage: x.parent()
|
1069
|
+
Real Interval Field with 100 bits of precision
|
1070
|
+
"""
|
1071
|
+
x = self._new_real()
|
1072
|
+
mpfi_set(x.value, self.__im)
|
1073
|
+
return x
|
1074
|
+
|
1075
|
+
def __neg__(self):
|
1076
|
+
"""
|
1077
|
+
Return the negation of ``self``.
|
1078
|
+
|
1079
|
+
EXAMPLES::
|
1080
|
+
|
1081
|
+
sage: CIF(1.5, 2.5).__neg__()
|
1082
|
+
-1.5000000000000000? - 2.5000000000000000?*I
|
1083
|
+
"""
|
1084
|
+
x = self._new()
|
1085
|
+
mpfi_neg(x.__re, self.__re)
|
1086
|
+
mpfi_neg(x.__im, self.__im)
|
1087
|
+
return x
|
1088
|
+
|
1089
|
+
def __pos__(self):
|
1090
|
+
"""
|
1091
|
+
Return the "positive" of ``self``, which is just ``self``.
|
1092
|
+
|
1093
|
+
EXAMPLES::
|
1094
|
+
|
1095
|
+
sage: CIF(1.5, 2.5).__pos__()
|
1096
|
+
1.5000000000000000? + 2.5000000000000000?*I
|
1097
|
+
"""
|
1098
|
+
return self
|
1099
|
+
|
1100
|
+
def __abs__(self):
|
1101
|
+
"""
|
1102
|
+
Return the absolute value of ``self``.
|
1103
|
+
|
1104
|
+
EXAMPLES::
|
1105
|
+
|
1106
|
+
sage: abs(CIF(1.5, 2.5))
|
1107
|
+
2.915475947422650?
|
1108
|
+
sage: CIF(1.5, 2.5).__abs__()
|
1109
|
+
2.915475947422650?
|
1110
|
+
"""
|
1111
|
+
x = self._new_real()
|
1112
|
+
|
1113
|
+
cdef mpfi_t t
|
1114
|
+
mpfi_init2(t, self._prec)
|
1115
|
+
|
1116
|
+
mpfi_sqr(x.value, self.__re)
|
1117
|
+
mpfi_sqr(t, self.__im)
|
1118
|
+
|
1119
|
+
mpfi_add(x.value, x.value, t)
|
1120
|
+
mpfi_sqrt(x.value, x.value)
|
1121
|
+
|
1122
|
+
mpfi_clear(t)
|
1123
|
+
return x
|
1124
|
+
|
1125
|
+
def __invert__(self):
|
1126
|
+
"""
|
1127
|
+
Return the multiplicative inverse of ``self``.
|
1128
|
+
|
1129
|
+
EXAMPLES::
|
1130
|
+
|
1131
|
+
sage: I = CIF.0
|
1132
|
+
sage: a = ~(5+I) # indirect doctest
|
1133
|
+
sage: a * (5+I)
|
1134
|
+
1.000000000000000? + 0.?e-16*I
|
1135
|
+
sage: a = CIF((1, 2), (3, 4))
|
1136
|
+
sage: c = a.__invert__()
|
1137
|
+
sage: c.endpoints()
|
1138
|
+
(0.0588235294117647 - 0.300000000000000*I,
|
1139
|
+
0.153846153846154 - 0.200000000000000*I,
|
1140
|
+
0.0588235294117647 - 0.200000000000000*I,
|
1141
|
+
0.153846153846154 - 0.300000000000000*I)
|
1142
|
+
|
1143
|
+
TESTS:
|
1144
|
+
|
1145
|
+
Check that the code is valid in all kind of complex intervals::
|
1146
|
+
|
1147
|
+
sage: rpts = [0, -194323/42, -110/439423, -411923/122212, \
|
1148
|
+
....: 15423/906, 337/59976, 145151/145112]
|
1149
|
+
sage: rpts = [RIF(a, b) if a <= b else RIF(b,a) \
|
1150
|
+
....: for a in rpts for b in rpts]
|
1151
|
+
sage: cpts = [CIF(a, b) for a in rpts for b in rpts if not CIF(a, b).contains_zero()]
|
1152
|
+
sage: for x in cpts:
|
1153
|
+
....: assert (x * (~x) - 1).contains_zero()
|
1154
|
+
|
1155
|
+
Test that the bug reported in :issue:`25414` has been fixed::
|
1156
|
+
|
1157
|
+
sage: 1 / CIF(RIF(-1 ,1), 0)
|
1158
|
+
[.. NaN ..] + [.. NaN ..]*I
|
1159
|
+
|
1160
|
+
Test that the bug reported in :issue:`37927` is fixed::
|
1161
|
+
|
1162
|
+
sage: (961 * (1 / CIF(0, 31))**2 + 1).contains_zero()
|
1163
|
+
True
|
1164
|
+
|
1165
|
+
REFERENCES:
|
1166
|
+
|
1167
|
+
- [RL1971]_
|
1168
|
+
"""
|
1169
|
+
cdef ComplexIntervalFieldElement result
|
1170
|
+
x = self._new()
|
1171
|
+
|
1172
|
+
if mpfi_nan_p(self.__re) or mpfi_nan_p(self.__im):
|
1173
|
+
# Return NaN if any input is NaN
|
1174
|
+
return x
|
1175
|
+
|
1176
|
+
if mpfi_has_zero(self.__re) and mpfi_has_zero(self.__im):
|
1177
|
+
# Return NaN when dividing by (a complex interval containing) zero.
|
1178
|
+
return x
|
1179
|
+
|
1180
|
+
# The algorithm roughly follows [RL1971].
|
1181
|
+
#
|
1182
|
+
# However, we deviate from [RL1971] significantly and the
|
1183
|
+
# documentation here is self-contained and hopefully easier
|
1184
|
+
# to follow than [RL1971]. There is a visualization at:
|
1185
|
+
# https://www.shadertoy.com/view/M3VXWG
|
1186
|
+
#
|
1187
|
+
# Note that [RL1971] has several mistakes. For example, when analyzing
|
1188
|
+
# the second case where y1 < 0 and y2 > 0 (and x1 >= 0 from earlier
|
1189
|
+
# assumptions), they have a subcase "y_1 >= x_1". That inequality can
|
1190
|
+
# never be true given the earlier assumptions and should be
|
1191
|
+
# "-y_1 >= x_1".
|
1192
|
+
|
1193
|
+
# To maximize symmetry considerations, we actually compute the
|
1194
|
+
# circle inversion (z |-> conjugate(1/z)) and conjugate at the end.
|
1195
|
+
|
1196
|
+
# Let the input be the complex interval [xmin, xmax] + [ymin, ymax] * I.
|
1197
|
+
#
|
1198
|
+
# We say that the complex interval is in standard form if either:
|
1199
|
+
# (I) It is contained within the first quadrant. Furthermore its
|
1200
|
+
# left bottom corner is on or below the north east diagonal.
|
1201
|
+
# That is 0 <= ymin <= xmin. Or:
|
1202
|
+
# (II) It is contained within the first and fourth quadrant crossing
|
1203
|
+
# the (positive) x-Axis. Furthermore, its midpoint is above the
|
1204
|
+
# x-Axis.
|
1205
|
+
# That is 0 < xmin; ymin < 0 < ymax and |ymin| <= |ymax|.
|
1206
|
+
#
|
1207
|
+
# Since we already guarded against the input containing zero, we always
|
1208
|
+
# can and will bring it into standard form by negating or swapping the
|
1209
|
+
# real and imaginary part.
|
1210
|
+
|
1211
|
+
cdef mpfr_t xmin, xmax, ymin, ymax
|
1212
|
+
mpfr_init2(xmin, self._prec)
|
1213
|
+
mpfr_init2(xmax, self._prec)
|
1214
|
+
mpfr_init2(ymin, self._prec)
|
1215
|
+
mpfr_init2(ymax, self._prec)
|
1216
|
+
|
1217
|
+
mpfi_get_left(xmin, self.__re)
|
1218
|
+
mpfi_get_right(xmax, self.__re)
|
1219
|
+
mpfi_get_left(ymin, self.__im)
|
1220
|
+
mpfi_get_right(ymax, self.__im)
|
1221
|
+
|
1222
|
+
# Record what mirror symmetries we applied to undo them later.
|
1223
|
+
#
|
1224
|
+
# We assume that we flip about the coordinate axes before flipping
|
1225
|
+
# about the north east diagonal.
|
1226
|
+
cdef bint negated_x = False
|
1227
|
+
cdef bint negated_y = False
|
1228
|
+
cdef bint swapped_xy = False
|
1229
|
+
|
1230
|
+
# Record whether we are in case (II).
|
1231
|
+
cdef bint crosses_x_axis = False
|
1232
|
+
|
1233
|
+
########################################################################
|
1234
|
+
# Now bring the input into standard form.
|
1235
|
+
|
1236
|
+
if mpfr_sgn(ymax) <= 0:
|
1237
|
+
# Interval below (and possibly touching) x-Axis, flip about it.
|
1238
|
+
_negate_interval(ymin, ymax)
|
1239
|
+
negated_y = True
|
1240
|
+
elif mpfr_sgn(ymin) < 0:
|
1241
|
+
# Interval crosses x-Axis
|
1242
|
+
crosses_x_axis = True
|
1243
|
+
# else: Interval is above x-Axis
|
1244
|
+
|
1245
|
+
# Negating interval for y and swapping do not commute, so
|
1246
|
+
# order of the above and below if-block is important.
|
1247
|
+
|
1248
|
+
if mpfr_sgn(xmax) <= 0:
|
1249
|
+
# Interval left of (and possibly touching) y-Axis, flip about it.
|
1250
|
+
_negate_interval(xmin, xmax)
|
1251
|
+
negated_x = True
|
1252
|
+
elif mpfr_sgn(xmin) < 0:
|
1253
|
+
# Interval crosses y-Axis, swap to make it cross x-Axis instead.
|
1254
|
+
mpfr_swap(xmin, ymin)
|
1255
|
+
mpfr_swap(xmax, ymax)
|
1256
|
+
swapped_xy = True
|
1257
|
+
crosses_x_axis = True
|
1258
|
+
# else: Interval is right of y-Axis
|
1259
|
+
|
1260
|
+
if crosses_x_axis:
|
1261
|
+
# Case (II). Ensure standard condition |ymax| >= |ymin|
|
1262
|
+
if mpfr_cmpabs(ymin, ymax) > 0:
|
1263
|
+
_negate_interval(ymin, ymax)
|
1264
|
+
# Note that we negate after potentially swapping.
|
1265
|
+
# Determine what we should have negated before swapping instead.
|
1266
|
+
if swapped_xy:
|
1267
|
+
# negated_x cannot be True already.
|
1268
|
+
negated_x = True
|
1269
|
+
else:
|
1270
|
+
# negated_y cannot be True already.
|
1271
|
+
negated_y = True
|
1272
|
+
else:
|
1273
|
+
# Case (I). Ensure standard condition |ymin| <= |xmin|.
|
1274
|
+
if mpfr_cmp(xmin, ymin) < 0:
|
1275
|
+
mpfr_swap(xmin, ymin)
|
1276
|
+
mpfr_swap(xmax, ymax)
|
1277
|
+
swapped_xy = True
|
1278
|
+
|
1279
|
+
########################################################################
|
1280
|
+
# Apply circle inversion
|
1281
|
+
|
1282
|
+
# Result will be [amin, amax] + [bmin, bmax] * I.
|
1283
|
+
cdef mpfr_t amin, amax, bmin, bmax
|
1284
|
+
|
1285
|
+
mpfr_init2(amin, self._prec)
|
1286
|
+
mpfr_init2(amax, self._prec)
|
1287
|
+
mpfr_init2(bmin, self._prec)
|
1288
|
+
mpfr_init2(bmax, self._prec)
|
1289
|
+
|
1290
|
+
_circle_invert_standard(
|
1291
|
+
amin, amax, bmin, bmax,
|
1292
|
+
xmin, xmax, ymin, ymax,
|
1293
|
+
crosses_x_axis, self._prec)
|
1294
|
+
|
1295
|
+
########################################################################
|
1296
|
+
# Undo symmetries applied above.
|
1297
|
+
|
1298
|
+
if swapped_xy:
|
1299
|
+
mpfr_swap(amin, bmin)
|
1300
|
+
mpfr_swap(amax, bmax)
|
1301
|
+
|
1302
|
+
if negated_x:
|
1303
|
+
_negate_interval(amin, amax)
|
1304
|
+
|
1305
|
+
# We sneak in the promised conjugation by
|
1306
|
+
# inverting negated_y.
|
1307
|
+
if not negated_y:
|
1308
|
+
_negate_interval(bmin, bmax)
|
1309
|
+
|
1310
|
+
########################################################################
|
1311
|
+
# Write out result and free memory
|
1312
|
+
|
1313
|
+
mpfi_interv_fr(x.__re, amin, amax)
|
1314
|
+
mpfi_interv_fr(x.__im, bmin, bmax)
|
1315
|
+
|
1316
|
+
mpfr_clear(xmin)
|
1317
|
+
mpfr_clear(xmax)
|
1318
|
+
mpfr_clear(ymin)
|
1319
|
+
mpfr_clear(ymax)
|
1320
|
+
mpfr_clear(amin)
|
1321
|
+
mpfr_clear(amax)
|
1322
|
+
mpfr_clear(bmin)
|
1323
|
+
mpfr_clear(bmax)
|
1324
|
+
|
1325
|
+
return x
|
1326
|
+
|
1327
|
+
def _complex_mpfr_field_(self, field):
|
1328
|
+
"""
|
1329
|
+
Convert to a complex field.
|
1330
|
+
|
1331
|
+
EXAMPLES::
|
1332
|
+
|
1333
|
+
sage: re = RIF("1.2")
|
1334
|
+
sage: im = RIF(2, 3)
|
1335
|
+
sage: a = ComplexIntervalField(30)(re, im)
|
1336
|
+
sage: CC(a)
|
1337
|
+
1.20000000018626 + 2.50000000000000*I
|
1338
|
+
"""
|
1339
|
+
cdef ComplexNumber x = field(0)
|
1340
|
+
mpfi_mid(x.__re, self.__re)
|
1341
|
+
mpfi_mid(x.__im, self.__im)
|
1342
|
+
return x
|
1343
|
+
|
1344
|
+
def __int__(self):
|
1345
|
+
"""
|
1346
|
+
Convert ``self`` to an ``int``.
|
1347
|
+
|
1348
|
+
EXAMPLES::
|
1349
|
+
|
1350
|
+
sage: int(CIF(1,1))
|
1351
|
+
Traceback (most recent call last):
|
1352
|
+
...
|
1353
|
+
TypeError: can...t convert complex interval to int
|
1354
|
+
"""
|
1355
|
+
raise TypeError("can't convert complex interval to int")
|
1356
|
+
|
1357
|
+
def _integer_(self, _):
|
1358
|
+
r"""
|
1359
|
+
Convert this interval to an integer.
|
1360
|
+
|
1361
|
+
EXAMPLES::
|
1362
|
+
|
1363
|
+
sage: ZZ(CIF(-3))
|
1364
|
+
-3
|
1365
|
+
sage: ZZ(CIF(1+I))
|
1366
|
+
Traceback (most recent call last):
|
1367
|
+
...
|
1368
|
+
ValueError: unable to convert interval 1 + 1*I to an integer
|
1369
|
+
sage: ZZ(CIF(RIF(1/2,3/2)))
|
1370
|
+
Traceback (most recent call last):
|
1371
|
+
...
|
1372
|
+
ValueError: unable to convert interval 1.? to an integer
|
1373
|
+
"""
|
1374
|
+
try:
|
1375
|
+
if self.imag()._integer_(None).is_zero():
|
1376
|
+
return self.real()._integer_(None)
|
1377
|
+
except ValueError:
|
1378
|
+
pass
|
1379
|
+
raise ValueError("unable to convert interval {!r} to an integer".format(self))
|
1380
|
+
|
1381
|
+
def __float__(self):
|
1382
|
+
"""
|
1383
|
+
Convert ``self`` to a ``float``.
|
1384
|
+
|
1385
|
+
EXAMPLES::
|
1386
|
+
|
1387
|
+
sage: float(CIF(1))
|
1388
|
+
1.0
|
1389
|
+
sage: float(CIF(1,1))
|
1390
|
+
Traceback (most recent call last):
|
1391
|
+
...
|
1392
|
+
TypeError: can...t convert complex interval to float
|
1393
|
+
"""
|
1394
|
+
if self.imag() == 0:
|
1395
|
+
return float(self.real().n(self._prec))
|
1396
|
+
else:
|
1397
|
+
raise TypeError("can't convert complex interval to float")
|
1398
|
+
|
1399
|
+
def __complex__(self):
|
1400
|
+
"""
|
1401
|
+
Convert ``self`` to a ``complex``.
|
1402
|
+
|
1403
|
+
EXAMPLES::
|
1404
|
+
|
1405
|
+
sage: complex(CIF(1,1))
|
1406
|
+
(1+1j)
|
1407
|
+
"""
|
1408
|
+
return complex(self.real().n(self._prec),
|
1409
|
+
self.imag().n(self._prec))
|
1410
|
+
|
1411
|
+
def __bool__(self):
|
1412
|
+
"""
|
1413
|
+
Return ``True`` if ``self`` is not known to be exactly zero.
|
1414
|
+
|
1415
|
+
EXAMPLES::
|
1416
|
+
|
1417
|
+
sage: bool(CIF(RIF(0, 0), RIF(0, 0)))
|
1418
|
+
False
|
1419
|
+
sage: bool(CIF(RIF(1), RIF(0)))
|
1420
|
+
True
|
1421
|
+
sage: bool(CIF(RIF(0), RIF(1)))
|
1422
|
+
True
|
1423
|
+
sage: bool(CIF(RIF(1, 2), RIF(0)))
|
1424
|
+
True
|
1425
|
+
sage: bool(CIF(RIF(-1, 1), RIF(-1, 1)))
|
1426
|
+
True
|
1427
|
+
"""
|
1428
|
+
return bool(self.real()) or bool(self.imag())
|
1429
|
+
|
1430
|
+
cpdef _richcmp_(left, right, int op):
|
1431
|
+
r"""
|
1432
|
+
As with the real interval fields this never returns false positives.
|
1433
|
+
|
1434
|
+
Thus, `a == b` is ``True`` iff both `a` and `b` represent the same
|
1435
|
+
one-point interval. Likewise `a != b` is ``True`` iff `x != y` for all
|
1436
|
+
`x \in a, y \in b`.
|
1437
|
+
|
1438
|
+
EXAMPLES::
|
1439
|
+
|
1440
|
+
sage: CIF(0) == CIF(0)
|
1441
|
+
True
|
1442
|
+
sage: CIF(0) == CIF(1)
|
1443
|
+
False
|
1444
|
+
sage: CIF.gen() == CIF.gen()
|
1445
|
+
True
|
1446
|
+
sage: CIF(0) == CIF.gen()
|
1447
|
+
False
|
1448
|
+
sage: CIF(0) != CIF(1)
|
1449
|
+
True
|
1450
|
+
sage: -CIF(-3).sqrt() != CIF(-3).sqrt()
|
1451
|
+
True
|
1452
|
+
|
1453
|
+
These intervals overlap, but contain unequal points::
|
1454
|
+
|
1455
|
+
sage: CIF(3).sqrt() == CIF(3).sqrt()
|
1456
|
+
False
|
1457
|
+
sage: CIF(3).sqrt() != CIF(3).sqrt()
|
1458
|
+
False
|
1459
|
+
|
1460
|
+
In the future, complex interval elements may be unordered,
|
1461
|
+
but or backwards compatibility we order them lexicographically::
|
1462
|
+
|
1463
|
+
sage: CDF(-1) < -CDF.gen() < CDF.gen() < CDF(1)
|
1464
|
+
True
|
1465
|
+
sage: CDF(1) >= CDF(1) >= CDF.gen() >= CDF.gen() >= 0 >= -CDF.gen() >= CDF(-1)
|
1466
|
+
True
|
1467
|
+
"""
|
1468
|
+
cdef ComplexIntervalFieldElement lt, rt
|
1469
|
+
lt = left
|
1470
|
+
rt = right
|
1471
|
+
if op == Py_EQ:
|
1472
|
+
# intervals a == b iff a<=b and b <= a
|
1473
|
+
# (this gives a result with two comparisons, where the
|
1474
|
+
# obvious approach would use three)
|
1475
|
+
return mpfr_lessequal_p(<.__re.right, &rt.__re.left) \
|
1476
|
+
and mpfr_lessequal_p(&rt.__re.right, <.__re.left) \
|
1477
|
+
and mpfr_lessequal_p(<.__im.right, &rt.__im.left) \
|
1478
|
+
and mpfr_lessequal_p(&rt.__im.right, <.__im.left)
|
1479
|
+
elif op == Py_NE:
|
1480
|
+
return mpfr_less_p(<.__re.right, &rt.__re.left) \
|
1481
|
+
or mpfr_less_p(&rt.__re.right, <.__re.left) \
|
1482
|
+
or mpfr_less_p(<.__im.right, &rt.__im.left) \
|
1483
|
+
or mpfr_less_p(&rt.__im.right, <.__im.left)
|
1484
|
+
else:
|
1485
|
+
# Eventually we probably want to disable comparison of complex
|
1486
|
+
# intervals, just like python complexes will be unordered.
|
1487
|
+
## raise TypeError("no ordering relation is defined for complex numbers")
|
1488
|
+
diff = left - right
|
1489
|
+
real_diff = diff.real()
|
1490
|
+
imag_diff = diff.imag()
|
1491
|
+
if op == Py_LT:
|
1492
|
+
return real_diff < 0 or (real_diff == 0 and imag_diff < 0)
|
1493
|
+
elif op == Py_LE:
|
1494
|
+
return real_diff < 0 or (real_diff == 0 and imag_diff <= 0)
|
1495
|
+
elif op == Py_GT:
|
1496
|
+
return real_diff > 0 or (real_diff == 0 and imag_diff > 0)
|
1497
|
+
elif op == Py_GE:
|
1498
|
+
return real_diff > 0 or (real_diff == 0 and imag_diff >= 0)
|
1499
|
+
|
1500
|
+
def lexico_cmp(left, right):
|
1501
|
+
"""
|
1502
|
+
Intervals are compared lexicographically on the 4-tuple:
|
1503
|
+
``(x.real().lower(), x.real().upper(),
|
1504
|
+
x.imag().lower(), x.imag().upper())``
|
1505
|
+
|
1506
|
+
EXAMPLES::
|
1507
|
+
|
1508
|
+
sage: a = CIF(RIF(0,1), RIF(0,1))
|
1509
|
+
sage: b = CIF(RIF(0,1), RIF(0,2))
|
1510
|
+
sage: c = CIF(RIF(0,2), RIF(0,2))
|
1511
|
+
sage: a.lexico_cmp(b)
|
1512
|
+
-1
|
1513
|
+
sage: b.lexico_cmp(c)
|
1514
|
+
-1
|
1515
|
+
sage: a.lexico_cmp(c)
|
1516
|
+
-1
|
1517
|
+
sage: a.lexico_cmp(a)
|
1518
|
+
0
|
1519
|
+
sage: b.lexico_cmp(a)
|
1520
|
+
1
|
1521
|
+
|
1522
|
+
TESTS::
|
1523
|
+
|
1524
|
+
sage: tests = []
|
1525
|
+
sage: for rl in (0, 1):
|
1526
|
+
....: for ru in (rl, rl + 1):
|
1527
|
+
....: for il in (0, 1):
|
1528
|
+
....: for iu in (il, il + 1):
|
1529
|
+
....: tests.append((CIF(RIF(rl, ru), RIF(il, iu)), (rl, ru, il, iu)))
|
1530
|
+
sage: for (i1, t1) in tests:
|
1531
|
+
....: for (i2, t2) in tests:
|
1532
|
+
....: if t1 == t2:
|
1533
|
+
....: assert(i1.lexico_cmp(i2) == 0)
|
1534
|
+
....: elif t1 < t2:
|
1535
|
+
....: assert(i1.lexico_cmp(i2) == -1)
|
1536
|
+
....: elif t1 > t2:
|
1537
|
+
....: assert(i1.lexico_cmp(i2) == 1)
|
1538
|
+
"""
|
1539
|
+
cdef int a, b
|
1540
|
+
a = mpfi_nan_p(left.__re)
|
1541
|
+
b = mpfi_nan_p((<ComplexIntervalFieldElement>right).__re)
|
1542
|
+
if a != b:
|
1543
|
+
return -1
|
1544
|
+
|
1545
|
+
cdef int i
|
1546
|
+
i = mpfr_cmp(&left.__re.left, &(<ComplexIntervalFieldElement>right).__re.left)
|
1547
|
+
if i < 0:
|
1548
|
+
return -1
|
1549
|
+
elif i > 0:
|
1550
|
+
return 1
|
1551
|
+
i = mpfr_cmp(&left.__re.right, &(<ComplexIntervalFieldElement>right).__re.right)
|
1552
|
+
if i < 0:
|
1553
|
+
return -1
|
1554
|
+
elif i > 0:
|
1555
|
+
return 1
|
1556
|
+
i = mpfr_cmp(&left.__im.left, &(<ComplexIntervalFieldElement>right).__im.left)
|
1557
|
+
if i < 0:
|
1558
|
+
return -1
|
1559
|
+
elif i > 0:
|
1560
|
+
return 1
|
1561
|
+
i = mpfr_cmp(&left.__im.right, &(<ComplexIntervalFieldElement>right).__im.right)
|
1562
|
+
if i < 0:
|
1563
|
+
return -1
|
1564
|
+
elif i > 0:
|
1565
|
+
return 1
|
1566
|
+
return 0
|
1567
|
+
|
1568
|
+
########################################################################
|
1569
|
+
# Transcendental (and other) functions
|
1570
|
+
########################################################################
|
1571
|
+
|
1572
|
+
def multiplicative_order(self):
|
1573
|
+
"""
|
1574
|
+
Return the multiplicative order of this complex number, if known,
|
1575
|
+
or raise a :exc:`NotImplementedError`.
|
1576
|
+
|
1577
|
+
EXAMPLES::
|
1578
|
+
|
1579
|
+
sage: C = CIF
|
1580
|
+
sage: i = C.0
|
1581
|
+
sage: i.multiplicative_order()
|
1582
|
+
4
|
1583
|
+
sage: C(1).multiplicative_order()
|
1584
|
+
1
|
1585
|
+
sage: C(-1).multiplicative_order()
|
1586
|
+
2
|
1587
|
+
sage: (i^2).multiplicative_order()
|
1588
|
+
2
|
1589
|
+
sage: (-i).multiplicative_order()
|
1590
|
+
4
|
1591
|
+
sage: C(2).multiplicative_order()
|
1592
|
+
+Infinity
|
1593
|
+
sage: w = (1 + C(-3).sqrt())/2 ; w
|
1594
|
+
0.50000000000000000? + 0.866025403784439?*I
|
1595
|
+
sage: w.multiplicative_order()
|
1596
|
+
Traceback (most recent call last):
|
1597
|
+
...
|
1598
|
+
NotImplementedError: order of element not known
|
1599
|
+
"""
|
1600
|
+
if self._multiplicative_order is not None:
|
1601
|
+
return Integer(self._multiplicative_order)
|
1602
|
+
ring = self._parent
|
1603
|
+
if self == ring.one():
|
1604
|
+
return Integer(1)
|
1605
|
+
if self == -ring.one():
|
1606
|
+
return Integer(2)
|
1607
|
+
if self == ring.gen() or self == -ring.gen():
|
1608
|
+
return Integer(4)
|
1609
|
+
if 1 not in abs(self): # clearly not a root of unity
|
1610
|
+
return infinity
|
1611
|
+
raise NotImplementedError("order of element not known")
|
1612
|
+
|
1613
|
+
def argument(self):
|
1614
|
+
r"""
|
1615
|
+
The argument (angle) of the complex number, normalized
|
1616
|
+
so that `-\pi < \theta.lower() \leq \pi`.
|
1617
|
+
|
1618
|
+
We raise a :exc:`ValueError` if the interval strictly contains 0,
|
1619
|
+
or if the interval contains only 0.
|
1620
|
+
|
1621
|
+
.. WARNING::
|
1622
|
+
|
1623
|
+
We do not always use the standard branch cut for
|
1624
|
+
argument! If the interval crosses the negative real axis,
|
1625
|
+
then the argument will be an interval whose lower bound is
|
1626
|
+
less than `\pi` and whose upper bound is more than `\pi`; in
|
1627
|
+
effect, we move the branch cut away from the interval.
|
1628
|
+
|
1629
|
+
EXAMPLES::
|
1630
|
+
|
1631
|
+
sage: i = CIF.0
|
1632
|
+
sage: (i^2).argument()
|
1633
|
+
3.141592653589794?
|
1634
|
+
sage: (1+i).argument()
|
1635
|
+
0.785398163397449?
|
1636
|
+
sage: i.argument()
|
1637
|
+
1.570796326794897?
|
1638
|
+
sage: (-i).argument()
|
1639
|
+
-1.570796326794897?
|
1640
|
+
sage: (-1/1000 - i).argument()
|
1641
|
+
-1.571796326461564?
|
1642
|
+
sage: CIF(2).argument()
|
1643
|
+
0
|
1644
|
+
sage: CIF(-2).argument()
|
1645
|
+
3.141592653589794?
|
1646
|
+
|
1647
|
+
Here we see that if the interval crosses the negative real
|
1648
|
+
axis, then the argument can exceed `\pi`, and we
|
1649
|
+
we violate the standard interval guarantees in the process::
|
1650
|
+
|
1651
|
+
sage: CIF(-2, RIF(-0.1, 0.1)).argument().str(style='brackets')
|
1652
|
+
'[3.0916342578678501 .. 3.1915510493117365]'
|
1653
|
+
sage: CIF(-2, -0.1).argument()
|
1654
|
+
-3.091634257867851?
|
1655
|
+
"""
|
1656
|
+
if mpfi_has_zero(self.__re) and mpfi_has_zero(self.__im):
|
1657
|
+
|
1658
|
+
if mpfi_is_zero(self.__re) and mpfi_is_zero(self.__im):
|
1659
|
+
raise ValueError("Can't take the argument of complex zero")
|
1660
|
+
if not mpfi_is_nonpos(self.__re) and not mpfi_is_nonneg(self.__re) \
|
1661
|
+
and not mpfi_is_nonpos(self.__im) and not mpfi_is_nonneg(self.__im):
|
1662
|
+
raise ValueError("Can't take the argument of interval strictly containing zero")
|
1663
|
+
|
1664
|
+
# Now if we exclude zero from the interval, we know that the
|
1665
|
+
# argument of the remaining points is bounded. Check which
|
1666
|
+
# axes the interval extends along (we can deduce information
|
1667
|
+
# about the quadrants from information about the axes).
|
1668
|
+
|
1669
|
+
which_axes = [False, False, False, False]
|
1670
|
+
if not mpfi_is_nonpos(self.__re):
|
1671
|
+
which_axes[0] = True
|
1672
|
+
if not mpfi_is_nonpos(self.__im):
|
1673
|
+
which_axes[1] = True
|
1674
|
+
if not mpfi_is_nonneg(self.__re):
|
1675
|
+
which_axes[2] = True
|
1676
|
+
if not mpfi_is_nonneg(self.__im):
|
1677
|
+
which_axes[3] = True
|
1678
|
+
|
1679
|
+
lower = None
|
1680
|
+
for i in range(-1, 3):
|
1681
|
+
if which_axes[i % 4] and not which_axes[(i - 1) % 4]:
|
1682
|
+
if lower is not None:
|
1683
|
+
raise ValueError("Can't take the argument of line-segment interval strictly containing zero")
|
1684
|
+
lower = i
|
1685
|
+
|
1686
|
+
for i in range(lower, lower+4):
|
1687
|
+
if which_axes[i % 4] and not which_axes[(i + 1) % 4]:
|
1688
|
+
upper = i
|
1689
|
+
break
|
1690
|
+
|
1691
|
+
fld = self._parent.real_field()
|
1692
|
+
return fld.pi() * fld(lower, upper) * fld(0.5)
|
1693
|
+
|
1694
|
+
else:
|
1695
|
+
|
1696
|
+
# OK, we know that the interval is bounded away from zero
|
1697
|
+
# in either the real or the imaginary direction (or both).
|
1698
|
+
# We'll handle the "bounded away in the imaginary direction"
|
1699
|
+
# case first.
|
1700
|
+
|
1701
|
+
fld = self._parent.real_field()
|
1702
|
+
|
1703
|
+
if mpfi_is_strictly_pos(self.__im):
|
1704
|
+
return (-self.real() / self.imag()).arctan() + fld.pi()/2
|
1705
|
+
if mpfi_is_strictly_neg(self.__im):
|
1706
|
+
return (-self.real() / self.imag()).arctan() - fld.pi()/2
|
1707
|
+
|
1708
|
+
if mpfi_is_strictly_pos(self.__re):
|
1709
|
+
return (self.imag() / self.real()).arctan()
|
1710
|
+
|
1711
|
+
# The only remaining case is that self.__re is strictly
|
1712
|
+
# negative and self.__im contains 0. In that case, we
|
1713
|
+
# return an interval containing pi.
|
1714
|
+
|
1715
|
+
return (self.imag() / self.real()).arctan() + fld.pi()
|
1716
|
+
|
1717
|
+
def arg(self):
|
1718
|
+
"""
|
1719
|
+
Same as :meth:`argument()`.
|
1720
|
+
|
1721
|
+
EXAMPLES::
|
1722
|
+
|
1723
|
+
sage: i = CIF.0
|
1724
|
+
sage: (i^2).arg()
|
1725
|
+
3.141592653589794?
|
1726
|
+
"""
|
1727
|
+
return self.argument()
|
1728
|
+
|
1729
|
+
def crosses_log_branch_cut(self):
|
1730
|
+
"""
|
1731
|
+
Return ``True`` if this interval crosses the standard branch cut
|
1732
|
+
for :meth:`log()` (and hence for exponentiation) and for argument.
|
1733
|
+
(Recall that this branch cut is infinitesimally below the
|
1734
|
+
negative portion of the real axis.)
|
1735
|
+
|
1736
|
+
EXAMPLES::
|
1737
|
+
|
1738
|
+
sage: z = CIF(1.5, 2.5) - CIF(0, 2.50000000000000001); z
|
1739
|
+
1.5000000000000000? + -1.?e-15*I
|
1740
|
+
sage: z.crosses_log_branch_cut()
|
1741
|
+
False
|
1742
|
+
sage: CIF(-2, RIF(-0.1, 0.1)).crosses_log_branch_cut()
|
1743
|
+
True
|
1744
|
+
"""
|
1745
|
+
|
1746
|
+
if mpfi_is_nonneg(self.__re):
|
1747
|
+
return False
|
1748
|
+
if mpfi_is_nonneg(self.__im):
|
1749
|
+
return False
|
1750
|
+
if mpfi_is_neg(self.__im):
|
1751
|
+
return False
|
1752
|
+
return True
|
1753
|
+
|
1754
|
+
def conjugate(self):
|
1755
|
+
"""
|
1756
|
+
Return the complex conjugate of this complex number.
|
1757
|
+
|
1758
|
+
EXAMPLES::
|
1759
|
+
|
1760
|
+
sage: i = CIF.0
|
1761
|
+
sage: (1+i).conjugate()
|
1762
|
+
1 - 1*I
|
1763
|
+
"""
|
1764
|
+
x = self._new()
|
1765
|
+
|
1766
|
+
mpfi_set(x.__re, self.__re)
|
1767
|
+
mpfi_neg(x.__im, self.__im)
|
1768
|
+
return x
|
1769
|
+
|
1770
|
+
def exp(self):
|
1771
|
+
r"""
|
1772
|
+
Compute `e^z` or `\exp(z)` where `z` is the complex number ``self``.
|
1773
|
+
|
1774
|
+
EXAMPLES::
|
1775
|
+
|
1776
|
+
sage: i = ComplexIntervalField(300).0
|
1777
|
+
sage: z = 1 + i
|
1778
|
+
sage: z.exp()
|
1779
|
+
1.46869393991588515713896759732660426132695673662900872279767567631093696585951213872272450? + 2.28735528717884239120817190670050180895558625666835568093865811410364716018934540926734485?*I
|
1780
|
+
"""
|
1781
|
+
mag = self.real().exp()
|
1782
|
+
theta = self.imag()
|
1783
|
+
re = theta.cos() * mag
|
1784
|
+
im = theta.sin() * mag
|
1785
|
+
return ComplexIntervalFieldElement(self._parent, re, im)
|
1786
|
+
|
1787
|
+
def log(self, base=None):
|
1788
|
+
"""
|
1789
|
+
Complex logarithm of `z`.
|
1790
|
+
|
1791
|
+
.. WARNING::
|
1792
|
+
|
1793
|
+
This does always not use the standard branch cut for complex log!
|
1794
|
+
See the docstring for :meth:`argument()` to see what we do instead.
|
1795
|
+
|
1796
|
+
EXAMPLES::
|
1797
|
+
|
1798
|
+
sage: a = CIF(RIF(3, 4), RIF(13, 14))
|
1799
|
+
sage: a.log().str(style='brackets')
|
1800
|
+
'[2.5908917751460420 .. 2.6782931373360067] + [1.2722973952087170 .. 1.3597029935721503]*I'
|
1801
|
+
sage: a.log().exp().str(style='brackets')
|
1802
|
+
'[2.7954667135098274 .. 4.2819545928390213] + [12.751682453911920 .. 14.237018048974635]*I'
|
1803
|
+
sage: a in a.log().exp()
|
1804
|
+
True
|
1805
|
+
|
1806
|
+
If the interval crosses the negative real axis, then we don't
|
1807
|
+
use the standard branch cut (and we violate the interval guarantees)::
|
1808
|
+
|
1809
|
+
sage: CIF(-3, RIF(-1/4, 1/4)).log().str(style='brackets')
|
1810
|
+
'[1.0986122886681095 .. 1.1020725100903968] + [3.0584514217013518 .. 3.2247338854782349]*I'
|
1811
|
+
sage: CIF(-3, -1/4).log()
|
1812
|
+
1.102072510090397? - 3.058451421701352?*I
|
1813
|
+
|
1814
|
+
Usually if an interval contains zero, we raise an exception::
|
1815
|
+
|
1816
|
+
sage: CIF(RIF(-1,1),RIF(-1,1)).log()
|
1817
|
+
Traceback (most recent call last):
|
1818
|
+
...
|
1819
|
+
ValueError: Can...t take the argument of interval strictly containing zero
|
1820
|
+
|
1821
|
+
But we allow the exact input zero::
|
1822
|
+
|
1823
|
+
sage: CIF(0).log()
|
1824
|
+
[-infinity .. -infinity]
|
1825
|
+
|
1826
|
+
If a base is passed from another function, we can accommodate this::
|
1827
|
+
|
1828
|
+
sage: CIF(-1,1).log(2)
|
1829
|
+
0.500000000000000? + 3.39927010637040?*I
|
1830
|
+
"""
|
1831
|
+
if not self:
|
1832
|
+
from sage.rings.real_mpfi import RIF
|
1833
|
+
return RIF(0).log()
|
1834
|
+
re = abs(self).log()
|
1835
|
+
im = self.argument()
|
1836
|
+
if base == 'e':
|
1837
|
+
base = None
|
1838
|
+
if base is not None:
|
1839
|
+
base = self._parent._real_field()(base)
|
1840
|
+
f = base.log()
|
1841
|
+
re /= f
|
1842
|
+
im /= f
|
1843
|
+
return ComplexIntervalFieldElement(self._parent, re, im)
|
1844
|
+
|
1845
|
+
def sqrt(self, bint all=False, **kwds):
|
1846
|
+
"""
|
1847
|
+
The square root function.
|
1848
|
+
|
1849
|
+
.. WARNING::
|
1850
|
+
|
1851
|
+
We approximate the standard branch cut along the negative real
|
1852
|
+
axis, with ``sqrt(-r^2) = i*r`` for positive real ``r``; but if
|
1853
|
+
the interval crosses the negative real axis, we pick the root with
|
1854
|
+
positive imaginary component for the entire interval.
|
1855
|
+
|
1856
|
+
INPUT:
|
1857
|
+
|
1858
|
+
- ``all`` -- boolean (default: ``False``); if ``True``, return a list
|
1859
|
+
of all square roots
|
1860
|
+
|
1861
|
+
EXAMPLES::
|
1862
|
+
|
1863
|
+
sage: CIF(-1).sqrt()^2
|
1864
|
+
-1
|
1865
|
+
sage: sqrt(CIF(2))
|
1866
|
+
1.414213562373095?
|
1867
|
+
sage: sqrt(CIF(-1))
|
1868
|
+
1*I
|
1869
|
+
sage: sqrt(CIF(2-I))^2
|
1870
|
+
2.00000000000000? - 1.00000000000000?*I
|
1871
|
+
sage: CC(-2-I).sqrt()^2
|
1872
|
+
-2.00000000000000 - 1.00000000000000*I
|
1873
|
+
|
1874
|
+
Here, we select a non-principal root for part of the interval, and
|
1875
|
+
violate the standard interval guarantees::
|
1876
|
+
|
1877
|
+
sage: CIF(-5, RIF(-1, 1)).sqrt().str(style='brackets')
|
1878
|
+
'[-0.22250788030178321 .. 0.22250788030178296] + [2.2251857651053086 .. 2.2581008643532262]*I'
|
1879
|
+
sage: CIF(-5, -1).sqrt()
|
1880
|
+
0.222507880301783? - 2.247111425095870?*I
|
1881
|
+
"""
|
1882
|
+
if self.is_zero():
|
1883
|
+
return [self] if all else self
|
1884
|
+
if mpfi_is_zero(self.__im) and not mpfi_has_zero(self.__re):
|
1885
|
+
if mpfr_sgn(&self.__re.left) > 0:
|
1886
|
+
x = ComplexIntervalFieldElement(self._parent, self.real().sqrt(), 0)
|
1887
|
+
else:
|
1888
|
+
x = ComplexIntervalFieldElement(self._parent, 0, (-self.real()).sqrt())
|
1889
|
+
else:
|
1890
|
+
theta = self.argument()/2
|
1891
|
+
rho = abs(self).sqrt()
|
1892
|
+
x = ComplexIntervalFieldElement(self._parent, rho*theta.cos(), rho*theta.sin())
|
1893
|
+
if all:
|
1894
|
+
return [x, -x]
|
1895
|
+
else:
|
1896
|
+
return x
|
1897
|
+
|
1898
|
+
def is_square(self):
|
1899
|
+
r"""
|
1900
|
+
Return ``True`` as `\CC` is algebraically closed.
|
1901
|
+
|
1902
|
+
EXAMPLES::
|
1903
|
+
|
1904
|
+
sage: CIF(2, 1).is_square()
|
1905
|
+
True
|
1906
|
+
"""
|
1907
|
+
return True
|
1908
|
+
|
1909
|
+
def is_NaN(self):
|
1910
|
+
r"""
|
1911
|
+
Return ``True`` if this is not-a-number.
|
1912
|
+
|
1913
|
+
EXAMPLES::
|
1914
|
+
|
1915
|
+
sage: CIF(2, 1).is_NaN()
|
1916
|
+
False
|
1917
|
+
sage: CIF(NaN).is_NaN() # needs sage.symbolic
|
1918
|
+
True
|
1919
|
+
sage: (1 / CIF(0, 0)).is_NaN()
|
1920
|
+
True
|
1921
|
+
"""
|
1922
|
+
return mpfi_nan_p(self.__re) or mpfi_nan_p(self.__im)
|
1923
|
+
|
1924
|
+
def cos(self):
|
1925
|
+
r"""
|
1926
|
+
Compute the cosine of this complex interval.
|
1927
|
+
|
1928
|
+
EXAMPLES::
|
1929
|
+
|
1930
|
+
sage: CIF(1,1).cos()
|
1931
|
+
0.833730025131149? - 0.988897705762865?*I
|
1932
|
+
sage: CIF(3).cos()
|
1933
|
+
-0.9899924966004455?
|
1934
|
+
sage: CIF(0,2).cos()
|
1935
|
+
3.762195691083632?
|
1936
|
+
|
1937
|
+
Check that :issue:`17285` is fixed::
|
1938
|
+
|
1939
|
+
sage: CIF(cos(2/3)) # needs sage.symbolic
|
1940
|
+
0.7858872607769480?
|
1941
|
+
|
1942
|
+
ALGORITHM:
|
1943
|
+
|
1944
|
+
The implementation uses the following trigonometric identity
|
1945
|
+
|
1946
|
+
.. MATH::
|
1947
|
+
|
1948
|
+
\cos(x + iy) = \cos(x) \cosh(y) - i \sin(x) \sinh(y)
|
1949
|
+
"""
|
1950
|
+
res = self._new()
|
1951
|
+
cdef mpfi_t tmp
|
1952
|
+
mpfi_init2(tmp, self._parent.prec())
|
1953
|
+
sig_on()
|
1954
|
+
mpfi_cos(res.__re, self.__re)
|
1955
|
+
mpfi_cosh(tmp, self.__im)
|
1956
|
+
mpfi_mul(res.__re, res.__re, tmp)
|
1957
|
+
|
1958
|
+
mpfi_sin(res.__im, self.__re)
|
1959
|
+
mpfi_sinh(tmp, self.__im)
|
1960
|
+
mpfi_mul(res.__im, res.__im, tmp)
|
1961
|
+
mpfi_neg(res.__im, res.__im)
|
1962
|
+
sig_off()
|
1963
|
+
mpfi_clear(tmp)
|
1964
|
+
return res
|
1965
|
+
|
1966
|
+
def sin(self):
|
1967
|
+
r"""
|
1968
|
+
Compute the sine of this complex interval.
|
1969
|
+
|
1970
|
+
EXAMPLES::
|
1971
|
+
|
1972
|
+
sage: CIF(1,1).sin()
|
1973
|
+
1.298457581415978? + 0.634963914784736?*I
|
1974
|
+
sage: CIF(2).sin()
|
1975
|
+
0.909297426825682?
|
1976
|
+
sage: CIF(0,2).sin()
|
1977
|
+
3.626860407847019?*I
|
1978
|
+
|
1979
|
+
Check that :issue:`17825` is fixed::
|
1980
|
+
|
1981
|
+
sage: CIF(sin(2/3)) # needs sage.symbolic
|
1982
|
+
0.618369803069737?
|
1983
|
+
|
1984
|
+
ALGORITHM:
|
1985
|
+
|
1986
|
+
The implementation uses the following trigonometric identity
|
1987
|
+
|
1988
|
+
.. MATH::
|
1989
|
+
|
1990
|
+
\sin(x + iy) = \sin(x) \cosh(y) + i \cos (x) \sinh(y)
|
1991
|
+
"""
|
1992
|
+
res = self._new()
|
1993
|
+
cdef mpfi_t tmp
|
1994
|
+
mpfi_init2(tmp, self._parent.prec())
|
1995
|
+
sig_on()
|
1996
|
+
mpfi_sin(res.__re, self.__re)
|
1997
|
+
mpfi_cosh(tmp, self.__im)
|
1998
|
+
mpfi_mul(res.__re, res.__re, tmp)
|
1999
|
+
|
2000
|
+
mpfi_cos(res.__im, self.__re)
|
2001
|
+
mpfi_sinh(tmp, self.__im)
|
2002
|
+
mpfi_mul(res.__im, res.__im, tmp)
|
2003
|
+
sig_off()
|
2004
|
+
mpfi_clear(tmp)
|
2005
|
+
return res
|
2006
|
+
|
2007
|
+
def tan(self):
|
2008
|
+
r"""
|
2009
|
+
Return the tangent of this complex interval.
|
2010
|
+
|
2011
|
+
EXAMPLES::
|
2012
|
+
|
2013
|
+
sage: CIF(1,1).tan()
|
2014
|
+
0.27175258531952? + 1.08392332733870?*I
|
2015
|
+
sage: CIF(2).tan()
|
2016
|
+
-2.185039863261519?
|
2017
|
+
sage: CIF(0,2).tan()
|
2018
|
+
0.964027580075817?*I
|
2019
|
+
"""
|
2020
|
+
return self.sin() / self.cos()
|
2021
|
+
|
2022
|
+
def cosh(self):
|
2023
|
+
r"""
|
2024
|
+
Return the hyperbolic cosine of this complex interval.
|
2025
|
+
|
2026
|
+
EXAMPLES::
|
2027
|
+
|
2028
|
+
sage: CIF(1,1).cosh()
|
2029
|
+
0.833730025131149? + 0.988897705762865?*I
|
2030
|
+
sage: CIF(2).cosh()
|
2031
|
+
3.762195691083632?
|
2032
|
+
sage: CIF(0,2).cosh()
|
2033
|
+
-0.4161468365471424?
|
2034
|
+
|
2035
|
+
ALGORITHM:
|
2036
|
+
|
2037
|
+
The implementation uses the following trigonometric identity
|
2038
|
+
|
2039
|
+
.. MATH::
|
2040
|
+
|
2041
|
+
\cosh(x+iy) = \cos(y) \cosh(x) + i \sin(y) \sinh(x)
|
2042
|
+
"""
|
2043
|
+
res = self._new()
|
2044
|
+
cdef mpfi_t tmp
|
2045
|
+
mpfi_init2(tmp, self._parent.prec())
|
2046
|
+
sig_on()
|
2047
|
+
mpfi_cos(res.__re, self.__im)
|
2048
|
+
mpfi_cosh(tmp, self.__re)
|
2049
|
+
mpfi_mul(res.__re, res.__re, tmp)
|
2050
|
+
|
2051
|
+
mpfi_sin(res.__im, self.__im)
|
2052
|
+
mpfi_sinh(tmp, self.__re)
|
2053
|
+
mpfi_mul(res.__im, res.__im, tmp)
|
2054
|
+
sig_off()
|
2055
|
+
mpfi_clear(tmp)
|
2056
|
+
return res
|
2057
|
+
|
2058
|
+
def sinh(self):
|
2059
|
+
r"""
|
2060
|
+
Return the hyperbolic sine of this complex interval.
|
2061
|
+
|
2062
|
+
EXAMPLES::
|
2063
|
+
|
2064
|
+
sage: CIF(1,1).sinh()
|
2065
|
+
0.634963914784736? + 1.298457581415978?*I
|
2066
|
+
sage: CIF(2).sinh()
|
2067
|
+
3.626860407847019?
|
2068
|
+
sage: CIF(0,2).sinh()
|
2069
|
+
0.909297426825682?*I
|
2070
|
+
|
2071
|
+
ALGORITHM:
|
2072
|
+
|
2073
|
+
The implementation uses the following trigonometric identity
|
2074
|
+
|
2075
|
+
.. MATH::
|
2076
|
+
|
2077
|
+
\sinh(x+iy) = \cos(y) \sinh(x) + i \sin(y) \cosh(x)
|
2078
|
+
"""
|
2079
|
+
res = self._new()
|
2080
|
+
cdef mpfi_t tmp
|
2081
|
+
mpfi_init2(tmp, self._parent.prec())
|
2082
|
+
sig_on()
|
2083
|
+
mpfi_cos(res.__re, self.__im)
|
2084
|
+
mpfi_sinh(tmp, self.__re)
|
2085
|
+
mpfi_mul(res.__re, res.__re, tmp)
|
2086
|
+
|
2087
|
+
mpfi_sin(res.__im, self.__im)
|
2088
|
+
mpfi_cosh(tmp, self.__re)
|
2089
|
+
mpfi_mul(res.__im, res.__im, tmp)
|
2090
|
+
sig_off()
|
2091
|
+
mpfi_clear(tmp)
|
2092
|
+
return res
|
2093
|
+
|
2094
|
+
def tanh(self):
|
2095
|
+
r"""
|
2096
|
+
Return the hyperbolic tangent of this complex interval.
|
2097
|
+
|
2098
|
+
EXAMPLES::
|
2099
|
+
|
2100
|
+
sage: CIF(1,1).tanh()
|
2101
|
+
1.08392332733870? + 0.27175258531952?*I
|
2102
|
+
sage: CIF(2).tanh()
|
2103
|
+
0.964027580075817?
|
2104
|
+
sage: CIF(0,2).tanh()
|
2105
|
+
-2.185039863261519?*I
|
2106
|
+
"""
|
2107
|
+
return self.sinh() / self.cosh()
|
2108
|
+
|
2109
|
+
def zeta(self, a=None):
|
2110
|
+
"""
|
2111
|
+
Return the image of this interval by the Hurwitz zeta function.
|
2112
|
+
|
2113
|
+
For ``a = 1`` (or ``a = None``), this computes the Riemann zeta function.
|
2114
|
+
|
2115
|
+
EXAMPLES::
|
2116
|
+
|
2117
|
+
sage: zeta(CIF(2, 3))
|
2118
|
+
0.7980219851462757? - 0.1137443080529385?*I
|
2119
|
+
sage: _.parent()
|
2120
|
+
Complex Interval Field with 53 bits of precision
|
2121
|
+
sage: CIF(2, 3).zeta(1/2)
|
2122
|
+
-1.955171567161496? + 3.123301509220897?*I
|
2123
|
+
"""
|
2124
|
+
from sage.rings.complex_arb import ComplexBallField
|
2125
|
+
return ComplexBallField(self.prec())(self).zeta(a).\
|
2126
|
+
_complex_mpfi_(self._parent)
|
2127
|
+
|
2128
|
+
cdef _negate_interval(mpfr_ptr xmin, mpfr_ptr xmax):
|
2129
|
+
"""
|
2130
|
+
Negate interval with endpoints xmin and xmax in place.
|
2131
|
+
"""
|
2132
|
+
mpfr_swap(xmin, xmax)
|
2133
|
+
mpfr_neg(xmin, xmin, MPFR_RNDD)
|
2134
|
+
mpfr_neg(xmax, xmax, MPFR_RNDU)
|
2135
|
+
|
2136
|
+
cdef _inversion_coordinate(
|
2137
|
+
mpfr_ptr result, mpfr_ptr tmp,
|
2138
|
+
mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_denom, mpfr_rnd_t rnd):
|
2139
|
+
"""
|
2140
|
+
Compute the x-coordinate of the image of the point (x,y) under inversion.
|
2141
|
+
That is compute x / (x^2 + y^2).
|
2142
|
+
|
2143
|
+
rnd_denom determines how to round when computing the denominator.
|
2144
|
+
rnd determines how to round when doing the division.
|
2145
|
+
|
2146
|
+
This function expects the callee to allocate and pass an mpfr number tmp
|
2147
|
+
that will be used for intermediate computations. This way, an allocated
|
2148
|
+
mpfr number can be used in multiple calculations.
|
2149
|
+
"""
|
2150
|
+
|
2151
|
+
mpfr_sqr(tmp, x, rnd_denom)
|
2152
|
+
mpfr_sqr(result, y, rnd_denom)
|
2153
|
+
mpfr_add(tmp, tmp, result, rnd_denom)
|
2154
|
+
mpfr_div(result, x, tmp, rnd)
|
2155
|
+
|
2156
|
+
cdef _inversion_coordinate_pos_down(
|
2157
|
+
mpfr_ptr result, mpfr_ptr tmp,
|
2158
|
+
mpfr_srcptr x, mpfr_srcptr y):
|
2159
|
+
"""
|
2160
|
+
Computes a lower bound for x / (x^2 + y^2) assuming that x is non-negative.
|
2161
|
+
|
2162
|
+
Note that the result will not be NaN as long as x or y is positive.
|
2163
|
+
"""
|
2164
|
+
|
2165
|
+
# Let us check that we do not get NaN.
|
2166
|
+
# We need to check mpfr_div since it could return NaN if we divide by zero
|
2167
|
+
# (it currently returns +/-inf, but the documentation says this might be
|
2168
|
+
# subject to change).
|
2169
|
+
# We round up when computing the denominator and thus should get something
|
2170
|
+
# positive if x or y is positive. Even if, say, x is so small that squaring
|
2171
|
+
# produces something smaller than the smallest positive mpfr floating point
|
2172
|
+
# number, we get something non-zero because we round up.
|
2173
|
+
|
2174
|
+
_inversion_coordinate(
|
2175
|
+
result, tmp, x, y,
|
2176
|
+
MPFR_RNDU, # denominator rounding
|
2177
|
+
MPFR_RNDD) # division rounding
|
2178
|
+
|
2179
|
+
cdef _inversion_coordinate_pos_up(
|
2180
|
+
mpfr_ptr result, mpfr_ptr tmp,
|
2181
|
+
mpfr_srcptr x, mpfr_srcptr y):
|
2182
|
+
"""
|
2183
|
+
Computes an upper bound for x / (x^2 + y^2) assuming that x is non-negative.
|
2184
|
+
"""
|
2185
|
+
_inversion_coordinate(
|
2186
|
+
result, tmp, x, y,
|
2187
|
+
MPFR_RNDD, # denominator rounding
|
2188
|
+
MPFR_RNDU) # division rounding
|
2189
|
+
|
2190
|
+
cdef _inversion_coordinate_neg_down(
|
2191
|
+
mpfr_ptr result, mpfr_ptr tmp,
|
2192
|
+
mpfr_srcptr x, mpfr_srcptr y):
|
2193
|
+
"""
|
2194
|
+
Computes a lower bound for x / (x^2 + y^2) assuming that x is non-positive.
|
2195
|
+
"""
|
2196
|
+
_inversion_coordinate(
|
2197
|
+
result, tmp, x, y,
|
2198
|
+
MPFR_RNDD, # denominator rounding
|
2199
|
+
MPFR_RNDD) # division rounding
|
2200
|
+
|
2201
|
+
cdef _circle_invert_standard(
|
2202
|
+
mpfr_ptr amin, mpfr_ptr amax, mpfr_ptr bmin, mpfr_ptr bmax,
|
2203
|
+
mpfr_srcptr xmin, mpfr_srcptr xmax, mpfr_srcptr ymin, mpfr_srcptr ymax,
|
2204
|
+
bint crosses_x_axis, mpfr_prec_t prec):
|
2205
|
+
"""
|
2206
|
+
Assumes that the input [xmin, xmax] + [ymin, ymax] * I is in standard form
|
2207
|
+
as described above in ComplexIntervalFieldElement.__invert__ with
|
2208
|
+
crosses_x_axis saying whether case (II) applies.
|
2209
|
+
|
2210
|
+
Computes a complex interval [amin, amax] + [bmin, bmax] * I containing
|
2211
|
+
the image of the input under circle inversion f(z) = conjugate(1/z).
|
2212
|
+
"""
|
2213
|
+
|
2214
|
+
# Note that, by the maximum principle, it is sufficient to consider the
|
2215
|
+
# image of the boundary of the input rect which will be formed by four
|
2216
|
+
# arcs or line segments.
|
2217
|
+
|
2218
|
+
# It is useful to do a case analysis by considering whether the input
|
2219
|
+
# crosses the x-Axis, the north east or south east diagonal, respectively.
|
2220
|
+
#
|
2221
|
+
# Given standard form, the input also has to cross the north east
|
2222
|
+
# diagonal and x-Axis if it crosses the south east diagonal.
|
2223
|
+
#
|
2224
|
+
# Thus, we are left with five cases:
|
2225
|
+
#
|
2226
|
+
# NE diagonal x-Axis SE diagonal.
|
2227
|
+
# 1.
|
2228
|
+
# 2. crosses
|
2229
|
+
# 3. crosses
|
2230
|
+
# 4. crosses crosses
|
2231
|
+
# 5. crosses crosses crosses
|
2232
|
+
|
2233
|
+
# The reader can go to https://www.shadertoy.com/view/M3VXWG to explore
|
2234
|
+
# the different cases visually.
|
2235
|
+
|
2236
|
+
# Case 1 is the easiest (and the generic case for small intervals).
|
2237
|
+
#
|
2238
|
+
# Consider the images
|
2239
|
+
# f(xmin + ymin * I), ..., f(xmax + ymax * I)
|
2240
|
+
# of the four corners of the input rect under inversion f.
|
2241
|
+
# Now consider the axis-parallel rectangle R that these images span.
|
2242
|
+
# In general, the image of the input rect might not be contained in R.
|
2243
|
+
# In case 1, however, (and only in case 1) it is and we furthermore know
|
2244
|
+
# which image is mapped to which edge of R. Thus, we have:
|
2245
|
+
#
|
2246
|
+
# amin = Re(f(xmax + ymax * I)) # Image of right top corner
|
2247
|
+
# amax = Re(f(xmin + ymin * I)) # left bottom corner
|
2248
|
+
# bmin = Im(f(xmax + ymin * I)) # right bottom corner
|
2249
|
+
# = Re(f(ymin + xmax * I))
|
2250
|
+
# bmax = Im(f(xmin + ymax * I)) # left top corner
|
2251
|
+
# = Re(f(ymax + xmin * I))
|
2252
|
+
#
|
2253
|
+
# Re(f(...)) can be computed with the correct rounding using one of the
|
2254
|
+
# helper functions such as _inversion_coordinate_pos_down.
|
2255
|
+
|
2256
|
+
# For the other cases, we might need to consider the images of two corners
|
2257
|
+
# and take the minimum to compute, say amin.
|
2258
|
+
|
2259
|
+
# Furthermore, we also need to consider the image of t + xmin * I which is
|
2260
|
+
# a circle touching the y-Axis at the origin. Depending on which of the
|
2261
|
+
# diagonals and x-Axis the input rect crosses, we need to expand R to
|
2262
|
+
# include the lowest, highest or rightmost point on this circle for the
|
2263
|
+
# correct result.
|
2264
|
+
#
|
2265
|
+
# For example, we have
|
2266
|
+
# amax = 1 / xmin for case 2 and bmax = 1 / (2 * ymin) for case 3.
|
2267
|
+
#
|
2268
|
+
|
2269
|
+
cdef bint crosses_NE_diagonal = mpfr_cmp(ymax, xmin) > 0
|
2270
|
+
cdef bint crosses_both_diagonals = False
|
2271
|
+
# Using that input can only cross south east diagonal if it crosses
|
2272
|
+
# x-Axis and north east diagonal.
|
2273
|
+
if crosses_x_axis and crosses_NE_diagonal:
|
2274
|
+
crosses_both_diagonals = mpfr_cmpabs(ymin, xmin) > 0
|
2275
|
+
|
2276
|
+
# Some temporary variables
|
2277
|
+
cdef mpfr_t tmp, min2
|
2278
|
+
|
2279
|
+
mpfr_init2(tmp, prec)
|
2280
|
+
if crosses_NE_diagonal:
|
2281
|
+
# Temporary variable needed only in some cases.
|
2282
|
+
mpfr_init2(min2, prec)
|
2283
|
+
|
2284
|
+
########################################################################
|
2285
|
+
# Compute amin
|
2286
|
+
|
2287
|
+
# Use image of right top corner
|
2288
|
+
_inversion_coordinate_pos_down(amin, tmp, xmax, ymax)
|
2289
|
+
|
2290
|
+
if crosses_NE_diagonal:
|
2291
|
+
# Also use image of left top corner.
|
2292
|
+
|
2293
|
+
# This is because in this case, the image of the left top corner
|
2294
|
+
# can be left of the image of the right top corner.
|
2295
|
+
|
2296
|
+
_inversion_coordinate_pos_down(min2, tmp, xmin, ymax)
|
2297
|
+
|
2298
|
+
# Note that mpfr_min does not return NaN if one (but not the other)
|
2299
|
+
# input is NaN. This could be a problem. Luckily,
|
2300
|
+
# _inversion_coordinate_pos_down never produces NaN.
|
2301
|
+
mpfr_min(amin, amin, min2, MPFR_RNDD)
|
2302
|
+
|
2303
|
+
# Note that we do not need to consider the images of the left or right
|
2304
|
+
# bottom corner here. Not even in case 5.
|
2305
|
+
# This is because in standard form, the top edge is further aways from
|
2306
|
+
# the x-Axis than the bottom edge. Thus, the images of the left and
|
2307
|
+
# right corner of the top edge is left of those of the bottom edge,
|
2308
|
+
# respectively.
|
2309
|
+
|
2310
|
+
# Potential optimization: if bmax >= amax, we only need to use the
|
2311
|
+
# image of the left top corner and skip computing the image of the
|
2312
|
+
# right top corner.
|
2313
|
+
|
2314
|
+
########################################################################
|
2315
|
+
# Compute amax
|
2316
|
+
|
2317
|
+
if crosses_x_axis:
|
2318
|
+
# Use rightmost point on the circle that is the image of
|
2319
|
+
# image of t + xmin * I
|
2320
|
+
mpfr_ui_div(amax, 1, xmin, MPFR_RNDU)
|
2321
|
+
else:
|
2322
|
+
# Use image of left bottom corner
|
2323
|
+
_inversion_coordinate_pos_up(amax, tmp, xmin, ymin)
|
2324
|
+
|
2325
|
+
########################################################################
|
2326
|
+
# Compute bmax
|
2327
|
+
|
2328
|
+
# In case 5, bmin can reuse bmax (up to sign), so we compute bmax first.
|
2329
|
+
|
2330
|
+
if crosses_NE_diagonal:
|
2331
|
+
# Use highest point on the circle that is the image of
|
2332
|
+
# t + xmin * I. That is bmax = 1 / (2 * xmin).
|
2333
|
+
if crosses_x_axis:
|
2334
|
+
# Re-use amax = 1 / xmin.
|
2335
|
+
# We can just copy the mantissa and decrease the exponent by 1.
|
2336
|
+
mpfr_div_2ui(bmax, amax, 1, MPFR_RNDU)
|
2337
|
+
else:
|
2338
|
+
# Compute bmax from scratch.
|
2339
|
+
mpfr_ui_div(bmax, 1, xmin, MPFR_RNDU)
|
2340
|
+
mpfr_div_2ui(bmax, bmax, 1, MPFR_RNDU)
|
2341
|
+
else:
|
2342
|
+
# Use image of of left top corner
|
2343
|
+
_inversion_coordinate_pos_up(bmax, tmp, ymax, xmin)
|
2344
|
+
|
2345
|
+
########################################################################
|
2346
|
+
# Compute bmin
|
2347
|
+
|
2348
|
+
# bmin is probably the hardest to compute.
|
2349
|
+
|
2350
|
+
cdef bint right_edge_crosses_NE_diagonal
|
2351
|
+
|
2352
|
+
if crosses_x_axis:
|
2353
|
+
# ymin and thus bmin will be negative.
|
2354
|
+
if crosses_both_diagonals:
|
2355
|
+
# We are in case 5.
|
2356
|
+
#
|
2357
|
+
# Use lowest point on the circle that is the image of
|
2358
|
+
# t + xmin * I. That is bmin = -1 / (2 * xmin).
|
2359
|
+
#
|
2360
|
+
# We can reuse bmax = 1 / (2 * xmin).
|
2361
|
+
mpfr_neg(bmin, bmax, MPFR_RNDD)
|
2362
|
+
else:
|
2363
|
+
# Use image of left bottom corner.
|
2364
|
+
_inversion_coordinate_neg_down(bmin, tmp, ymin, xmin)
|
2365
|
+
else:
|
2366
|
+
# ymin and thus bmin will be non-negative.
|
2367
|
+
|
2368
|
+
# Use image of right bottom corner.
|
2369
|
+
_inversion_coordinate_pos_down(bmin, tmp, ymin, xmax)
|
2370
|
+
|
2371
|
+
if crosses_NE_diagonal:
|
2372
|
+
right_edge_crosses_NE_diagonal = mpfr_cmp(ymax, xmax) > 0
|
2373
|
+
if right_edge_crosses_NE_diagonal:
|
2374
|
+
# Also use image of right top corner.
|
2375
|
+
#
|
2376
|
+
# This is similar to the computation of amin which also
|
2377
|
+
# considered a second corner when crosses_NE_diagonal.
|
2378
|
+
#
|
2379
|
+
# In particular, the same comment about NaN applies.
|
2380
|
+
#
|
2381
|
+
_inversion_coordinate_pos_down(min2, tmp, ymax, xmax)
|
2382
|
+
|
2383
|
+
# See comment about NaN above.
|
2384
|
+
mpfr_min(bmin, bmin, min2, MPFR_RNDD)
|
2385
|
+
|
2386
|
+
########################################################################
|
2387
|
+
# Free memory
|
2388
|
+
|
2389
|
+
mpfr_clear(tmp)
|
2390
|
+
if crosses_NE_diagonal:
|
2391
|
+
mpfr_clear(min2)
|
2392
|
+
|
2393
|
+
|
2394
|
+
def make_ComplexIntervalFieldElement0( fld, re, im ):
|
2395
|
+
"""
|
2396
|
+
Construct a :class:`ComplexIntervalFieldElement` for pickling.
|
2397
|
+
|
2398
|
+
TESTS::
|
2399
|
+
|
2400
|
+
sage: a = CIF(1 + I)
|
2401
|
+
sage: loads(dumps(a)) == a # indirect doctest
|
2402
|
+
True
|
2403
|
+
"""
|
2404
|
+
return fld(re, im)
|
2405
|
+
|
2406
|
+
|
2407
|
+
def create_ComplexIntervalFieldElement(s_real, s_imag=None, int pad=0, min_prec=53):
|
2408
|
+
r"""
|
2409
|
+
Return the complex number defined by the strings ``s_real`` and ``s_imag``
|
2410
|
+
as an element of ``ComplexIntervalField(prec=n)``, where `n` potentially
|
2411
|
+
has slightly more (controlled by pad) bits than given by `s`.
|
2412
|
+
|
2413
|
+
INPUT:
|
2414
|
+
|
2415
|
+
- ``s_real`` -- string that defines a real number (or something whose
|
2416
|
+
string representation defines a number)
|
2417
|
+
|
2418
|
+
- ``s_imag`` -- string that defines a real number (or something whose
|
2419
|
+
string representation defines a number)
|
2420
|
+
|
2421
|
+
- ``pad`` -- integer at least 0
|
2422
|
+
|
2423
|
+
- ``min_prec`` -- number will have at least this many bits of precision,
|
2424
|
+
no matter what
|
2425
|
+
|
2426
|
+
EXAMPLES::
|
2427
|
+
|
2428
|
+
sage: ComplexIntervalFieldElement('2.3')
|
2429
|
+
2.300000000000000?
|
2430
|
+
sage: ComplexIntervalFieldElement('2.3','1.1')
|
2431
|
+
2.300000000000000? + 1.100000000000000?*I
|
2432
|
+
sage: ComplexIntervalFieldElement(10)
|
2433
|
+
10
|
2434
|
+
sage: ComplexIntervalFieldElement(10,10)
|
2435
|
+
10 + 10*I
|
2436
|
+
sage: ComplexIntervalFieldElement(1.000000000000000000000000000,2)
|
2437
|
+
1 + 2*I
|
2438
|
+
sage: ComplexIntervalFieldElement(1,2.000000000000000000000)
|
2439
|
+
1 + 2*I
|
2440
|
+
sage: ComplexIntervalFieldElement(1.234567890123456789012345, 5.4321098654321987654321)
|
2441
|
+
1.234567890123456789012350? + 5.432109865432198765432000?*I
|
2442
|
+
|
2443
|
+
TESTS:
|
2444
|
+
|
2445
|
+
Make sure we've rounded up ``log(10,2)`` enough to guarantee
|
2446
|
+
sufficient precision (:issue:`10164`). This is a little tricky
|
2447
|
+
because at the time of writing, we don't support intervals long
|
2448
|
+
enough to trip the error. However, at least we can make sure that
|
2449
|
+
we either do it correctly or fail noisily::
|
2450
|
+
|
2451
|
+
sage: c_CIFE = sage.rings.complex_interval.create_ComplexIntervalFieldElement
|
2452
|
+
sage: for kp in range(2,6):
|
2453
|
+
....: s = '1.' + '0'*10**kp + '1'
|
2454
|
+
....: try:
|
2455
|
+
....: assert c_CIFE(s,0).real()-1 != 0
|
2456
|
+
....: assert c_CIFE(0,s).imag()-1 != 0
|
2457
|
+
....: except TypeError:
|
2458
|
+
....: pass
|
2459
|
+
"""
|
2460
|
+
if s_imag is None:
|
2461
|
+
s_imag = 0
|
2462
|
+
|
2463
|
+
if not isinstance(s_real, str):
|
2464
|
+
s_real = str(s_real).strip()
|
2465
|
+
if not isinstance(s_imag, str):
|
2466
|
+
s_imag = str(s_imag).strip()
|
2467
|
+
#if base == 10:
|
2468
|
+
bits = max(int(LOG_TEN_TWO_PLUS_EPSILON*len(s_real)),
|
2469
|
+
int(LOG_TEN_TWO_PLUS_EPSILON*len(s_imag)))
|
2470
|
+
#else:
|
2471
|
+
# bits = max(int(math.log(base,2)*len(s_imag)),int(math.log(base,2)*len(s_imag)))
|
2472
|
+
|
2473
|
+
from sage.rings.complex_interval_field import ComplexIntervalField
|
2474
|
+
C = ComplexIntervalField(prec=max(bits+pad, min_prec))
|
2475
|
+
return ComplexIntervalFieldElement(C, s_real, s_imag)
|