diff --git a/VERSION.txt b/VERSION.txt index 20494d07023..b503aeef942 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 8.2.beta3, Release Date: 2018-01-17 +SageMath version 8.2.beta4, Release Date: 2018-01-27 diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 80f6370a8ec..b86336cdc35 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -21,6 +21,7 @@ # SAGE_ROOT -- root directory of sage install # SAGE_LOCAL -- $SAGE_ROOT/local # SAGE_DISTFILES -- directory that stores upstream tarballs +# SAGE_DESTDIR -- temporary root the package will be installed to # PKG_BASE -- the base name of the package itself (e.g. 'patch') # PKG_VER -- the version number of the package # PKG_NAME -- $PKG_BASE-$PKG_VER @@ -804,6 +805,10 @@ export rsync_proxy=$http_proxy # Actually install ################################################################## +# Set the $SAGE_DESTDIR variable to be passed to the spkg-install +# script (the script itself could set this, but better to standardize +# this in one place) +export SAGE_DESTDIR="${SAGE_BUILD_DIR}/${PKG_NAME}/inst" if [ -f spkg-build ]; then # Package has both spkg-build and spkg-install; execute the latter with SAGE_SUDO @@ -826,6 +831,46 @@ else fi fi +# All spkgs should eventually support this, but fall back on old behavior in +# case DESTDIR=$SAGE_DESTDIR installation was not used +echo "Copying package files from temporary location $SAGE_DESTDIR to $SAGE_LOCAL" +if [ -d "$SAGE_DESTDIR" ]; then + PREFIX="${SAGE_DESTDIR}${SAGE_LOCAL%/}/" + + rm -f "$PREFIX"lib/*.la + if [ $? -ne 0 ]; then + error_msg "Error deleting unnecessary libtool archive files" + exit 1 + fi + + # Generate installed file manifest + FILE_LIST="" + FIRST=1 + IFS=$'\n' + for filename in $(find "$PREFIX" -type f -o -type l | sort); do + filename="${filename#$PREFIX}" + if [ $FIRST -eq 1 ]; then + FILE_LIST="\"$filename\"" + FIRST=0 + else + FILE_LIST="${FILE_LIST},"$'\n '"\"${filename}\"" + fi + # Copy file from the temp install path into $SAGE_LOCAL + if [ ! -d "$SAGE_LOCAL/$(dirname "$filename")" ]; then + mkdir -p "$SAGE_LOCAL/$(dirname "$filename")" + fi + mv "$PREFIX$filename" "${SAGE_LOCAL%/}/$filename" + if [ $? -ne 0 ]; then + error_msg "Error moving files for $PKG_BASE." + exit 1 + fi + done + + # Remove the $SAGE_DESTDIR entirely once all files have been moved to their + # final location. + rm -rf "$SAGE_DESTDIR" +fi + if [ "$UNAME" = "CYGWIN" ]; then # Rebase after installing each package--in case any packages load this # package at build time we need to ensure during the build that no binaries @@ -834,7 +879,11 @@ if [ "$UNAME" = "CYGWIN" ]; then sage-rebase.sh "$SAGE_LOCAL" 2>/dev/null fi -echo "Successfully installed $PKG_NAME" + +# Note: spkg-check tests are run after the package has been copied into +# SAGE_LOCAL. It might make more sense to run the tests before, but the +# spkg-check scripts were written before use of DESTDIR installs, and so +# fail in many cases. This might be good to change later. if [ "$SAGE_CHECK" = "yes" ]; then if [ -f spkg-check ]; then @@ -851,11 +900,6 @@ if [ "$SAGE_CHECK" = "yes" ]; then fi fi -rm -f "$SAGE_LOCAL"/lib/*.la -if [ $? -ne 0 ]; then - error_msg "Error deleting unnecessary libtool archive files" - exit 1 -fi # Mark that the new package has been installed (and tested, if # applicable). @@ -867,11 +911,17 @@ cat > "$PKG_NAME_INSTALLED" << __EOF__ "install_date": "$(date)", "system_uname": "$(uname -a)", "sage_version": "$(cat "${SAGE_ROOT}/VERSION.txt")", - "test_result": "$TEST_SUITE_RESULT" + "test_result": "$TEST_SUITE_RESULT", + "files": [ + $FILE_LIST + ] } __EOF__ +echo "Successfully installed $PKG_NAME" + + ################################################################## # Delete the temporary build directory if required ################################################################## diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 680bb78988f..41fb4d74819 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=fce3f8df178645228d91b6b65e3a03af0b2b3641 -md5=587c7e18518428f0f30138eeb7743bad -cksum=144653522 +sha1=499badf9321c53c458652ca71580585463e574a3 +md5=e483eb587a1be5886b718e24f54a84a5 +cksum=3889320352 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 1f7e0d6eac6..2197544d04c 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -251 +252 diff --git a/build/pkgs/ecl/spkg-install b/build/pkgs/ecl/spkg-install index 226af5333e8..7ee84ec5bd8 100644 --- a/build/pkgs/ecl/spkg-install +++ b/build/pkgs/ecl/spkg-install @@ -81,13 +81,13 @@ sdh_make_install # Create symbolic link to lib/ecl-version directory. # Also create a symbolic link lib/ecl/ecl -> include/ecl. # This is important when the Sage install is moved, see Trac #14662. -cd "$SAGE_LOCAL/lib/" && rm -f ecl && ln -s ecl-* ecl +cd "$SAGE_DESTDIR$SAGE_LOCAL/lib/" && rm -f ecl && ln -s ecl-* ecl if [ $? -ne 0 ]; then echo >&2 "Error - Failed to create symbolic link to ECL library" echo >&2 "directory ... exiting" exit 1 fi -cd "$SAGE_LOCAL/lib/ecl" && rm -f ecl && ln -s ../../include/ecl ecl +cd "$SAGE_DESTDIR$SAGE_LOCAL/lib/ecl" && rm -f ecl && ln -s ../../include/ecl ecl if [ $? -ne 0 ]; then echo >&2 "Error - Failed to create symbolic link to ECL include" echo >&2 "directory ... exiting" diff --git a/build/pkgs/gcc/spkg-install b/build/pkgs/gcc/spkg-install index e9a068f8675..a346ae73af0 100644 --- a/build/pkgs/gcc/spkg-install +++ b/build/pkgs/gcc/spkg-install @@ -123,8 +123,9 @@ $MAKE install # Force re-installation of gmp, mpir, mpfr and mpc with the GCC we just built. +# Also mark gfortran as not installed. cd "$SAGE_SPKG_INST" -rm -f gmp-* mpir-* mpfr-* mpc-* +rm -f gmp-* mpir-* mpfr-* mpc-* gfortran-* # Force re-configuration: the next time that "make" is run, we don't # want GCC to be built again, see Trac #19324 diff --git a/build/pkgs/giac/checksums.ini b/build/pkgs/giac/checksums.ini index 27861689d59..ae2283791d5 100644 --- a/build/pkgs/giac/checksums.ini +++ b/build/pkgs/giac/checksums.ini @@ -1,4 +1,4 @@ tarball=giac-VERSION.tar.bz2 -sha1=79503a2c2ee1ffe996727d09ebe6c6be3554434c -md5=ad15340533a7308f30b739bc36991a56 -cksum=2233538356 +sha1=3b61dd5fe79a76c2e0d4ef60ad1ad90dc3c04bd3 +md5=55308225758c547b061b52d699fa8b13 +cksum=2762392051 diff --git a/build/pkgs/giac/package-version.txt b/build/pkgs/giac/package-version.txt index ad6d053bf90..f7272f4bb5c 100644 --- a/build/pkgs/giac/package-version.txt +++ b/build/pkgs/giac/package-version.txt @@ -1 +1 @@ -1.2.3.47.p1 +1.4.9.45 diff --git a/build/pkgs/giac/patches/README.txt b/build/pkgs/giac/patches/README.txt index 691aca83157..93e759e6cc5 100644 --- a/build/pkgs/giac/patches/README.txt +++ b/build/pkgs/giac/patches/README.txt @@ -6,6 +6,3 @@ (xcas, qcas). http://xcas.e.ujf-grenoble.fr/XCAS/viewtopic.php?f=4&t=1555. The macos-ifactor patch enables pari in ifactor under osx because the problem can't be reproduced with the spkg library. - -* the pari2.8 patch is because some outputs in the check suite differs when giac is built - with pari 2.8 vs 2.7. (One more keyword and a different ordering in a sum) diff --git a/build/pkgs/giac/patches/cSolveorder-check.patch b/build/pkgs/giac/patches/cSolveorder-check.patch deleted file mode 100644 index 08a155138b7..00000000000 --- a/build/pkgs/giac/patches/cSolveorder-check.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/check/TP16-sol.cas.out1 2016-07-16 14:21:09.000000000 +0200 -+++ b/check/TP16-sol.cas.out1 2016-09-14 14:08:07.110527423 +0200 -@@ -48,7 +48,7 @@ - "Done", - [-sqrt(13)-1,sqrt(13)-1,4], - y^2+6*sqrt(13)+18,y^2-6*sqrt(13)+18,y^2, ---sqrt(6)*I*sqrt(sqrt(13)+3),sqrt(6)*I*sqrt(sqrt(13)+3),-sqrt(6)*sqrt(sqrt(13)-3),sqrt(6)*sqrt(sqrt(13)-3),0, -+sqrt(6)*I*sqrt(sqrt(13)+3),-sqrt(6)*I*sqrt(sqrt(13)+3),-sqrt(6)*sqrt(sqrt(13)-3),sqrt(6)*sqrt(sqrt(13)-3),0, - "No such variable u", - x^2+1/4*y^2+1/9*z^2-1, - x^2+y^2+z^2-u, diff --git a/build/pkgs/giac/patches/libpng16.patch b/build/pkgs/giac/patches/libpng16.patch deleted file mode 100644 index b6ba599c4e5..00000000000 --- a/build/pkgs/giac/patches/libpng16.patch +++ /dev/null @@ -1,62 +0,0 @@ -Make sure libpng 1.6x as provided by sage is used. ---- giac/configure.in 2017-06-19 13:50:43.676339211 +0000 -+++ giac.patched/configure.in 2017-06-19 13:51:38.986548183 +0000 -@@ -100,7 +100,7 @@ - [ if test "x$enableval" = "xno"; then CONFIG_PNG="no"; fi], []) - - if test "x$CONFIG_PNG" = "xyes"; then -- AC_CHECK_HEADERS(png.h, AC_CHECK_LIB(png,main)) -+ AC_CHECK_HEADERS(png.h, AC_CHECK_LIB(png16,main)) - fi - - ---- giac/configure 2017-05-28 12:54:29.000000000 +0000 -+++ giac.patched/configure 2017-06-19 13:51:54.826611543 +0000 -@@ -15482,13 +15550,13 @@ - cat >>confdefs.h <<_ACEOF - #define HAVE_PNG_H 1 - _ACEOF -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpng" >&5 --$as_echo_n "checking for main in -lpng... " >&6; } --if ${ac_cv_lib_png_main+:} false; then : -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpng16" >&5 -+$as_echo_n "checking for main in -lpng16... " >&6; } -+if ${ac_cv_lib_png16_main+:} false; then : - $as_echo_n "(cached) " >&6 - else - ac_check_lib_save_LIBS=$LIBS --LIBS="-lpng $LIBS" -+LIBS="-lpng16 $LIBS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - -@@ -15502,22 +15570,22 @@ - } - _ACEOF - if ac_fn_cxx_try_link "$LINENO"; then : -- ac_cv_lib_png_main=yes -+ ac_cv_lib_png16_main=yes - else -- ac_cv_lib_png_main=no -+ ac_cv_lib_png16_main=no - fi - rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LIBS=$ac_check_lib_save_LIBS - fi --{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_main" >&5 --$as_echo "$ac_cv_lib_png_main" >&6; } --if test "x$ac_cv_lib_png_main" = xyes; then : -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png16_main" >&5 -+$as_echo "$ac_cv_lib_png16_main" >&6; } -+if test "x$ac_cv_lib_png16_main" = xyes; then : - cat >>confdefs.h <<_ACEOF --#define HAVE_LIBPNG 1 -+#define HAVE_LIBPNG16 1 - _ACEOF - -- LIBS="-lpng $LIBS" -+ LIBS="-lpng16 $LIBS" - - fi - diff --git a/build/pkgs/giac/spkg-src b/build/pkgs/giac/spkg-src index 6706f87ed38..d82372402ef 100755 --- a/build/pkgs/giac/spkg-src +++ b/build/pkgs/giac/spkg-src @@ -13,9 +13,8 @@ fi # Exit on failure set -e -# TODO on the next update: l71 switch from gz to bz2 as wished in #18826 -VERSION="1.2.3" -VERSIONREV="47" +VERSION="1.4.9" +VERSIONREV="45" # The upstream tarball name is: giac"$SOURCEORIG".tar.gz SOURCEORIG=_"$VERSION"-"$VERSIONREV" diff --git a/build/pkgs/jupyter_client/checksums.ini b/build/pkgs/jupyter_client/checksums.ini index 84292b0761e..ab30f0430b2 100644 --- a/build/pkgs/jupyter_client/checksums.ini +++ b/build/pkgs/jupyter_client/checksums.ini @@ -1,4 +1,4 @@ tarball=jupyter_client-VERSION.tar.gz -sha1=1f226cd2d437eed5f9c45d572c0c9efe53437ea9 -md5=990ab28f63861cc29f90585d3f725b10 -cksum=1587833857 +sha1=2290704671547049ee20b034135a7a191fbc26f1 +md5=03293d63b59a3f71c417ee907852b460 +cksum=3064225526 diff --git a/build/pkgs/jupyter_client/package-version.txt b/build/pkgs/jupyter_client/package-version.txt index 831446cbd27..ce7f2b425b5 100644 --- a/build/pkgs/jupyter_client/package-version.txt +++ b/build/pkgs/jupyter_client/package-version.txt @@ -1 +1 @@ -5.1.0 +5.2.2 diff --git a/build/pkgs/mpc/checksums.ini b/build/pkgs/mpc/checksums.ini index c97e6b75889..70fbea4b5be 100644 --- a/build/pkgs/mpc/checksums.ini +++ b/build/pkgs/mpc/checksums.ini @@ -1,4 +1,4 @@ tarball=mpc-VERSION.tar.gz -sha1=b8be66396c726fdc36ebb0f692ed8a8cca3bcc66 -md5=d6a1d5f8ddea3abd2cc3e98f58352d26 -cksum=1941630434 +sha1=b019d9e1d27ec5fb99497159d43a3164995de2d0 +md5=4125404e41e482ec68282a2e687f6c73 +cksum=3987925640 diff --git a/build/pkgs/mpc/package-version.txt b/build/pkgs/mpc/package-version.txt index 3b69baff860..9084fa2f716 100644 --- a/build/pkgs/mpc/package-version.txt +++ b/build/pkgs/mpc/package-version.txt @@ -1 +1 @@ -1.0.3.p1 +1.1.0 diff --git a/build/pkgs/mpc/patches/mpc_mul_faster.patch b/build/pkgs/mpc/patches/mpc_mul_faster.patch deleted file mode 100644 index 5fc59a1bffc..00000000000 --- a/build/pkgs/mpc/patches/mpc_mul_faster.patch +++ /dev/null @@ -1,124 +0,0 @@ -diff -ru src/src/mul.c b/src/mul.c ---- src/src/mul.c 2012-07-22 17:40:22.000000000 +0200 -+++ b/src/mul.c 2014-01-27 15:12:37.449617411 +0100 -@@ -170,6 +170,10 @@ - return MPC_INEX (inex_re, inex_im); - } - -+#define MPFR_MANT(x) ((x)->_mpfr_d) -+#define MPFR_PREC(x) ((x)->_mpfr_prec) -+#define MPFR_EXP(x) ((x)->_mpfr_exp) -+#define MPFR_LIMB_SIZE(x) ((MPFR_PREC (x) - 1) / GMP_NUMB_BITS + 1) - - static int - mpfr_fmma (mpfr_ptr z, mpfr_srcptr a, mpfr_srcptr b, mpfr_srcptr c, -@@ -183,33 +187,68 @@ - - int inex; - mpfr_t u, v; -+ mp_size_t an, bn, cn, dn; - - /* u=a*b, v=sign*c*d exactly */ -- mpfr_init2 (u, mpfr_get_prec (a) + mpfr_get_prec (b)); -- mpfr_init2 (v, mpfr_get_prec (c) + mpfr_get_prec (d)); -- mpfr_mul (u, a, b, GMP_RNDN); -- mpfr_mul (v, c, d, GMP_RNDN); -- if (sign < 0) -- mpfr_neg (v, v, GMP_RNDN); -+ an = MPFR_LIMB_SIZE(a); -+ bn = MPFR_LIMB_SIZE(b); -+ cn = MPFR_LIMB_SIZE(c); -+ dn = MPFR_LIMB_SIZE(d); -+ MPFR_MANT(u) = malloc ((an + bn) * sizeof (mp_limb_t)); -+ MPFR_MANT(v) = malloc ((cn + dn) * sizeof (mp_limb_t)); -+ if (an >= bn) -+ mpn_mul (MPFR_MANT(u), MPFR_MANT(a), an, MPFR_MANT(b), bn); -+ else -+ mpn_mul (MPFR_MANT(u), MPFR_MANT(b), bn, MPFR_MANT(a), an); -+ if ((MPFR_MANT(u)[an + bn - 1] >> (GMP_NUMB_BITS - 1)) == 0) -+ { -+ mpn_lshift (MPFR_MANT(u), MPFR_MANT(u), an + bn, 1); -+ MPFR_EXP(u) = MPFR_EXP(a) + MPFR_EXP(b) - 1; -+ } -+ else -+ MPFR_EXP(u) = MPFR_EXP(a) + MPFR_EXP(b); -+ if (cn >= dn) -+ mpn_mul (MPFR_MANT(v), MPFR_MANT(c), cn, MPFR_MANT(d), dn); -+ else -+ mpn_mul (MPFR_MANT(v), MPFR_MANT(d), dn, MPFR_MANT(c), cn); -+ if ((MPFR_MANT(v)[cn + dn - 1] >> (GMP_NUMB_BITS - 1)) == 0) -+ { -+ mpn_lshift (MPFR_MANT(v), MPFR_MANT(v), cn + dn, 1); -+ MPFR_EXP(v) = MPFR_EXP(c) + MPFR_EXP(d) - 1; -+ } -+ else -+ MPFR_EXP(v) = MPFR_EXP(c) + MPFR_EXP(d); -+ MPFR_PREC(u) = (an + bn) * GMP_NUMB_BITS; -+ MPFR_PREC(v) = (cn + dn) * GMP_NUMB_BITS; -+ MPFR_SIGN(u) = MPFR_SIGN(a) * MPFR_SIGN(b); -+ if (sign > 0) -+ MPFR_SIGN(v) = MPFR_SIGN(c) * MPFR_SIGN(d); -+ else -+ MPFR_SIGN(v) = -MPFR_SIGN(c) * MPFR_SIGN(d); -+ -+ mpfr_check_range (u, 0, GMP_RNDN); -+ mpfr_check_range (v, 0, GMP_RNDN); - - /* tentatively compute z as u+v; here we need z to be distinct - from a, b, c, d to not lose the latter */ - inex = mpfr_add (z, u, v, rnd); -- -- if (mpfr_inf_p (z)) { -- /* replace by "correctly rounded overflow" */ -- mpfr_set_si (z, (mpfr_signbit (z) ? -1 : 1), GMP_RNDN); -- inex = mpfr_mul_2ui (z, z, mpfr_get_emax (), rnd); -- } -- else if (mpfr_zero_p (u) && !mpfr_zero_p (v)) { -- /* exactly u underflowed, determine inexact flag */ -- inex = (mpfr_signbit (u) ? 1 : -1); -- } -- else if (mpfr_zero_p (v) && !mpfr_zero_p (u)) { -- /* exactly v underflowed, determine inexact flag */ -- inex = (mpfr_signbit (v) ? 1 : -1); -- } -- else if (mpfr_nan_p (z) || (mpfr_zero_p (u) && mpfr_zero_p (v))) { -+ -+ if (!mpfr_regular_p(z) || !mpfr_regular_p(u) || !mpfr_regular_p(v)) -+ { -+ if (mpfr_inf_p (z)) { -+ /* replace by "correctly rounded overflow" */ -+ mpfr_set_si (z, (mpfr_signbit (z) ? -1 : 1), GMP_RNDN); -+ inex = mpfr_mul_2ui (z, z, mpfr_get_emax (), rnd); -+ } -+ else if (mpfr_zero_p (u) && !mpfr_zero_p (v)) { -+ /* exactly u underflowed, determine inexact flag */ -+ inex = (mpfr_signbit (u) ? 1 : -1); -+ } -+ else if (mpfr_zero_p (v) && !mpfr_zero_p (u)) { -+ /* exactly v underflowed, determine inexact flag */ -+ inex = (mpfr_signbit (v) ? 1 : -1); -+ } -+ else if (mpfr_nan_p (z) || (mpfr_zero_p (u) && mpfr_zero_p (v))) { - /* In the first case, u and v are infinities with opposite signs. - In the second case, u and v are zeroes; their sum may be 0 or the - least representable number, with a sign to be determined. -@@ -312,15 +351,14 @@ - mpfr_set_exp ((mpfr_ptr) c, ec); - mpfr_set_exp ((mpfr_ptr) d, ed); - /* works also when some of a, b, c, d are not all distinct */ -- } -- -- mpfr_clear (u); -- mpfr_clear (v); -+ } -+ } - -+ free (MPFR_MANT(u)); -+ free (MPFR_MANT(v)); - return inex; - } - -- - int - mpc_mul_naive (mpc_ptr z, mpc_srcptr x, mpc_srcptr y, mpc_rnd_t rnd) - { diff --git a/build/pkgs/mpfi/checksums.ini b/build/pkgs/mpfi/checksums.ini index 108e255e173..6d6940e0237 100644 --- a/build/pkgs/mpfi/checksums.ini +++ b/build/pkgs/mpfi/checksums.ini @@ -1,4 +1,4 @@ tarball=mpfi-VERSION.tar.bz2 -sha1=68773ce05e89e0f968687dd82d402f80ccc4c31f -md5=50d05e9d6f20a07c043b3b038927a456 -cksum=2405993671 +sha1=6a44e59f69fa72b4fe1c67b9c9ccf678f321ef80 +md5=1c233f3646bfb8a363aee0cc653c8baa +cksum=4291278873 diff --git a/build/pkgs/mpfi/package-version.txt b/build/pkgs/mpfi/package-version.txt index 343372e95da..4cda8f19edc 100644 --- a/build/pkgs/mpfi/package-version.txt +++ b/build/pkgs/mpfi/package-version.txt @@ -1 +1 @@ -1.5.1.p0 +1.5.2 diff --git a/build/pkgs/mpfi/spkg-install b/build/pkgs/mpfi/spkg-install index 7c5aaf3ac45..fad7f89a9eb 100644 --- a/build/pkgs/mpfi/spkg-install +++ b/build/pkgs/mpfi/spkg-install @@ -19,7 +19,7 @@ sdh_configure --with-mpfr="$SAGE_LOCAL" --with-gmp="$SAGE_LOCAL" sdh_make sdh_make_install -if ! [ $? -eq 0 -a -f $SAGE_LOCAL/include/mpfi.h ]; then +if ! [ $? -eq 0 -a -f $SAGE_DESTDIR$SAGE_LOCAL/include/mpfi.h ]; then echo "An error occurred while building MPFI." exit 1 fi diff --git a/build/pkgs/mpfr/checksums.ini b/build/pkgs/mpfr/checksums.ini index cd5a5a629d9..2728dda9c04 100644 --- a/build/pkgs/mpfr/checksums.ini +++ b/build/pkgs/mpfr/checksums.ini @@ -1,4 +1,4 @@ tarball=mpfr-VERSION.tar.bz2 -sha1=874e84bb5959fd5a19c032cfb5d673dded4b5cff -md5=b1d23a55588e3b2a13e3be66bc69fd8d -cksum=3347469031 +sha1=799245347044c8f0da9e513f86bb5e4c07974931 +md5=ef619f3bb68039e35c4a219e06be72d0 +cksum=3469661192 diff --git a/build/pkgs/mpfr/package-version.txt b/build/pkgs/mpfr/package-version.txt index fc261c4280b..fcdb2e109f6 100644 --- a/build/pkgs/mpfr/package-version.txt +++ b/build/pkgs/mpfr/package-version.txt @@ -1 +1 @@ -3.1.5.p0 +4.0.0 diff --git a/build/pkgs/mpfr/patches/clang_workaround.patch b/build/pkgs/mpfr/patches/clang_workaround.patch deleted file mode 100644 index 845ee1accef..00000000000 --- a/build/pkgs/mpfr/patches/clang_workaround.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/src/set_d.c b/src/set_d.c -index c076ccf..5fc9548 100644 ---- a/src/set_d.c -+++ b/src/set_d.c -@@ -118,8 +118,15 @@ __gmpfr_extract_double (mpfr_limb_ptr rp, double d) - - d *= MP_BASE_AS_DOUBLE; - #if GMP_NUMB_BITS >= 64 -+#ifndef __clang__ - manl = d; - #else -+ /* clang produces an invalid exception when d >= 2^63, -+ see https://bugs.llvm.org//show_bug.cgi?id=17686. -+ Since this is always the case, here, we use the following patch. */ -+ manl = 0x8000000000000000 + (mp_limb_t) (d - 0x8000000000000000); -+#endif /* __clang__ */ -+#else - manh = (mp_limb_t) d; - manl = (mp_limb_t) ((d - manh) * MP_BASE_AS_DOUBLE); - #endif diff --git a/build/pkgs/notebook/checksums.ini b/build/pkgs/notebook/checksums.ini index ce2119db22a..214164b6dd1 100644 --- a/build/pkgs/notebook/checksums.ini +++ b/build/pkgs/notebook/checksums.ini @@ -1,4 +1,4 @@ tarball=notebook-VERSION.tar.gz -sha1=ebf8ac32b9ca6c981b8936f987d19a5689d0b298 -md5=61a3f3c8d97fe9ce8affd359733717e9 -cksum=2566272680 +sha1=5ef18cf1731383860efd944526454e5e9653b3db +md5=ea79ad977a3ab25ef5f506065017e1ed +cksum=2023952192 diff --git a/build/pkgs/notebook/dependencies b/build/pkgs/notebook/dependencies index 1f206344809..97c7dede39f 100644 --- a/build/pkgs/notebook/dependencies +++ b/build/pkgs/notebook/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | pip ipython jupyter_client ipykernel nbconvert nbformat jinja2 tornado terminado +$(PYTHON) | pip ipython jupyter_client ipykernel nbconvert nbformat jinja2 tornado terminado send2trash ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/notebook/jupyter_notebook_config.py b/build/pkgs/notebook/jupyter_notebook_config.py index 1b0566a32ac..1ea31ce125f 100644 --- a/build/pkgs/notebook/jupyter_notebook_config.py +++ b/build/pkgs/notebook/jupyter_notebook_config.py @@ -11,3 +11,8 @@ # * https://github.com/oreillymedia/thebe/issues/93 c.NotebookApp.disable_check_xsrf = True + +# send2trash sometimes doesn't work, so disable that for now +# See https://github.com/jupyter/notebook/issues/3249 + +c.FileContentsManager.delete_to_trash = False diff --git a/build/pkgs/notebook/package-version.txt b/build/pkgs/notebook/package-version.txt index ce7f2b425b5..c7cb1311a64 100644 --- a/build/pkgs/notebook/package-version.txt +++ b/build/pkgs/notebook/package-version.txt @@ -1 +1 @@ -5.2.2 +5.3.1 diff --git a/build/pkgs/pari_jupyter/SPKG.txt b/build/pkgs/pari_jupyter/SPKG.txt index 681cdc57f23..3a6ad00273c 100644 --- a/build/pkgs/pari_jupyter/SPKG.txt +++ b/build/pkgs/pari_jupyter/SPKG.txt @@ -11,12 +11,12 @@ GPL version 3 or later == Upstream Contact == * https://github.com/jdemeyer/pari_jupyter -* Jeroen Demeyer +* Jeroen Demeyer == Dependencies == +* Python (tested with version 2.7.14 and 3.6.1) * Jupyter 4 -* Python (tested with 2.7.9) -* Cython (git master) -* PARI (git master) -* GMP or MPIR (any version which works with PARI) +* PARI version 2.8.0 or later +* Readline (any version which works with PARI) +* Optional: Cython version 0.25 or later diff --git a/build/pkgs/pari_jupyter/checksums.ini b/build/pkgs/pari_jupyter/checksums.ini index 8c4503ffb22..0bcc161a9b1 100644 --- a/build/pkgs/pari_jupyter/checksums.ini +++ b/build/pkgs/pari_jupyter/checksums.ini @@ -1,4 +1,4 @@ -tarball=pari_jupyter-VERSION.tar.bz2 -sha1=285acc6650ad177b092605938582e16d67e910bb -md5=ab0dc1d09303d33e861088155b82c965 -cksum=1154883481 +tarball=pari_jupyter-VERSION.tar.gz +sha1=6eac8e4466e4753fd07a38d16538222bec9b0a53 +md5=4d6e4b12afdb26c53e38b3b7aadfa18f +cksum=109015385 diff --git a/build/pkgs/pari_jupyter/dependencies b/build/pkgs/pari_jupyter/dependencies index 516d7089387..9e6b05089de 100644 --- a/build/pkgs/pari_jupyter/dependencies +++ b/build/pkgs/pari_jupyter/dependencies @@ -1 +1 @@ -$(PYTHON) pari jupyter_core | pip cython +$(PYTHON) pari | pip cython notebook jupyter_core diff --git a/build/pkgs/pari_jupyter/package-version.txt b/build/pkgs/pari_jupyter/package-version.txt index 23aa8390630..1892b926767 100644 --- a/build/pkgs/pari_jupyter/package-version.txt +++ b/build/pkgs/pari_jupyter/package-version.txt @@ -1 +1 @@ -1.2.2 +1.3.2 diff --git a/build/pkgs/patch/spkg-install b/build/pkgs/patch/spkg-install index f5d5a6e92da..d9de2282753 100644 --- a/build/pkgs/patch/spkg-install +++ b/build/pkgs/patch/spkg-install @@ -31,12 +31,5 @@ sdh_make sdh_make_install if [ "$UNAME" = "CYGWIN" ] ; then - cp ../patch.exe.manifest "$SAGE_LOCAL/bin/" -fi - -# Sanity check that we have the correct version of patch -# in our PATH. -if ! patch --version | grep >/dev/null 'patch 2\.7\.5'; then - echo >&2 "Cannot find the patch program we just installed" - exit 1 + cp ../patch.exe.manifest "$SAGE_DESTDIR$SAGE_LOCAL/bin/" fi diff --git a/build/pkgs/pynac/checksums.ini b/build/pkgs/pynac/checksums.ini index e35983b473e..0b2fe41225c 100644 --- a/build/pkgs/pynac/checksums.ini +++ b/build/pkgs/pynac/checksums.ini @@ -1,4 +1,4 @@ tarball=pynac-VERSION.tar.bz2 -sha1=33e2990a1f3a90ced00c2d87709a851682892e7f -md5=5faf705c049ca4cf09f1de436363c3a3 -cksum=3009897742 +sha1=ec322d219a9c02b95a29789ca221b28c6cca7a14 +md5=10f21726733209ae6f641b5736c4c9fb +cksum=2341458065 diff --git a/build/pkgs/pynac/package-version.txt b/build/pkgs/pynac/package-version.txt index a597e4f317c..def4250351c 100644 --- a/build/pkgs/pynac/package-version.txt +++ b/build/pkgs/pynac/package-version.txt @@ -1 +1 @@ -0.7.14 +0.7.15 diff --git a/build/pkgs/readline/spkg-install b/build/pkgs/readline/spkg-install index b8c2663871e..e17b66fdcff 100644 --- a/build/pkgs/readline/spkg-install +++ b/build/pkgs/readline/spkg-install @@ -69,10 +69,10 @@ esac # Make sure that the install worked, despite whatever the # exit code of 'make' or 'make install' was: -if [[ -f "$SAGE_LOCAL/lib/$DYLIB_NAME" ]]; then +if [[ -f "$SAGE_DESTDIR$SAGE_LOCAL/lib/$DYLIB_NAME" ]]; then echo "Fixing permissions of libraries..." - chmod 755 "$SAGE_LOCAL"/lib/libreadline.* - chmod 755 "$SAGE_LOCAL"/lib/libhistory.* + chmod 755 "$SAGE_DESTDIR$SAGE_LOCAL"/lib/libreadline.* + chmod 755 "$SAGE_DESTDIR$SAGE_LOCAL"/lib/libhistory.* else # One or both of the readline libraries are missing, i.e. # haven't been installed. diff --git a/build/pkgs/send2trash/SPKG.txt b/build/pkgs/send2trash/SPKG.txt new file mode 100644 index 00000000000..d829cf1573b --- /dev/null +++ b/build/pkgs/send2trash/SPKG.txt @@ -0,0 +1,17 @@ += Send2Trash = + +== Description == + +Send file to trash natively under Mac OS X, Windows and Linux. + +Send2Trash is a small package that sends files to the Trash (or Recycle +Bin) natively and on all platforms. On OS X, it uses native +FSMoveObjectToTrashSync Cocoa calls, on Windows, it uses native (and +ugly) SHFileOperation win32 calls. On other platforms, if PyGObject and +GIO are available, it will use this. Otherwise, it will fallback to its +own implementation of the trash specifications from freedesktop.org. + +ctypes is used to access native libraries, so no compilation is +necessary. + +Send2Trash supports Python 2.7 and up (Python 3 is supported). diff --git a/build/pkgs/send2trash/checksums.ini b/build/pkgs/send2trash/checksums.ini new file mode 100644 index 00000000000..f8312979034 --- /dev/null +++ b/build/pkgs/send2trash/checksums.ini @@ -0,0 +1,4 @@ +tarball=Send2Trash-VERSION.tar.gz +sha1=34a01a1b0c25180e8f04c476f2a7cdaaf46e52ae +md5=3aa42844d608370c9e19d108fdf3782d +cksum=995505276 diff --git a/build/pkgs/send2trash/dependencies b/build/pkgs/send2trash/dependencies new file mode 100644 index 00000000000..d5dab729e18 --- /dev/null +++ b/build/pkgs/send2trash/dependencies @@ -0,0 +1,5 @@ +$(PYTHON) | pip + +---------- +All lines of this file are ignored except the first. +It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/send2trash/package-version.txt b/build/pkgs/send2trash/package-version.txt new file mode 100644 index 00000000000..9df886c42a1 --- /dev/null +++ b/build/pkgs/send2trash/package-version.txt @@ -0,0 +1 @@ +1.4.2 diff --git a/build/pkgs/send2trash/spkg-install b/build/pkgs/send2trash/spkg-install new file mode 100644 index 00000000000..deba1bb42bb --- /dev/null +++ b/build/pkgs/send2trash/spkg-install @@ -0,0 +1 @@ +cd src && sdh_pip_install . diff --git a/build/pkgs/send2trash/type b/build/pkgs/send2trash/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/send2trash/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/singular_jupyter/checksums.ini b/build/pkgs/singular_jupyter/checksums.ini index 9610c182c79..7def85d733f 100644 --- a/build/pkgs/singular_jupyter/checksums.ini +++ b/build/pkgs/singular_jupyter/checksums.ini @@ -1,4 +1,4 @@ tarball=jupyter_kernel_singular-VERSION.tar.gz -sha1=381319a1a49c4565078392bcd65b306f2dc22707 -md5=915e2e89b759297a8aebcfe8ca400cbb -cksum=3440281746 +sha1=e10d0894cac9ee111e34c6d6d6e409b26edf108f +md5=c2acfe07c1094200dac521d2e8dcb2a9 +cksum=970360836 diff --git a/build/pkgs/singular_jupyter/package-version.txt b/build/pkgs/singular_jupyter/package-version.txt index 2003b639c40..c81aa44afbf 100644 --- a/build/pkgs/singular_jupyter/package-version.txt +++ b/build/pkgs/singular_jupyter/package-version.txt @@ -1 +1 @@ -0.9.2 +0.9.7 diff --git a/build/pkgs/texlive/spkg-install b/build/pkgs/texlive/spkg-install old mode 100644 new mode 100755 diff --git a/configure.ac b/configure.ac index a6900c297ad..fbe94eb4ff7 100644 --- a/configure.ac +++ b/configure.ac @@ -70,7 +70,7 @@ AM_INIT_AUTOMAKE([1.9.6 foreign]) # Allow "configure --disable-maintainer-mode" to disable timestamp checking AM_MAINTAINER_MODE([enable]) -dnl Make sure the path to our own m4 macros is always properly set +dnl Make sure the path to our own m4 macros is always properly set dnl and doesn't depend on how autoconf is called. AC_CONFIG_MACRO_DIR([m4]) @@ -212,7 +212,7 @@ then AC_MSG_NOTICE([On some systems it can be found in /usr/ccs/bin]) AC_MSG_NOTICE([See also http://www.gnu.org/software/m4/]) AC_MSG_ERROR([Exiting, as the macro processor 'm4' can not be found.]) -fi +fi AC_CHECK_PROG(found_ranlib, ranlib, yes, no) if test x$found_ranlib != xyes @@ -355,6 +355,8 @@ AC_DEFUN([SAGE_MUST_INSTALL_GCC], [ # By default, do not install GCC need_to_install_gcc=no +# or GFORTRAN +need_to_install_gfortran=no if test -f "$SAGE_LOCAL/bin/gcc"; then # Special value for SAGE_INSTALL_GCC if GCC is already installed @@ -381,6 +383,13 @@ AC_SUBST(CC) AC_SUBST(CXX) AC_SUBST(FC) +# Figuring out if we are using clang instead of gcc. +AX_COMPILER_VENDOR() +IS_REALLY_GCC=no +if test "x$ax_cv_c_compiler_vendor" = xgnu ; then + IS_REALLY_GCC=yes +fi + # On darwin, also set the objective C/C++ compilers # Checking on all platforms doesn't hurt and stops # configure from sending an error when run on non-darwin. diff --git a/m4/ax_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4 new file mode 100644 index 00000000000..0256bbaf82c --- /dev/null +++ b/m4/ax_compiler_vendor.m4 @@ -0,0 +1,88 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_COMPILER_VENDOR +# +# DESCRIPTION +# +# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, +# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, +# watcom, etc. The vendor is returned in the cache variable +# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2008 Matteo Frigo +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 16 + +AC_DEFUN([AX_COMPILER_VENDOR], +[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, + dnl Please add if possible support to ax_compiler_version.m4 + [# note: don't check for gcc first since some other compilers define __GNUC__ + vendors="intel: __ICC,__ECC,__INTEL_COMPILER + ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ + pathscale: __PATHCC__,__PATHSCALE__ + clang: __clang__ + cray: _CRAYC + fujitsu: __FUJITSU + gnu: __GNUC__ + sun: __SUNPRO_C,__SUNPRO_CC + hp: __HP_cc,__HP_aCC + dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER + borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ + comeau: __COMO__ + kai: __KCC + lcc: __LCC__ + sgi: __sgi,sgi + microsoft: _MSC_VER + metrowerks: __MWERKS__ + watcom: __WATCOMC__ + portland: __PGI + tcc: __TINYC__ + unknown: UNKNOWN" + for ventest in $vendors; do + case $ventest in + *:) vendor=$ventest; continue ;; + *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; + esac + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ + #if !($vencpp) + thisisanerror; + #endif + ])], [break]) + done + ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` + ]) +]) + diff --git a/src/bin/sage b/src/bin/sage index d9fd2897e50..4cfd8c076d6 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -324,40 +324,44 @@ if [ "$1" = '-i' ]; then fi set -e - cd "$SAGE_ROOT" - # First of all, make sure that the toolchain is up-to-date - # (which is a dependency of every package) - ./sage --location - $MAKE all-toolchain - echo - + # Parse options + PACKAGES="" # Packages to install INSTALL_OPTIONS="" # Options to sage-spkg - for PKG in "$@" - do - case "$PKG" in + for OPT in "$@"; do + case "$OPT" in -info|--info) - echo >&2 "Error: 'sage -i $PKG ' is no longer supported, use 'sage --info ' instead." + echo >&2 "Error: 'sage -i $OPT ' is no longer supported, use 'sage --info ' instead." exit 2;; -f) FORCE_INSTALL=yes;; - -*) INSTALL_OPTIONS="$INSTALL_OPTIONS $PKG";; - *) - # First check that $PKG is actually a Makefile target - if ! grep "^$PKG: " build/make/Makefile >/dev/null; then - echo >&2 "Error: package '$PKG' not found" - echo >&2 "Assuming it is an old-style package... (this is deprecated: use -p instead of -i to install old-style packages)" - echo >&2 - sleep 5 - ./sage -p $INSTALL_OPTIONS "$PKG" - else - if [ x$FORCE_INSTALL = xyes ]; then - $MAKE "$PKG-clean" - fi - $MAKE SAGE_SPKG="sage-spkg $INSTALL_OPTIONS" "$PKG" - fi;; + -*) INSTALL_OPTIONS="$INSTALL_OPTIONS $OPT";; + *) PACKAGES="$PACKAGES $OPT";; esac done + + # First, uninstall the packages if -f was given + if [ "$FORCE_INSTALL" = yes ]; then + for PKG in $PACKAGES; do + $MAKE "$PKG-clean" || true # Ignore errors + done + fi + + # Make sure that the toolchain is up-to-date + # (which is a dependency of every package) + $MAKE all-toolchain + + # Now install the packages + for PKG in $PACKAGES; do + echo + # First check that $PKG is actually a Makefile target + if ! grep "^$PKG: " build/make/Makefile >/dev/null; then + echo >&2 "Error: package '$PKG' not found" + echo >&2 "Note: if it is an old-style package, use -p instead of -i to install it" + exit 1 + fi + $MAKE SAGE_SPKG="sage-spkg $INSTALL_OPTIONS" "$PKG" + done exit 0 fi diff --git a/src/bin/sage-banner b/src/bin/sage-banner index 5116d986fde..d2e95e4428d 100644 --- a/src/bin/sage-banner +++ b/src/bin/sage-banner @@ -1,5 +1,5 @@ ┌────────────────────────────────────────────────────────────────────┐ -│ SageMath version 8.2.beta3, Release Date: 2018-01-17 │ +│ SageMath version 8.2.beta4, Release Date: 2018-01-27 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ diff --git a/src/bin/sage-dist-helpers b/src/bin/sage-dist-helpers index d5b966a422a..63a4b5ebcfe 100644 --- a/src/bin/sage-dist-helpers +++ b/src/bin/sage-dist-helpers @@ -45,8 +45,9 @@ # # - sdh_make_install [...] # -# Runs `$SAGE_SUDO $MAKE install`. Additional arguments to `make` may be -# given as arguments. +# Runs `$SAGE_SUDO $MAKE install` with DESTDIR correctly set to a temporary +# install directory, for staged installations. Additional arguments to +# `make` may be given as arguments. # # - sdh_pip_install [...] # @@ -137,7 +138,7 @@ sdh_make() { sdh_make_install() { echo "Installing $PKG_NAME" - $SAGE_SUDO ${MAKE:-make} install "$@" || \ + $SAGE_SUDO ${MAKE:-make} install DESTDIR="$SAGE_DESTDIR" "$@" || \ sdh_die "Error installing $PKG_NAME" } diff --git a/src/bin/sage-eval b/src/bin/sage-eval index 3011bff7b6e..781c36150f8 100755 --- a/src/bin/sage-eval +++ b/src/bin/sage-eval @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 import sys from sage.all import * diff --git a/src/bin/sage-fixdoctests b/src/bin/sage-fixdoctests index 92d6cebd748..0debd28d544 100755 --- a/src/bin/sage-fixdoctests +++ b/src/bin/sage-fixdoctests @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 """ Given the output of doctest and a file, adjust the doctests so they won't fail. diff --git a/src/bin/sage-ipython b/src/bin/sage-ipython index d83ba020be8..d2ca96b1a87 100755 --- a/src/bin/sage-ipython +++ b/src/bin/sage-ipython @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 # -*- coding: utf-8 -*- """ Sage IPython startup script. diff --git a/src/bin/sage-list-packages b/src/bin/sage-list-packages index 1988cb86aec..bf35f8d8df9 100755 --- a/src/bin/sage-list-packages +++ b/src/bin/sage-list-packages @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 r""" Script to list the Sage packages diff --git a/src/bin/sage-preparse b/src/bin/sage-preparse index 58a26eb7d47..2d87e73dca7 100755 --- a/src/bin/sage-preparse +++ b/src/bin/sage-preparse @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 """ Preparse .sage files and save the result to .sage.py files. diff --git a/src/bin/sage-run-cython b/src/bin/sage-run-cython index feb91fff1b3..c6dbe00e9f5 100755 --- a/src/bin/sage-run-cython +++ b/src/bin/sage-run-cython @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 import sys from sage.repl.load import load_cython diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index 405c3f637d4..754081f3015 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -1,6 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 -import optparse, os, sys +import optparse +import os +import sys # Note: the DOT_SAGE and SAGE_STARTUP_FILE environment variables have already been set by sage-env DOT_SAGE = os.environ['DOT_SAGE'] diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index b95e9d65275..270e83c3a8a 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,4 +1,4 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='8.2.beta3' -SAGE_RELEASE_DATE='2018-01-17' +SAGE_VERSION='8.2.beta4' +SAGE_RELEASE_DATE='2018-01-27' diff --git a/src/doc/de/tutorial/afterword.rst b/src/doc/de/tutorial/afterword.rst index 271ac92d543..cc38bcdef05 100644 --- a/src/doc/de/tutorial/afterword.rst +++ b/src/doc/de/tutorial/afterword.rst @@ -121,7 +121,7 @@ sein, also verhält sich Sage an manchen Stellen anders als Python. Rational Field sage: 2//3 0 - sage: int(2)/int(3) # optional - python2 + sage: int(2)/int(3) # py2 0 - **Große ganze Zahlen:** Python besitzt von Hause aus Unterstützung diff --git a/src/doc/de/tutorial/tour_help.rst b/src/doc/de/tutorial/tour_help.rst index 5e0884ad5e5..f15eb9e8ee3 100644 --- a/src/doc/de/tutorial/tour_help.rst +++ b/src/doc/de/tutorial/tour_help.rst @@ -262,9 +262,9 @@ verwendet haben, eine Liste (python 2): :: - sage: range(2,10) # optional - python2 + sage: range(2,10) # py2 [2, 3, 4, 5, 6, 7, 8, 9] - sage: list(range(2,10)) # optional - python3 + sage: list(range(2,10)) # py3 [2, 3, 4, 5, 6, 7, 8, 9] Hier ist eine etwas kompliziertere Liste: diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index b6154adec6e..c72582a1054 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1221,6 +1221,10 @@ REFERENCES: **I** +.. [IK2010] Kenji Iohara and Yoshiyuki Koga. + *Representation Theory of the Virasoro Algebra*. + Springer, (2010). + .. [ILS2012] Giuseppe F. Italiano, Luigi Laura, and Federico Santaroni. *Finding strong bridges and strong articulation points in linear time*. Theoretical Computer @@ -1657,6 +1661,10 @@ REFERENCES: FSE’93, Volume 809 of LNCS, pages 1-17. Springer, Heidelberg, December 1994. +.. [Mat1992] \O. Mathieu. *Classification of Harish-Chandra + modules over the Virasoro Lie algebra*. + Invent. Math. **107(2)** (1992), pp. 225-234. + .. [Mat2002] Jiří Matousek, "Lectures on Discrete Geometry", Springer, 2002 @@ -2060,14 +2068,15 @@ REFERENCES: Reduction*. Advances in Cryptology - EUROCRYPT '95. LNCS Volume 921, 1995, pp 1-12. -.. [Shi1971] Shimura, Goro. *Introduction to the arithmetic theory of - automorphic functions*. Princeton University Press, 1971. - .. [Shim2016] Shimada, Ichiro, Connected components of the moduli of elliptic K3 surfaces, https://arxiv.org/abs/1610.04706. -.. [Shr2004] Shreve, S. Stochastic Calculus for Finance II: - Continuous-Time Models. New York: Springer, 2004 +.. [Shi1971] Goro Shimura, *Introduction to the arithmetic theory of + automorphic functions*. Publications of the Mathematical + Society of Japan and Princeton University Press, 1971. + +.. [Shr2004] \S. Shreve, *Stochastic Calculus for Finance II: + Continuous-Time Models*. New York: Springer, 2004 .. [SIHMAS2011] \K. Shibutani, T. Isobe, H. Hiwatari, A. Mitsuda, T. Akishita, and T. Shirai, *Piccolo: An ultra-lightweight block-cipher*; in diff --git a/src/doc/en/thematic_tutorials/algebraic_combinatorics/rsk.rst b/src/doc/en/thematic_tutorials/algebraic_combinatorics/rsk.rst index cbc10938634..cbbf6a1d89a 100644 --- a/src/doc/en/thematic_tutorials/algebraic_combinatorics/rsk.rst +++ b/src/doc/en/thematic_tutorials/algebraic_combinatorics/rsk.rst @@ -88,7 +88,7 @@ We can also check this against the hook length formula (Theorem 8.1):: sage: def hook_length_formula(p): ....: n = p.size() - ....: return factorial(n) / prod(p.hook_length(*c) for c in p.cells()) + ....: return factorial(n) // prod(p.hook_length(*c) for c in p.cells()) sage: for la in u.support(): ....: assert u[la] == hook_length_formula(la) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index cf7b312707f..6f54d8b55a1 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -875,7 +875,8 @@ The four axioms requested for coercions rational field is a homomorphism of euclidean domains:: sage: QQ.coerce_map_from(ZZ).category_for() - Join of Category of euclidean domains and Category of metric spaces + Join of Category of euclidean domains and Category of infinite sets + and Category of metric spaces .. end of output diff --git a/src/doc/en/tutorial/programming.rst b/src/doc/en/tutorial/programming.rst index a2e8147f695..febe20200f1 100644 --- a/src/doc/en/tutorial/programming.rst +++ b/src/doc/en/tutorial/programming.rst @@ -672,7 +672,7 @@ the Python int ``1`` is unique, but the Sage Integer ``1`` is not: sage: 1 is 2/2 False - sage: int(1) is int(2)/int(2) # optional - python2 + sage: int(1) is int(2)/int(2) # py2 True sage: 1 is 1 False diff --git a/src/doc/en/tutorial/tour_help.rst b/src/doc/en/tutorial/tour_help.rst index b290d3e949d..800777882dc 100644 --- a/src/doc/en/tutorial/tour_help.rst +++ b/src/doc/en/tutorial/tour_help.rst @@ -259,9 +259,9 @@ the ``range`` command that we used creates a list (in python 2): :: - sage: range(2,10) # optional - python2 + sage: range(2,10) # py2 [2, 3, 4, 5, 6, 7, 8, 9] - sage: list(range(2,10)) # optional - python3 + sage: list(range(2,10)) # py3 [2, 3, 4, 5, 6, 7, 8, 9] Here is a more complicated list: diff --git a/src/doc/es/tutorial/tour_help.rst b/src/doc/es/tutorial/tour_help.rst index c759d1b0fb6..efbb2880940 100644 --- a/src/doc/es/tutorial/tour_help.rst +++ b/src/doc/es/tutorial/tour_help.rst @@ -258,9 +258,9 @@ Por ejemplo, el comando ``range`` que hemos usado crea una lista (python 2): :: - sage: range(2,10) # optional - python2 + sage: range(2,10) # py2 [2, 3, 4, 5, 6, 7, 8, 9] - sage: list(range(2,10)) # optional - python3 + sage: list(range(2,10)) # py3 [2, 3, 4, 5, 6, 7, 8, 9] He aquí una lista más complicada: diff --git a/src/doc/fr/tutorial/afterword.rst b/src/doc/fr/tutorial/afterword.rst index 4355559abf2..1a470f08cfe 100644 --- a/src/doc/fr/tutorial/afterword.rst +++ b/src/doc/fr/tutorial/afterword.rst @@ -132,7 +132,7 @@ Aussi, Sage se comporte différemment de Python à plusieurs égards. Rational Field sage: 2//3 0 - sage: int(2)/int(3) # optional - python2 + sage: int(2)/int(3) # py2 0 - **Entiers longs :** Python possède nativement un support pour les entiers de diff --git a/src/doc/fr/tutorial/tour_help.rst b/src/doc/fr/tutorial/tour_help.rst index 9e853c11659..3ad0435ec8c 100644 --- a/src/doc/fr/tutorial/tour_help.rst +++ b/src/doc/fr/tutorial/tour_help.rst @@ -264,9 +264,9 @@ liste (en python 2): :: - sage: range(2,10) # optional - python2 + sage: range(2,10) # py2 [2, 3, 4, 5, 6, 7, 8, 9] - sage: list(range(2,10)) # optional - python3 + sage: list(range(2,10)) # py3 [2, 3, 4, 5, 6, 7, 8, 9] Voici un exemple plus compliqué de liste : diff --git a/src/doc/ja/tutorial/afterword.rst b/src/doc/ja/tutorial/afterword.rst index 47371fecdda..68403ea6216 100644 --- a/src/doc/ja/tutorial/afterword.rst +++ b/src/doc/ja/tutorial/afterword.rst @@ -96,7 +96,7 @@ Pythonの数学機能には混乱を招きがちな面があり,SageにはPyth Rational Field sage: 2//3 0 - sage: int(2)/int(3) # optional - python2 + sage: int(2)/int(3) # py2 0 - **長整数:** Python本体は,C言語由来のint型だけではなく任意精度整数をサポートしている. diff --git a/src/doc/ja/tutorial/programming.rst b/src/doc/ja/tutorial/programming.rst index 082853703c3..f390e5744d9 100644 --- a/src/doc/ja/tutorial/programming.rst +++ b/src/doc/ja/tutorial/programming.rst @@ -647,7 +647,7 @@ Sageにおける異種オブジェクト間の比較演算では,まず対象 sage: 1 is 2/2 False - sage: int(1) is int(2)/int(2) # optional - python2 + sage: int(1) is int(2)/int(2) # py2 True sage: 1 is 1 False diff --git a/src/doc/ja/tutorial/tour_help.rst b/src/doc/ja/tutorial/tour_help.rst index a319a189e06..7c3994930e5 100644 --- a/src/doc/ja/tutorial/tour_help.rst +++ b/src/doc/ja/tutorial/tour_help.rst @@ -254,9 +254,9 @@ Sageにおける最も基本的なデータ構造はリストで,名前の示 :: - sage: range(2,10) # optional - python2 + sage: range(2,10) # py2 [2, 3, 4, 5, 6, 7, 8, 9] - sage: list(range(2,10)) # optional - python3 + sage: list(range(2,10)) # py3 [2, 3, 4, 5, 6, 7, 8, 9] もう少し複雑なリストの例として: diff --git a/src/doc/pt/tutorial/afterword.rst b/src/doc/pt/tutorial/afterword.rst index a218562c045..5318a424766 100644 --- a/src/doc/pt/tutorial/afterword.rst +++ b/src/doc/pt/tutorial/afterword.rst @@ -113,7 +113,7 @@ se comporta diferentemente do Python em diversas situações. Rational Field sage: 2//3 0 - sage: int(2)/int(3) # optional - python2 + sage: int(2)/int(3) # py2 0 - **Inteiros longos:** O Python possui suporte nativo para inteiros diff --git a/src/doc/pt/tutorial/programming.rst b/src/doc/pt/tutorial/programming.rst index 71ef68e996b..82ba2c538f8 100644 --- a/src/doc/pt/tutorial/programming.rst +++ b/src/doc/pt/tutorial/programming.rst @@ -693,7 +693,7 @@ o int ``1`` do Python é único, mas o Inteiro ``1`` do Sage não é. sage: 1 is 2/2 False - sage: int(1) is int(2)/int(2) # optional - python2 + sage: int(1) is int(2)/int(2) # py2 True sage: 1 is 1 False diff --git a/src/doc/pt/tutorial/tour_help.rst b/src/doc/pt/tutorial/tour_help.rst index e31190a4e8c..7b4f5243ddb 100644 --- a/src/doc/pt/tutorial/tour_help.rst +++ b/src/doc/pt/tutorial/tour_help.rst @@ -260,9 +260,9 @@ exemplo, o comando ``range`` que usamos acima cria uma lista: :: - sage: range(2,10) # optional - python2 + sage: range(2,10) # py2 [2, 3, 4, 5, 6, 7, 8, 9] - sage: list(range(2,10)) # optional - python3 + sage: list(range(2,10)) # py3 [2, 3, 4, 5, 6, 7, 8, 9] Abaixo segue uma lista mais complicada: diff --git a/src/doc/ru/tutorial/afterword.rst b/src/doc/ru/tutorial/afterword.rst index 6b59856ea52..6465ec04a8f 100644 --- a/src/doc/ru/tutorial/afterword.rst +++ b/src/doc/ru/tutorial/afterword.rst @@ -106,7 +106,7 @@ Sage ведет себя немного другим образом. Rational Field sage: 2//3 0 - sage: int(2)/int(3) # optional - python2 + sage: int(2)/int(3) # py2 0 - **Большие целые числа:** Python имеет встроенную поддержку целых чисел diff --git a/src/doc/ru/tutorial/tour_help.rst b/src/doc/ru/tutorial/tour_help.rst index 5650c9d70f9..57d4da60df4 100644 --- a/src/doc/ru/tutorial/tour_help.rst +++ b/src/doc/ru/tutorial/tour_help.rst @@ -246,9 +246,9 @@ tanh, taylor``. Данная функция является хорошим сп :: - sage: range(2,10) # optional - python2 + sage: range(2,10) # py2 [2, 3, 4, 5, 6, 7, 8, 9] - sage: list(range(2,10)) # optional - python3 + sage: list(range(2,10)) # py3 [2, 3, 4, 5, 6, 7, 8, 9] Далее показан пример более сложного списка: diff --git a/src/module_list.py b/src/module_list.py index a066fca2391..911d598ecfd 100644 --- a/src/module_list.py +++ b/src/module_list.py @@ -1154,8 +1154,7 @@ def uname_specific(name, value, alternative): sources = ['sage/rings/morphism.pyx']), Extension('sage.rings.complex_mpc', - sources = ['sage/rings/complex_mpc.pyx'], - libraries = ['mpc']), + sources = ['sage/rings/complex_mpc.pyx']), Extension('sage.rings.noncommutative_ideals', sources = ['sage/rings/noncommutative_ideals.pyx']), diff --git a/src/sage/algebras/lie_algebras/examples.py b/src/sage/algebras/lie_algebras/examples.py index 88a364c0d2a..9b98295d1cf 100644 --- a/src/sage/algebras/lie_algebras/examples.py +++ b/src/sage/algebras/lie_algebras/examples.py @@ -274,6 +274,8 @@ def regular_vector_fields(R): r""" Return the Lie algebra of regular vector fields on `\CC^{\times}`. + This is also known as the Witt (Lie) algebra. + .. SEEALSO:: :class:`~sage.algebras.lie_algebras.virasoro.LieAlgebraRegularVectorFields` @@ -286,10 +288,17 @@ def regular_vector_fields(R): from sage.algebras.lie_algebras.virasoro import LieAlgebraRegularVectorFields return LieAlgebraRegularVectorFields(R) +witt = regular_vector_fields + def pwitt(R, p): r""" Return the `p`-Witt Lie algebra over `R`. + INPUT: + + - ``R`` -- the base ring + - ``p`` -- a positive integer that is `0` in ``R`` + EXAMPLES:: sage: lie_algebras.pwitt(GF(5), 5) diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index 8110996d00f..46758624192 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -45,6 +45,14 @@ cdef class LieAlgebraElement(IndexedFreeModuleElement): sage: y*x x*y - z + Check that actions work:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: d = L.basis() + sage: M = L.chargeless_representation(1/2, 3/4) + sage: d[-5] * M.basis()[10] + -47/4*v[5] + TESTS:: sage: L. = LieAlgebra(QQ, {('x','y'): {'z':1}}) @@ -96,7 +104,7 @@ cdef class LieAlgebraElement(IndexedFreeModuleElement): sage: x * y b2*b3 sage: y * x - b2*b3 - b0 + b2*b3 + b0 sage: L = lie_algebras.regular_vector_fields(QQ) sage: L.an_element() diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py index 51ede7639c2..0b2014a97fe 100644 --- a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -92,9 +92,9 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): sage: G[2] * G[3] PBW[2]*PBW[3] sage: G[3] * G[2] - PBW[2]*PBW[3] - PBW[5] + PBW[2]*PBW[3] + PBW[5] sage: G[-2] * G[3] * G[2] - PBW[-2]*PBW[2]*PBW[3] - PBW[-2]*PBW[5] + PBW[-2]*PBW[2]*PBW[3] + PBW[-2]*PBW[5] """ @staticmethod def __classcall_private__(cls, g, basis_key=None, prefix='PBW', **kwds): diff --git a/src/sage/algebras/lie_algebras/virasoro.py b/src/sage/algebras/lie_algebras/virasoro.py index d217d51471a..6a2b0814150 100644 --- a/src/sage/algebras/lie_algebras/virasoro.py +++ b/src/sage/algebras/lie_algebras/virasoro.py @@ -26,6 +26,7 @@ from sage.algebras.lie_algebras.lie_algebra_element import LieAlgebraElement from sage.algebras.lie_algebras.lie_algebra import (InfinitelyGeneratedLieAlgebra, FinitelyGeneratedLieAlgebra) +from sage.combinat.free_module import CombinatorialFreeModule class LieAlgebraRegularVectorFields(InfinitelyGeneratedLieAlgebra, IndexedGenerators): r""" @@ -36,10 +37,15 @@ class LieAlgebraRegularVectorFields(InfinitelyGeneratedLieAlgebra, IndexedGenera .. MATH:: - [d_i, d_j] = (j - i) d_{i+j}. + [d_i, d_j] = (i - j) d_{i+j}. This is also known as the Witt (Lie) algebra. + .. NOTE:: + + This differs from some conventions (e.g., [Ka1990]_), where + we have `d'_i \mapsto -d_i`. + REFERENCES: - :wikipedia:`Witt_algebra` @@ -101,13 +107,13 @@ def bracket_on_basis(self, i, j): sage: L = lie_algebras.regular_vector_fields(QQ) sage: L.bracket_on_basis(2, -2) - -4*d[0] + 4*d[0] sage: L.bracket_on_basis(2, 4) - 2*d[6] + -2*d[6] sage: L.bracket_on_basis(4, 4) 0 """ - return self.term(i + j, j - i) + return self.term(i + j, i - j) def _an_element_(self): """ @@ -148,7 +154,7 @@ class WittLieAlgebra_charp(FinitelyGeneratedLieAlgebra, IndexedGenerators): .. MATH:: - [d_i, d_j] = (j - i) d_{i+j}, + [d_i, d_j] = (i - j) d_{i+j}, where the `i+j` on the right hand side is identified with its remainder modulo `p`. @@ -170,6 +176,8 @@ def __init__(self, R, p): sage: TestSuite(L).run() # not tested -- universal envelope doesn't work sage: L._test_jacobi_identity() """ + if R(p) != 0: + raise ValueError("{} is not 0 in {}".format(p, R)) cat = LieAlgebras(R).FiniteDimensional().WithBasis() FinitelyGeneratedLieAlgebra.__init__(self, R, index_set=range(p), category=cat) IndexedGenerators.__init__(self, range(p), prefix='d', bracket='[') @@ -217,15 +225,15 @@ def bracket_on_basis(self, i, j): sage: L = lie_algebras.pwitt(Zmod(5), 5) sage: L.bracket_on_basis(2, 3) - d[0] - sage: L.bracket_on_basis(3, 2) 4*d[0] + sage: L.bracket_on_basis(3, 2) + d[0] sage: L.bracket_on_basis(2, 2) 0 sage: L.bracket_on_basis(1, 3) - 2*d[4] + 3*d[4] """ - return self.term((i + j) % self._p, j - i) + return self.term((i + j) % self._p, i - j) def _an_element_(self): """ @@ -283,7 +291,7 @@ class VirasoroAlgebra(InfinitelyGeneratedLieAlgebra, IndexedGenerators): .. MATH:: - [d_i, d_j] = (j - i) d_{i+j} + \frac{1}{12}(j^3 - j) \delta_{i,-j} c + [d_i, d_j] = (i - j) d_{i+j} + \frac{1}{12}(i^3 - i) \delta_{i,-j} c and @@ -437,14 +445,14 @@ def bracket_on_basis(self, i, j): sage: d.bracket_on_basis('c', 2) 0 sage: d.bracket_on_basis(2, -2) - -4*d[0] - 1/2*c + 4*d[0] + 1/2*c """ if i == 'c' or j == 'c': return self.zero() - ret = self._from_dict({i + j: j-i}) + ret = self._from_dict({i + j: i-j}) R = self.base_ring() if i == -j: - ret += R(j ** 3 - j) / R(12) * self.c() + ret += R(i ** 3 - i) / R(12) * self.c() return ret def _an_element_(self): @@ -473,6 +481,536 @@ def some_elements(self): d = self.monomial return [d(0), d(2), d(-2), d('c'), self.an_element()] + def chargeless_representation(self, a, b): + """ + Return the chargeless representation of ``self`` with + parameters ``a`` and ``b``. + + .. SEEALSO:: + + :class:`~sage.algebras.lie_algebras.virasoro.ChargelessRepresentation` + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: L.chargeless_representation(3, 2) + Chargeless representation (3, 2) of + The Virasoro algebra over Rational Field + """ + return ChargelessRepresentation(self, a, b) + + def verma_module(self, c, h): + """ + Return the Verma module with central charge ``c`` and + conformal (or highest) weight ``h``. + + .. SEEALSO:: + + :class:`~sage.algebras.lie_algebras.virasoro.VermaModule` + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: L.verma_module(3, 2) + Verma module with charge 3 and confromal weight 2 of + The Virasoro algebra over Rational Field + """ + return VermaModule(self, c, h) + class Element(LieAlgebraElement): pass +##################################################################### +## Representations + +class ChargelessRepresentation(CombinatorialFreeModule): + r""" + A chargeless representation of the Virasoro algebra. + + Let `L` be the Virasoro algebra over the field `F` of + characteristic `0`. For `\alpha, \beta \in R`, we denote `V_{a,b}` + as the `(a, b)`-*chargeless representation* of `L`, which is the + `F`-span of `\{v_k \mid k \in \ZZ\}` with `L` action + + .. MATH:: + + \begin{aligned} + d_n \cdot v_k & = (a n + b - k) v_{n+k}, + \\ c \cdot v_k & = 0, + \end{aligned} + + This comes from the action of `d_n = -t^{n+1} \frac{d}{dt}` on + `F[t, t^{-1}]` (recall that `L` is the central extension of the + :class:`algebra of derivations ` + of `F[t, t^{-1}]`), where + + .. MATH:: + + V_{a,b} = F[t, t^{-1}] t^{a-b} (dt)^{-a} + + and `v_k = t^{a-b+k} (dz)^{-a}`. + + The chargeless representations are either irreducible or + contains exactly two simple subquotients, one of which is the + trivial representation and the other is `F[t, t^{-1}] / F`. + The non-trivial simple subquotients are called the + *intermediate series*. + + The module `V_{a,b}` is irreducible if and only if + `a \neq 0, -1` or `b \notin \ZZ`. When `a = 0` and `b \in \ZZ`, + then there exists a subrepresentation isomorphic to the trivial + representation. If `a = -1` and `b \in \ZZ`, then there exists + a subrepresentation `V` such that `V_{a,b} / V` is isomorphic + to `K \frac{dt}{t}` and `V` is irreducible. + + In characteristic `p`, the non-trivial simple subquotient + is isomorphic to `F[t, t^{-1}] / F[t^p, t^{-p}]`. For + `p \neq 2,3`, then the action is given as above. + + EXAMPLES: + + We first construct the irreducible `V_{1/2, 3/4}` and do some + basic computations:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.chargeless_representation(1/2, 3/4) + sage: d = L.basis() + sage: v = M.basis() + sage: d[3] * v[2] + 1/4*v[5] + sage: d[3] * v[-1] + 13/4*v[2] + sage: (d[3] - d[-2]) * (v[-1] + 1/2*v[0] - v[4]) + -3/4*v[-3] + 1/8*v[-2] - v[2] + 9/8*v[3] + 7/4*v[7] + + We construct the reducible `V_{0,2}` and the trivial + subrepresentation given by the span of `v_2`. We verify + this for `\{d_i \mid -10 \leq i < 10\}`:: + + sage: M = L.chargeless_representation(0, 2) + sage: v = M.basis() + sage: all(d[i] * v[2] == M.zero() for i in range(-10, 10)) + True + + REFERENCES: + + - [Mat1992]_ + - [IK2010]_ + """ + def __init__(self, V, a, b): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.chargeless_representation(1/2, 3/4) + sage: TestSuite(M).run() + """ + self._a = a + self._b = b + self._V = V + if V.base_ring().characteristic() in [2,3]: + raise NotImplementedError("not implemented for characteristic 2,3") + CombinatorialFreeModule.__init__(self, V.base_ring(), ZZ, + prefix='v') + + def _repr_(self): + """ + Return a string representation of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: L.chargeless_representation(1/2, 3/4) + Chargeless representation (1/2, 3/4) of + The Virasoro algebra over Rational Field + """ + return "Chargeless representation ({}, {}) of {}".format( + self._a, self._b, self._V) + + def parameters(self): + """ + Return the parameters `(a, b)` of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.chargeless_representation(1/2, 3/4) + sage: M.parameters() + (1/2, 3/4) + """ + return (self._a, self._b) + + def virasoro_algebra(self): + """ + Return the Virasoro algebra ``self`` is a representation of. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.chargeless_representation(1/2, 3/4) + sage: M.virasoro_algebra() is L + True + """ + return self._V + + class Element(CombinatorialFreeModule.Element): + def _acted_upon_(self, scalar, self_on_left=False): + """ + Return the action of ``scalar`` on ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: d = L.basis() + sage: M = L.chargeless_representation(1/2, 3/4) + sage: x = d[-5] * M.an_element() + M.basis()[10]; x + -9/4*v[-6] - 7/4*v[-5] - 33/4*v[-4] + v[10] + sage: d[2] * x + -279/16*v[-4] - 189/16*v[-3] - 759/16*v[-2] - 33/4*v[12] + + sage: v = M.basis() + sage: all(d[i]*(d[j]*v[k]) - d[j]*(d[i]*v[k]) == d[i].bracket(d[j])*v[k] + ....: for i in range(-5, 5) for j in range(-5, 5) for k in range(-5, 5)) + True + """ + P = self.parent() + # We implement only a left action + if not self_on_left and scalar in P._V: + scalar = P._V(scalar) + return P.sum_of_terms((n+k, (P._a * n + P._b - k) * cv * cm) + for n,cv in scalar.monomial_coefficients(copy=False).items() if n != 'c' + for k,cm in self.monomial_coefficients(copy=False).items()) + return CombinatorialFreeModule.Element._acted_upon_(self, scalar, self_on_left) + + _rmul_ = _lmul_ = _acted_upon_ + +class VermaModule(CombinatorialFreeModule): + """ + A Verma module of the Virasoro algebra. + + The Virasoro algebra admits a triangular decomposition + + .. MATH:: + + V_- \oplus R d_0 \oplus R \hat{c} \oplus V_+, + + where `V_-` (resp. `V_+`) is the span of `\{d_i \mid i < 0\}` + (resp. `\{d_i \mid i > 0\}`). We can construct the *Verma module* + `M_{c,h}` as the induced representation of the `R d_0 \oplus + R \hat{c} \oplus V_+` representation `R_{c,H} = Rv`, where + + .. MATH:: + + V_+ v = 0, \qquad \hat{c} v = c v, \qquad d_0 v = h v. + + Therefore, we have a basis of `M_{c,h}` + + .. MATH:: + + \{ L_{i_1} \cdots L_{i_k} v \mid i_1 \leq \cdots \leq i_k < 0 \}. + + Moreover, the Verma modules are the free objects in the category of + highest weight representations of `V` and are indecomposable. + The Verma module `M_{c,h}` is irreducible for generic values of `c` + and `h` and when it is reducible, the quotient by the maximal + submodule is the unique irreducible highest weight representation + `V_{c,h}`. + + EXAMPLES: + + We construct a Verma module and do some basic computations:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(3, 0) + sage: d = L.basis() + sage: v = M.highest_weight_vector() + sage: d[3] * v + 0 + sage: d[-3] * v + d[-3]*v + sage: d[-1] * (d[-3] * v) + 2*d[-4]*v + d[-3]*d[-1]*v + sage: d[2] * (d[-1] * (d[-3] * v)) + 12*d[-2]*v + 5*d[-1]*d[-1]*v + + We verify that `d_{-1} v` is a singular vector for + `\{d_i \mid 1 \leq i < 20\}`:: + + sage: w = M.basis()[-1]; w + d[-1]*v + sage: all(d[i] * w == M.zero() for i in range(1,20)) + True + + We also verify a singular vector for `V_{-2,1}`:: + + sage: M = L.verma_module(-2, 1) + sage: B = M.basis() + sage: w = B[-1,-1] - 2 * B[-2] + sage: d = L.basis() + sage: all(d[i] * w == M.zero() for i in range(1,20)) + True + + REFERENCES: + + - :wikipedia:`Virasoro_algebra#Representation_theory` + """ + @staticmethod + def __classcall_private__(cls, V, c, h): + """ + Normalize input to ensure a unique representation. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(3, 1/2) + sage: M2 = L.verma_module(int(3), 1/2) + sage: M is M2 + True + """ + R = V.base_ring() + return super(VermaModule, cls).__classcall__(cls, V, R(c), R(h)) + + @staticmethod + def _partition_to_neg_tuple(x): + """ + Helper function to convert a partition to an increasing + sequence of negative numbers. + + EXAMPLES:: + + sage: from sage.algebras.lie_algebras.virasoro import VermaModule + sage: VermaModule._partition_to_neg_tuple([3,2,2,1]) + (-3, -2, -2, -1) + """ + # The entries of the partition are likely ints, but we need to + # make sure they are Integers. + return tuple([ZZ(-i) for i in x]) + + def __init__(self, V, c, h): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(3, 1/2) + sage: TestSuite(M).run() + """ + self._c = c + self._h = h + self._V = V + from sage.combinat.partition import _Partitions + indices = _Partitions.map(VermaModule._partition_to_neg_tuple) + CombinatorialFreeModule.__init__(self, V.base_ring(), + indices, prefix='v') + + def _repr_term(self, k): + """ + Return a string representation for the term indexed by ``k``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(1, -2) + sage: M._repr_term((-3,-2,-2,-1)) + 'd[-3]*d[-2]*d[-2]*d[-1]*v' + """ + if not k: + return 'v' + d = self._V.basis() + return '*'.join(repr(d[i]) for i in k) + '*v' + + def _latex_term(self, k): + """ + Return a latex representation for the term indexed by ``k``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(1, -2) + sage: M._latex_term((-3,-2,-2,-1)) + 'd_{-3} d_{-2} d_{-2} d_{-1} v' + """ + if not k: + return 'v' + d = self._V.basis() + from sage.misc.latex import latex + return ' '.join(latex(d[i]) for i in k) + ' v' + + def _repr_(self): + """ + Return a string representation of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(3, 0) + sage: M + Verma module with charge 3 and confromal weight 0 of + The Virasoro algebra over Rational Field + """ + return "Verma module with charge {} and confromal weight {} of {}".format( + self._c, self._h, self._V) + + def _monomial(self, index): + """ + TESTS:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(3, 0) + sage: v = M.basis() + sage: v[-3] # indirect doctest + d[-3]*v + sage: v[-3,-2,-2] # indirect doctest + d[-3]*d[-2]*d[-2]*v + """ + if index in ZZ: + if index >= 0: + raise ValueError("sequence must have non-positive entries") + index = (index,) + return super(VermaModule, self)._monomial(index) + + def central_charge(self): + """ + Return the central charge of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(3, 0) + sage: M.central_charge() + 3 + """ + return self._c + + def conformal_weight(self): + """ + Return the conformal weight of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(3, 0) + sage: M.conformal_weight() + 3 + """ + return self._c + + def virasoro_algebra(self): + """ + Return the Virasoro algebra ``self`` is a representation of. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(1/2, 3/4) + sage: M.virasoro_algebra() is L + True + """ + return self._V + + @cached_method + def highest_weight_vector(self): + """ + Return the highest weight vector of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(-2/7, 3) + sage: M.highest_weight_vector() + v + """ + return self.monomial(()) + + def _d_action_on_basis(self, n, k): + """ + Return the action of `d_n` on `v_k`. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: M = L.verma_module(-2/7, 3) + sage: M._d_action_on_basis(-3, ()) + d[-3]*v + sage: M._d_action_on_basis(0, ()) + 3*v + sage: M._d_action_on_basis('c', ()) + -2/7*v + sage: M._d_action_on_basis('c', (-4,-2,-2,-1)) + -2/7*d[-4]*d[-2]*d[-2]*d[-1]*v + sage: M._d_action_on_basis(3, (-4,-2,-2,-1)) + 7*d[-5]*d[-1]*v + 60*d[-4]*d[-2]*v + 15*d[-4]*d[-1]*d[-1]*v + + 14*d[-3]*d[-2]*d[-1]*v + 7*d[-2]*d[-2]*d[-1]*d[-1]*v + sage: M._d_action_on_basis(-1, (-4,-2,-2,-1)) + d[-9]*d[-1]*v + d[-5]*d[-4]*d[-1]*v + 3*d[-5]*d[-2]*d[-2]*d[-1]*v + + 2*d[-4]*d[-3]*d[-2]*d[-1]*v + d[-4]*d[-2]*d[-2]*d[-1]*d[-1]*v + """ + # c acts my multiplication by self._c on all elements + if n == 'c': + return self.term(k, self._c) + + # when k corresponds to the highest weight vector + if not k: + if n > 0: + return self.zero() + if n == 0: + return self.term(k, self._h) + return self.monomial((n,)) + + # The basis are eigenvectors for d_0 + if n == 0: + return self.term(k, self._h - sum(k)) + + # We keep things in order + if n <= k[0]: + return self.monomial((n,) + k) + + # [L_n, L_m] v = L_n L_m v - L_m L_n v + # L_n L_m v = L_m L_n v + [L_n, L_m] v + d = self._V.basis() + m = k[0] + k = k[1:] + # We need to explicitly call the action as this method is + # used in discovering the action + return (self._d_action_on_basis(n, k)._acted_upon_(d[m], False) + + self.monomial(k)._acted_upon_(d[n].bracket(d[m]), False)) + + class Element(CombinatorialFreeModule.Element): + def _acted_upon_(self, scalar, self_on_left=False): + """ + Return the action of ``scalar`` on ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: d = L.basis() + sage: M = L.verma_module(1/2, 3/4) + sage: x = d[-5] * M.an_element() + M.basis()[-10]; x + d[-10]*v + 2*d[-5]*v + 3*d[-5]*d[-2]*v + 2*d[-5]*d[-1]*v + sage: d[2] * x + 12*d[-8]*v + 39/4*d[-5]*v + 14*d[-3]*v + 21*d[-3]*d[-2]*v + + 14*d[-3]*d[-1]*v + sage: v = M.highest_weight_vector() + sage: d[2] * (d[-2] * v) + 13/4*v + + sage: it = iter(M.basis()) + sage: B = [next(it) for _ in range(10)] + sage: all(d[i]*(d[j]*v) - d[j]*(d[i]*v) == d[i].bracket(d[j])*v + ....: for i in range(-5, 5) for j in range(-5, 5) for v in B) + True + """ + P = self.parent() + # We implement only a left action + if not self_on_left and scalar in P._V: + scalar = P._V(scalar) + return P.linear_combination((P._d_action_on_basis(n, k), cv * cm) + for n,cv in scalar.monomial_coefficients(copy=False).items() + for k,cm in self.monomial_coefficients(copy=False).items()) + return CombinatorialFreeModule.Element._acted_upon_(self, scalar, self_on_left) + + _rmul_ = _lmul_ = _acted_upon_ + diff --git a/src/sage/algebras/orlik_solomon.py b/src/sage/algebras/orlik_solomon.py index 1a692846c46..5ee9915d980 100644 --- a/src/sage/algebras/orlik_solomon.py +++ b/src/sage/algebras/orlik_solomon.py @@ -284,7 +284,7 @@ def product_on_basis(self, a, b): return R(coeff) * self.subset_image(ns) - # r is the accumalator + # r is the accumulator # we reverse a in the product, so add a sign # note that l>=2 here if len(a) % 4 < 2: diff --git a/src/sage/algebras/steenrod/steenrod_algebra_bases.py b/src/sage/algebras/steenrod/steenrod_algebra_bases.py index bf04407ada0..8b59bee8d3b 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_bases.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_bases.py @@ -105,7 +105,7 @@ ` in :file:`steenrod_algebra.py`. """ -from __future__ import absolute_import +from __future__ import absolute_import, division #***************************************************************************** # Copyright (C) 2008-2010 John H. Palmieri @@ -484,12 +484,12 @@ def xi_degrees(n,p=2, reverse=True): [307, 18, 1] """ from sage.rings.all import Integer - if n <= 0: return [] + if n <= 0: + return [] N = Integer(n*(p-1) + 1) - l = [int((p**d-1)/(p-1)) for d in range(1,N.exact_log(p)+1)] - if not reverse: - return l - l.reverse() + l = [(p**d-1)//(p-1) for d in range(1, N.exact_log(p)+1)] + if reverse: + l.reverse() return l ######################################################## @@ -609,7 +609,7 @@ def milnor_basis(n, p=2, **kwds): # first find the P part of each basis element. # in this part of the code (the P part), all dimensions are # divided by 2(p-1). - for dim in range(n/(2*(p-1)) + 1): + for dim in range(n//(2*(p-1)) + 1): if dim == 0: P_result = [[0]] else: @@ -625,7 +625,7 @@ def milnor_basis(n, p=2, **kwds): for p_mono in P_result: deg = n - 2*dim*(p-1) q_degrees = [1+2*(p-1)*d for d in - xi_degrees(int((deg - 1)/(2*(p-1))), p)] + [1] + xi_degrees(int((deg - 1)//(2*(p-1))), p)] + [1] q_degrees_decrease = q_degrees q_degrees.reverse() if deg % (2*(p-1)) <= len(q_degrees): @@ -721,8 +721,8 @@ def serre_cartan_basis(n, p=2, bound=1, **kwds): new = vec + (last,) result.append(new) else: # p odd - if n % (2 * (p-1)) == 0 and n/(2 * (p-1)) >= bound: - result = [(0, int(n/(2 * (p-1))), 0)] + if n % (2 * (p-1)) == 0 and n//(2 * (p-1)) >= bound: + result = [(0, int(n//(2 * (p-1))), 0)] elif n == 1: result = [(1,)] else: @@ -1041,7 +1041,7 @@ def sorting_pair(s,t,basis): # pair used for sorting the basis trunc = kwds.get("truncation_type", 0) result = [] - for dim in range(n/(2*p-2) + 1): + for dim in range(n//(2*p-2) + 1): P_result = [] for v in WeightedIntegerVectors(dim, xi_degrees(dim, p=p, reverse=False)): mono = [] diff --git a/src/sage/calculus/desolvers.py b/src/sage/calculus/desolvers.py index 192c39a9209..24bc544690b 100644 --- a/src/sage/calculus/desolvers.py +++ b/src/sage/calculus/desolvers.py @@ -1178,7 +1178,7 @@ def desolve_rk4(de, dvar, ics=None, ivar=None, end_points=None, step=0.1, output [[0, 1], [0.5, 1.12419127424558], [1.0, 1.461590162288825]] Variant 1 for input - we can pass ODE in the form used by - desolve function In this example we integrate bakwards, since + desolve function In this example we integrate backwards, since ``end_points < ics[0]``:: sage: y = function('y')(x) diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index 78248bb4362..ab7559ea797 100644 --- a/src/sage/categories/category.py +++ b/src/sage/categories/category.py @@ -1738,7 +1738,7 @@ def morphism_class(self): This class contains the methods defined in the nested class ``self.MorphismMethods`` (if it exists), and has as bases the - morphims classes of the super categories of ``self``. + morphism classes of the super categories of ``self``. .. SEEALSO:: diff --git a/src/sage/categories/homset.py b/src/sage/categories/homset.py index eb57aee1198..a3595bd0fa8 100644 --- a/src/sage/categories/homset.py +++ b/src/sage/categories/homset.py @@ -47,8 +47,6 @@ - Simon King (2013-02): added examples """ -from __future__ import absolute_import - #***************************************************************************** # Copyright (C) 2005 David Kohel , William Stein # @@ -64,7 +62,9 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.categories.category import Category +from __future__ import absolute_import, print_function + +from sage.categories.category import Category, JoinCategory from . import morphism from sage.structure.parent import Parent, Set_generic from sage.misc.fast_methods import WithEqualityById @@ -343,6 +343,34 @@ def Hom(X, Y, category=None, check=True): si... = ... pg_Hom(si..., si..., ...) ... sage: Q == loads(dumps(Q)) True + + Check that the ``_Hom_`` method of the ``category`` input is used:: + + sage: from sage.categories.category_types import Category_over_base_ring + sage: class ModulesWithHom(Category_over_base_ring): + ....: def super_categories(self): + ....: return [Modules(self.base_ring())] + ....: class ParentMethods: + ....: def _Hom_(self, Y, category=None): + ....: print("Modules") + ....: raise TypeError + sage: class AlgebrasWithHom(Category_over_base_ring): + ....: def super_categories(self): + ....: return [Algebras(self.base_ring()), ModulesWithHom(self.base_ring())] + ....: class ParentMethods: + ....: def _Hom_(self, Y, category=None): + ....: R = self.base_ring() + ....: if category is not None and category.is_subcategory(Algebras(R)): + ....: print("Algebras") + ....: raise TypeError + sage: from sage.structure.element import Element + sage: class Foo(Parent): + ....: _no_generic_basering_coercion = True + ....: class Element(Element): + ....: pass + sage: X = Foo(base=QQ, category=AlgebrasWithHom(QQ)) + sage: H = Hom(X, X, ModulesWithHom(QQ)) + Modules """ # This should use cache_function instead # However some special handling is currently needed for @@ -394,18 +422,31 @@ def Hom(X, Y, category=None, check=True): try: # _Hom_ hook from the parent H = X._Hom_(Y, category) except (AttributeError, TypeError): - try: - # Workaround in case the above fails, but the category - # also provides a _Hom_ hook. - # FIXME: - # - If X._Hom_ actually comes from category and fails, it - # will be called twice. - # - This is bound to fail if X is an extension type and - # does not actually inherit from category.parent_class - H = category.parent_class._Hom_(X, Y, category = category) - except (AttributeError, TypeError): + # Workaround in case the above fails, but the category + # also provides a _Hom_ hook. + # FIXME: + # - If X._Hom_ actually comes from category and fails, it + # will be called twice. + # - This is bound to fail if X is an extension type and + # does not actually inherit from category.parent_class + # For join categories, we check all of the direct super + # categories as the parent_class of the join category is + # not (necessarily) inherited and join categories do not + # implement a _Hom_ (see trac #23418). + if not isinstance(category, JoinCategory): + cats = [category] + else: + cats = category.super_categories() + H = None + for C in cats: + try: + H = C.parent_class._Hom_(X, Y, category=category) + break + except (AttributeError, TypeError): + pass + if H is None: # By default, construct a plain homset. - H = Homset(X, Y, category = category, check=check) + H = Homset(X, Y, category=category, check=check) _cache[key] = H if isinstance(X, UniqueRepresentation) and isinstance(Y, UniqueRepresentation): if not isinstance(H, WithEqualityById): diff --git a/src/sage/categories/number_fields.py b/src/sage/categories/number_fields.py index a1c6336e656..0317f520a5e 100644 --- a/src/sage/categories/number_fields.py +++ b/src/sage/categories/number_fields.py @@ -26,6 +26,11 @@ class NumberFields(Category_singleton): sage: C Category of number fields + By definition, it is infinite:: + + sage: NumberFields().Infinite() is NumberFields() + True + Notice that the rational numbers `\QQ` *are* considered as an object in this category:: @@ -58,9 +63,9 @@ def super_categories(self): EXAMPLES:: sage: NumberFields().super_categories() - [Category of fields] + [Category of infinite fields] """ - return[Fields()] + return [Fields().Infinite()] def __contains__(self, x): r""" diff --git a/src/sage/coding/guruswami_sudan/gs_decoder.py b/src/sage/coding/guruswami_sudan/gs_decoder.py index ae566604ab4..e731b41c29c 100644 --- a/src/sage/coding/guruswami_sudan/gs_decoder.py +++ b/src/sage/coding/guruswami_sudan/gs_decoder.py @@ -390,7 +390,7 @@ def find_integral_max(real_max, f): lmax = sqrt(n*s*(s+1.)/(k-1.)) - 1. #the best integral value will be (l,tau) = find_integral_max(lmax, lambda l: get_tau(s,l)) - #Note that we have not proven that this ell is minimial in integral + #Note that we have not proven that this ell is minimal in integral #sense! It just seems that this most often happens return (tau,(s,l)) if l is not None: @@ -481,7 +481,7 @@ def gs_satisfactory(tau, s, l, C = None, n_k = None): INPUT: - - ``tau`` -- an integer, number of errrors one expects Guruswami-Sudan algorithm + - ``tau`` -- an integer, number of errors one expects Guruswami-Sudan algorithm to correct - ``s`` -- an integer, multiplicity parameter of Guruswami-Sudan algorithm - ``l`` -- an integer, list size parameter diff --git a/src/sage/combinat/abstract_tree.py b/src/sage/combinat/abstract_tree.py index 1bdede02f5c..4ced7fca867 100644 --- a/src/sage/combinat/abstract_tree.py +++ b/src/sage/combinat/abstract_tree.py @@ -72,6 +72,8 @@ # Unfortunately Cython forbids multiple inheritance. Therefore, we do not # inherit from SageObject to be able to inherit from Element or a subclass # of it later. + + class AbstractTree(object): """ Abstract Tree. @@ -1049,7 +1051,7 @@ def node_number(self): 5 """ if self.is_empty(): - return 0 + return Integer(0) else: return sum((i.node_number() for i in self), Integer(1)) @@ -1151,7 +1153,8 @@ def _ascii_art_(self): / / 14 15 """ - node_to_str = lambda t: str(t.label()) if hasattr(t, "label") else "o" + def node_to_str(t): + return str(t.label()) if hasattr(t, "label") else "o" if self.is_empty(): from sage.typeset.ascii_art import empty_ascii_art @@ -1159,15 +1162,15 @@ def _ascii_art_(self): from sage.typeset.ascii_art import AsciiArt if len(self) == 0: - t_repr = AsciiArt( [node_to_str(self)] ) + t_repr = AsciiArt([node_to_str(self)]) t_repr._root = 1 return t_repr if len(self) == 1: repr_child = self[0]._ascii_art_() - sep = AsciiArt( [" "*(repr_child._root-1)] ) - t_repr = AsciiArt( [node_to_str(self)] ) + sep = AsciiArt([" "*(repr_child._root-1)]) + t_repr = AsciiArt([node_to_str(self)]) t_repr._root = 1 - repr_root = (sep + t_repr)*(sep + AsciiArt( ["|"] )) + repr_root = (sep + t_repr)*(sep + AsciiArt(["|"])) t_repr = repr_root * repr_child t_repr._root = repr_child._root t_repr._baseline = t_repr._h - 1 @@ -1182,12 +1185,12 @@ def _ascii_art_(self): t_repr = l_repr.pop(0) acc += AsciiArt([" "]) + t_repr if len(l_repr) == 0: - lf_sep += "_"*(t_repr._root+1) + lf_sep += "_" * (t_repr._root + 1) else: - lf_sep += "_"*(t_repr._l+1) + lf_sep += "_" * (t_repr._l + 1) ls_sep += " "*(t_repr._root) + "/" + " "*(t_repr._l-t_repr._root) mid = whitesep + (len(lf_sep) - whitesep) // 2 - node = node_to_str( self ) + node = node_to_str(self) t_repr = AsciiArt([lf_sep[:mid-1] + node + lf_sep[mid+len(node)-1:], ls_sep]) * acc t_repr._root = mid t_repr._baseline = t_repr._h - 1 @@ -1302,8 +1305,8 @@ def node_to_str(t): tr = l_repr.pop(0) acc += UnicodeArt([u" "]) + tr if not len(l_repr): - lf_sep += u"─" * (tr._root) + u"╮" # + u" " * (tr._l - tr._root) - ls_sep += u" " * (tr._root) + u"│" # + u" " * (tr._l - tr._root) + lf_sep += u"─" * (tr._root) + u"╮" + ls_sep += u" " * (tr._root) + u"│" else: lf_sep += u"─" * (tr._root) + u"┬" + u"─" * (tr._l - tr._root) ls_sep += u" " * (tr._root) + u"│" + u" " * (tr._l - tr._root) @@ -1316,7 +1319,7 @@ def node_to_str(t): t_repr._baseline = t_repr._h - 1 return t_repr - def canonical_labelling(self,shift=1): + def canonical_labelling(self, shift=1): """ Returns a labelled version of ``self``. @@ -1345,9 +1348,9 @@ def canonical_labelling(self,shift=1): liste = [] deca = 1 for subtree in self: - liste += [subtree.canonical_labelling(shift+deca)] + liste += [subtree.canonical_labelling(shift + deca)] deca += subtree.node_number() - return LTR._element_constructor_(liste,label=shift) + return LTR._element_constructor_(liste, label=shift) def to_hexacode(self): r""" @@ -1419,7 +1422,7 @@ def tree_factorial(self): """ nb = self.node_number() if nb <= 1: - return 1 + return Integer(1) return nb * prod(s.tree_factorial() for s in self) def _latex_(self): @@ -1474,12 +1477,16 @@ def _latex_(self): space = " "*9 sepspace = sep + space spacesep = space + sep - node_to_str = lambda node: " " + node + " " * (len(space) - 1 - len(node)) + + def node_to_str(node): + return " " + node + " " * (len(space) - 1 - len(node)) # # TODO:: modify how to create nodes --> new_cmd : \\node[...] in create_node num = [0] def resolve(self): - nodes = []; matrix = []; edges = [] + nodes = [] + matrix = [] + edges = [] def create_node(self): r""" @@ -2034,7 +2041,7 @@ class AbstractLabelledTree(AbstractTree): .. SEEALSO:: :class:`AbstractTree` """ - def __init__(self, parent, children, label = None, check = True): + def __init__(self, parent, children, label=None, check=True): """ TESTS:: @@ -2100,7 +2107,7 @@ def _repr_(self): sage: LabelledOrderedTree([[],LabelledOrderedTree([[]], label=2)], label=3) 3[None[], 2[None[]]] """ - return "%s%s"%(self._label, self[:]) + return "%s%s" % (self._label, self[:]) def label(self, path=None): """ @@ -2177,7 +2184,7 @@ def leaf_labels(self): sage: LBT(None).leaf_labels() [] """ - return [t.label() for t in self.subtrees() if t.node_number()==1] + return [t.label() for t in self.subtrees() if t.node_number() == 1] def __eq__(self, other): """ @@ -2201,8 +2208,8 @@ def __eq__(self, other): sage: t1 == t2 False """ - return ( super(AbstractLabelledTree, self).__eq__(other) and - self._label == other._label ) + return (super(AbstractLabelledTree, self).__eq__(other) and + self._label == other._label) def _hash_(self): """ @@ -2292,8 +2299,8 @@ def as_digraph(self): Digraph on 4 vertices """ from sage.graphs.digraph import DiGraph - resu = dict([[self.label(), - [t.label() for t in self if not t.is_empty()]]]) + resu = {self.label(): + [t.label() for t in self if not t.is_empty()]} resu = DiGraph(resu, format="dict_of_lists") for t in self: if not t.is_empty(): diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index d8ecf4383c9..6ace53b8e96 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -374,7 +374,7 @@ def period(self, m): Return the period of the binary recurrence sequence modulo an integer ``m``. - If `n_1` is congruent to `n_2` modulu ``period(m)``, then `u_{n_1}` is + If `n_1` is congruent to `n_2` modulo ``period(m)``, then `u_{n_1}` is is congruent to `u_{n_2}` modulo ``m``. INPUT: diff --git a/src/sage/combinat/cartesian_product.py b/src/sage/combinat/cartesian_product.py index 0082a28710d..1dfb80c4473 100644 --- a/src/sage/combinat/cartesian_product.py +++ b/src/sage/combinat/cartesian_product.py @@ -19,8 +19,7 @@ from six.moves import range -from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets -from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets +from sage.categories.enumerated_sets import EnumeratedSets from sage.sets.set_from_iterator import EnumeratedSetFromIterator from inspect import isgenerator @@ -92,7 +91,6 @@ def CartesianProduct(*iters): deprecation(18411, "CartesianProduct is deprecated. Use cartesian_product instead") from sage.combinat.misc import IterableFunctionCall - from sage.sets.set_from_iterator import EnumeratedSetFromIterator deprecate_ifc = False iiters = [] for a in iters: @@ -163,16 +161,28 @@ def __init__(self, *iters): """ TESTS:: - sage: import sage.combinat.cartesian_product as cartesian_product - sage: cp = cartesian_product.CartesianProduct_iters([1,2],[3,4]); cp + sage: from sage.combinat.cartesian_product import CartesianProduct_iters + sage: cp = CartesianProduct_iters([1,2],[3,4]); cp Cartesian product of [1, 2], [3, 4] sage: loads(dumps(cp)) == cp True sage: TestSuite(cp).run(skip='_test_an_element') + + Check that :trac:`24558` is fixed:: + + sage: from sage.combinat.cartesian_product import CartesianProduct_iters + sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator + sage: I = EnumeratedSetFromIterator(Integers) + sage: CartesianProduct_iters(I, I) + Cartesian product of {0, 1, -1, 2, -2, ...}, {0, 1, -1, 2, -2, ...} """ self.iters = iters self._mrange = xmrange_iter(iters) - category = FiniteEnumeratedSets() if self.is_finite() else InfiniteEnumeratedSets() + category = EnumeratedSets() + try: + category = category.Finite() if self.is_finite() else category.Infinite() + except ValueError: # Unable to determine if it is finite or not + pass def iterfunc(): # we can not use self.__iterate__ directly because # that leads to an infinite recursion in __eq__ diff --git a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py index 5f96100876b..b4fd1b000e7 100644 --- a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py +++ b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py @@ -2547,7 +2547,8 @@ def mutate(self, sequence, inplace=True, input_type=None): is_vertices = set(seqq).issubset(set(seed._nlist)) is_indices = set(seqq).issubset(set(range(n))) - # Note - this does not guarantee that the sequence consists of cluster variables, it only rules out some posibilities. + # Note - this does not guarantee that the sequence consists of + # cluster variables, it only rules out some possibilities. is_cluster_vars = reduce(lambda x, y: isinstance(y, str), seqq, 1) and seed._use_fpolys # Ensures the sequence has elements of type input_type. @@ -4921,7 +4922,7 @@ def is_LeeLiZel_allowable(T,n,m,b,c): def get_green_vertices(C): r""" - Get the green vertices from a matrix. Will go through each clumn and return + Get the green vertices from a matrix. Will go through each column and return the ones where no entry is greater than 0. INPUT: diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py index f236b90c536..ab6436b3fa1 100644 --- a/src/sage/combinat/composition.py +++ b/src/sage/combinat/composition.py @@ -1226,7 +1226,7 @@ def shuffle_product(self, other, overlap=False): OUTPUT: - An enumerated set (allowing for mutliplicities) + An enumerated set (allowing for multiplicities) EXAMPLES: diff --git a/src/sage/combinat/composition_tableau.py b/src/sage/combinat/composition_tableau.py index b2f9593a830..1eba224737d 100644 --- a/src/sage/combinat/composition_tableau.py +++ b/src/sage/combinat/composition_tableau.py @@ -318,7 +318,7 @@ class CompositionTableaux(UniqueRepresentation, Parent): [[3, 3, 3]]] sage: CT = CompositionTableaux([1,2,1]); CT - Composition tableaux of shape [1, 2, 1] and maximun entry 4 + Composition tableaux of shape [1, 2, 1] and maximum entry 4 sage: list(CT) [[[1], [2, 2], [3]], [[1], [2, 2], [4]], @@ -327,7 +327,7 @@ class CompositionTableaux(UniqueRepresentation, Parent): [[2], [3, 3], [4]]] sage: CT = CompositionTableaux(shape=[1,2,1],max_entry=3); CT - Composition tableaux of shape [1, 2, 1] and maximun entry 3 + Composition tableaux of shape [1, 2, 1] and maximum entry 3 sage: list(CT) [[[1], [2, 2], [3]]] @@ -363,17 +363,17 @@ def __classcall_private__(cls, *args, **kwargs): sage: CT = CompositionTableaux(size=3); CT Composition Tableaux of size 3 and maximum entry 3 sage: CT = CompositionTableaux([1,2]); CT - Composition tableaux of shape [1, 2] and maximun entry 3 + Composition tableaux of shape [1, 2] and maximum entry 3 sage: CT = CompositionTableaux(shape=[1,2]); CT - Composition tableaux of shape [1, 2] and maximun entry 3 + Composition tableaux of shape [1, 2] and maximum entry 3 sage: CT = CompositionTableaux(shape=[]); CT - Composition tableaux of shape [] and maximun entry 0 + Composition tableaux of shape [] and maximum entry 0 sage: CT = CompositionTableaux(0); CT Composition Tableaux of size 0 and maximum entry 0 sage: CT = CompositionTableaux(max_entry=3); CT Composition tableaux with maximum entry 3 sage: CT = CompositionTableaux([1,2],max_entry=3); CT - Composition tableaux of shape [1, 2] and maximun entry 3 + Composition tableaux of shape [1, 2] and maximum entry 3 sage: CT = CompositionTableaux(size=2,shape=[1,2]); CT Traceback (most recent call last): ... @@ -737,11 +737,11 @@ def _repr_(self): TESTS:: sage: CompositionTableaux([1,2,1]) - Composition tableaux of shape [1, 2, 1] and maximun entry 4 + Composition tableaux of shape [1, 2, 1] and maximum entry 4 sage: CompositionTableaux([1,2,1],max_entry=3) - Composition tableaux of shape [1, 2, 1] and maximun entry 3 + Composition tableaux of shape [1, 2, 1] and maximum entry 3 """ - return "Composition tableaux of shape %s and maximun entry %s"%(str(self.shape), str(self.max_entry)) + return "Composition tableaux of shape %s and maximum entry %s" % (str(self.shape), str(self.max_entry)) def an_element(self): r""" diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 68a5ae7da85..9eb981769ca 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -2706,7 +2706,7 @@ class FiniteStateMachine(sage.structure.sage_object.SageObject): process. - ``store_states_dict`` -- If ``True``, then additionally the states - are stored in an interal dictionary for speed up. + are stored in an internal dictionary for speed up. - ``on_duplicate_transition`` -- A function which is called when a transition is inserted into ``self`` which already existed (same diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 447da288ae1..a7579527bf2 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -31,9 +31,11 @@ import sage.data_structures.blas_dict as blas from sage.typeset.ascii_art import AsciiArt from sage.typeset.unicode_art import UnicodeArt +from sage.misc.superseded import deprecation import six + class CombinatorialFreeModule(UniqueRepresentation, Module, IndexedGenerators): r""" Class for free modules with a named basis @@ -851,10 +853,16 @@ def get_order_cmp(self): Return a comparison function on the basis indices that is compatible with the current term order. + DEPRECATED by :trac:`24548`. + EXAMPLES:: sage: A = FiniteDimensionalAlgebrasWithBasis(QQ).example() sage: Acmp = A.get_order_cmp() + doctest:warning...: + DeprecationWarning: comparison should use keys + See http://trac.sagemath.org/24548 for details. + sage: sorted(A.basis().keys(), Acmp) ['x', 'y', 'a', 'b'] sage: A.set_order(list(reversed(A.basis().keys()))) @@ -862,6 +870,7 @@ def get_order_cmp(self): sage: sorted(A.basis().keys(), Acmp) ['b', 'a', 'y', 'x'] """ + deprecation(24548, 'comparison should use keys') self.get_order() return self._order_cmp @@ -869,6 +878,8 @@ def _order_cmp(self, x, y): """ Compare `x` and `y` w.r.t. the term order. + DEPRECATED by :trac:`24548`. + INPUT: - ``x``, ``y`` -- indices of the basis of ``self`` @@ -883,12 +894,16 @@ def _order_cmp(self, x, y): sage: A = CombinatorialFreeModule(QQ, ['x','y','a','b']) sage: A.set_order(['x', 'y', 'a', 'b']) sage: A._order_cmp('x', 'y') + doctest:warning...: + DeprecationWarning: comparison should use keys + See http://trac.sagemath.org/24548 for details. -1 sage: A._order_cmp('y', 'y') 0 sage: A._order_cmp('a', 'y') 1 """ + deprecation(24548, 'comparison should use keys') ix = self._rank_basis(x) iy = self._rank_basis(y) if ix < iy: diff --git a/src/sage/combinat/integer_matrices.py b/src/sage/combinat/integer_matrices.py index cd8b2236c2b..ec35259808a 100644 --- a/src/sage/combinat/integer_matrices.py +++ b/src/sage/combinat/integer_matrices.py @@ -323,7 +323,7 @@ def integer_matrices_generator(row_sums, column_sums): """ column_sums = list(column_sums) if sum(row_sums) != sum(column_sums): - raise StopIteration + return if not row_sums: yield [] elif len(row_sums) == 1: diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py index f15a58caba1..5610576bbe1 100644 --- a/src/sage/combinat/q_analogues.py +++ b/src/sage/combinat/q_analogues.py @@ -2,7 +2,7 @@ r""" `q`-Analogues """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007 Mike Hansen , # # Distributed under the terms of the GNU General Public License (GPL) @@ -15,7 +15,7 @@ # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ -#***************************************************************************** +# **************************************************************************** # python3 from __future__ import division @@ -69,7 +69,7 @@ def q_int(n, q=None): sage: q_int(0).parent() Univariate Polynomial Ring in q over Integer Ring """ - if not n in ZZ: + if n not in ZZ: raise ValueError('%s must be an integer' % n) if q is None: @@ -80,6 +80,7 @@ def q_int(n, q=None): return sum(q**i for i in range(n)) return -q**n*sum(q**i for i in range(-n)) + def q_factorial(n, q=None): """ Returns the `q`-analogue of the factorial `n!`. @@ -105,9 +106,10 @@ def q_factorial(n, q=None): ValueError: Argument (-2) must be a nonnegative integer. """ if n in ZZ and n >= 0: - return prod([q_int(i, q) for i in range(1, n+1)]) + return prod(q_int(i, q) for i in range(1, n + 1)) else: - raise ValueError("Argument (%s) must be a nonnegative integer." %n) + raise ValueError("Argument (%s) must be a nonnegative integer." % n) + def q_binomial(n, k, q=None, algorithm='auto'): r""" @@ -297,7 +299,7 @@ def q_binomial(n, k, q=None, algorithm='auto'): if not(0 <= k and k <= n): return zero - k = min(n-k,k) # Pick the smallest k + k = min(n - k, k) # Pick the smallest k # heuristic choice of the fastest algorithm if algorithm == 'auto': @@ -322,7 +324,7 @@ def q_binomial(n, k, q=None, algorithm='auto'): # the algorithms if algorithm == 'naive': denom = prod(one - q**i for i in range(1, k+1)) - if not denom: # q is a root of unity, use the cyclotomic algorithm + if not denom: # q is a root of unity, use the cyclotomic algorithm from sage.rings.polynomial.cyclotomic import cyclotomic_value return cyclotomic_value(n, k, q, algorithm='cyclotomic') else: @@ -359,6 +361,7 @@ def gaussian_binomial(n, k, q=None, algorithm='auto'): """ return q_binomial(n, k, q, algorithm) + def q_multinomial(seq, q=None, binomial_algorithm='auto'): r""" Return the `q`-multinomial coefficient. @@ -485,11 +488,12 @@ def qt_catalan_number(n): ZZqt = ZZ['q','t'] d = {} for dw in DyckWords(n): - tup = (dw.area(),dw.bounce()) - d[tup] = d.get(tup,0)+1 + tup = (dw.area(), dw.bounce()) + d[tup] = d.get(tup, 0) + 1 return ZZqt(d) else: - raise ValueError("Argument (%s) must be a nonnegative integer." %n) + raise ValueError("Argument (%s) must be a nonnegative integer." % n) + def q_pochhammer(n, a, q=None): r""" @@ -556,6 +560,7 @@ def q_pochhammer(n, a, q=None): return R.prod(one / (one - a/q**-k) for k in range(1,-n+1)) return R.prod((one - a*q**k) for k in range(n)) + @cached_function def q_jordan(t, q): r""" @@ -614,7 +619,6 @@ def q_jordan(t, q): - Xavier Caruso (2012-06-29) """ - if q == 1: raise ValueError("q must not be equal to 1") @@ -631,6 +635,7 @@ def q_jordan(t, q): tj = ti return res + def q_subgroups_of_abelian_group(la, mu, q=None, algorithm='birkhoff'): r""" Return the `q`-number of subgroups of type ``mu`` in a finite abelian @@ -756,7 +761,7 @@ def q_subgroups_of_abelian_group(la, mu, q=None, algorithm='birkhoff'): - Tomer Bauer (2013-09-26): Implemented the Birkhoff algorithm """ if q is None: - q = ZZ['q'].gens()[0] + q = ZZ['q'].gen() la_c = Partition(la).conjugate() mu_c = Partition(mu).conjugate() k = mu_c.length() @@ -780,3 +785,64 @@ def F(args): raise ValueError("invalid algorithm choice") + +@cached_function +def q_stirling_number1(n, k, q=None): + r""" + Return the (unsigned) `q`-Stirling number of the first kind. + + This is a `q`-analogue of :func:`sage.combinat.combinat.stirling_number1` . + + INPUT: + + - ``n``, ``k`` -- integers with ``1 <= k <= n`` + + - ``q`` -- optional variable (default `q`) + + OUTPUT: a polynomial in the variable `q` + + These polynomials satisfy the recurrence + + .. MATH:: + + s_{n,k} = s_{n-1,k-1} + [n-1]_q s_{n-1, k}. + + EXAMPLES:: + + sage: from sage.combinat.q_analogues import q_stirling_number1 + sage: q_stirling_number1(4,2) + q^3 + 3*q^2 + 4*q + 3 + + sage: all(stirling_number1(6,k) == q_stirling_number1(6,k)(1) + ....: for k in range(1,7)) + True + + sage: x = polygen(QQ['q'],'x') + sage: S = sum(q_stirling_number1(5,k)*x**k for k in range(1, 6)) + sage: factor(S) + x * (x + 1) * (x + q + 1) * (x + q^2 + q + 1) * (x + q^3 + q^2 + q + 1) + + TESTS:: + + sage: q_stirling_number1(-1,2) + Traceback (most recent call last): + ... + ValueError: q-Stirling numbers are not defined for n < 0 + + REFERENCES: + + - [Ca1948]_ + + - [Ca1954]_ + """ + if q is None: + q = ZZ['q'].gen() + A = q.parent() + if n < 0: + raise ValueError('q-Stirling numbers are not defined for n < 0') + if n == 0 == k: + return A.one() + if k > n or k < 1: + return A.zero() + return (q_stirling_number1(n - 1, k - 1, q=q) + + q_int(n - 1) * q_stirling_number1(n - 1, k, q=q)) diff --git a/src/sage/combinat/root_system/cartan_type.py b/src/sage/combinat/root_system/cartan_type.py index c4231a6af0a..f3515a39f1e 100644 --- a/src/sage/combinat/root_system/cartan_type.py +++ b/src/sage/combinat/root_system/cartan_type.py @@ -473,7 +473,7 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import print_function, absolute_import +from __future__ import print_function, absolute_import, division from six.moves import range from six.moves.builtins import sorted @@ -708,17 +708,17 @@ def __call__(self, *args): from . import type_BC_affine return type_BC_affine.CartanType(n) if letter == "A" and t[2] == 2: - if n%2 == 0: # Kac' A_2n^(2) - return CartanType(["BC", ZZ(n/2), 2]) + if n % 2 == 0: # Kac' A_2n^(2) + return CartanType(["BC", ZZ(n//2), 2]) else: # Kac' A_2n-1^(2) - return CartanType(["B", ZZ((n+1)/2), 1]).dual() + return CartanType(["B", ZZ((n+1)//2), 1]).dual() if letter == "D" and t[2] == 2: return CartanType(["C", n-1, 1]).dual() if letter == "D" and t[2] == 3 and n == 4: return CartanType(["G", 2, 1]).dual().relabel([0,2,1]) if letter == "E" and t[2] == 2 and n == 6: return CartanType(["F", 4, 1]).dual() - raise ValueError("%s is not a valid Cartan type"%t) + raise ValueError("%s is not a valid Cartan type" % t) if isinstance(t[0], string_types) and isinstance(t[1], (list, tuple)): letter, n = t[0], t[1] diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 6797d671797..6d484917311 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -2526,7 +2526,7 @@ def plot_hedron(self, **options): sage: RootSystem(["D",3]).ambient_space().plot_hedron() Graphics3d Object - Surprise: polyhedrons of large dimension know how to + Surprise: polyhedra of large dimension know how to project themselves nicely:: sage: RootSystem(["F",4]).ambient_space().plot_hedron() # long time diff --git a/src/sage/combinat/similarity_class_type.py b/src/sage/combinat/similarity_class_type.py index 4e49bbcecd0..2110f05a97f 100644 --- a/src/sage/combinat/similarity_class_type.py +++ b/src/sage/combinat/similarity_class_type.py @@ -2,7 +2,7 @@ Similarity class types of matrices with entries in a finite field The notion of a matrix conjugacy class type was introduced by J. A. Green in -[Green55]_, in the context of computing the irreducible charcaters of finite +[Green55]_, in the context of computing the irreducible characters of finite general linear groups. The class types are equivalence classes of similarity classes of square matrices with entries in a finite field which, roughly speaking, have the same qualitative properties. diff --git a/src/sage/combinat/species/series.py b/src/sage/combinat/species/series.py index bdad43ef40f..2a5f966432d 100644 --- a/src/sage/combinat/species/series.py +++ b/src/sage/combinat/species/series.py @@ -406,10 +406,9 @@ def _product_generator_gen(self, g): """ EXAMPLES:: - sage: from builtins import map sage: from sage.combinat.species.stream import _integers_from sage: L = LazyPowerSeriesRing(QQ) - sage: g = map(lambda i: L([1]+[0]*i+[1]), _integers_from(0)) + sage: g = (L([1]+[0]*i+[1]) for i in _integers_from(0)) sage: g2 = L._product_generator_gen(g) sage: [next(g2) for i in range(10)] [1, 1, 2, 4, 7, 12, 20, 33, 53, 84] @@ -1488,7 +1487,7 @@ def _integral_zero_gen(self, ao): #Check to see if the stream is finite if self.is_finite(n-1): yield self._stream[n-1] - raise StopIteration + break else: yield (Integer(1)/Integer(n))*self._stream[n-1] n += 1 @@ -1511,7 +1510,6 @@ def _integral_nonzero_gen(self, integration_constant): if ao == inf: yield self._zero - raise StopIteration else: for _ in range(ao-1): yield self._zero @@ -1523,7 +1521,7 @@ def _integral_nonzero_gen(self, integration_constant): #Check to see if the stream is finite if self.is_finite(n-1): yield self.coefficient(n-1) - raise StopIteration + break else: yield (Integer(1)/Integer(n))*self.coefficient(n-1) n += 1 diff --git a/src/sage/combinat/species/stream.py b/src/sage/combinat/species/stream.py index 4b1335975e8..1040411f1b2 100644 --- a/src/sage/combinat/species/stream.py +++ b/src/sage/combinat/species/stream.py @@ -358,7 +358,6 @@ def __iter__(self): except IndexError: break i += 1 - raise StopIteration def __len__(self): """ diff --git a/src/sage/combinat/tamari_lattices.py b/src/sage/combinat/tamari_lattices.py index 2dfba4b6b6b..39aabcee00b 100644 --- a/src/sage/combinat/tamari_lattices.py +++ b/src/sage/combinat/tamari_lattices.py @@ -163,7 +163,7 @@ def GeneralizedTamariLattice(a, b, m=1): - `a` and `b` coprime integers with `a \geq b` - - `m` a nonnegative integer such that `a \geq b \times m` + - `m` a nonnegative integer such that `a \geq b m` OUTPUT: @@ -222,21 +222,26 @@ def covers(p): for p in paths_in_triangle(a, b, a, b)])) -def TamariLattice(n): +def TamariLattice(n, m=1): r""" Return the `n`-th Tamari lattice. + Using the slope parameter `m`, one can also get the `m`-Tamari lattices. + INPUT: - - `n` a nonnegative integer + - `n` -- a nonnegative integer (the index) + + - `m` -- an optional nonnegative integer (the slope, default to 1) OUTPUT: - - a finite lattice + a finite lattice - The elements of the lattice are - :func:`Dyck paths` - in the `(n+1 \times n)`-rectangle. + In the usual case, the elements of the lattice are :func:`Dyck + paths` in the `(n+1 \times + n)`-rectangle. For a general slope `m`, the elements are Dyck + paths in the `(m n+1 \times n)`-rectangle. See :wikipedia:`Tamari lattice` for mathematical background. @@ -245,5 +250,12 @@ def TamariLattice(n): sage: posets.TamariLattice(3) Finite lattice containing 5 elements + + sage: posets.TamariLattice(3, 2) + Finite lattice containing 12 elements + + REFERENCES: + + - [BMFPR]_ """ - return GeneralizedTamariLattice(n + 1, n, 1) + return GeneralizedTamariLattice(m * n + 1, n, m) diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index 206d7f6b639..f761f8f2c97 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -1834,7 +1834,8 @@ def _dlx_solutions_iterator(self): [[0, 7, 14], [0, 12, 10], [6, 13, 5], [6, 14, 2], [11, 9, 5], [11, 10, 3]] """ if len(self.rows()) == 0: - raise StopIteration + return + x = self.dlx_solver() while x.search() == 1: yield x.get_solution() @@ -2047,7 +2048,7 @@ def solve(self, partial=None): """ if not self.is_suitable(): - raise StopIteration + return if partial is None: it = self._dlx_solutions_iterator() elif partial == 'common_prefix': diff --git a/src/sage/combinat/tutorial.py b/src/sage/combinat/tutorial.py index 95f07084e97..cf479065cfd 100644 --- a/src/sage/combinat/tutorial.py +++ b/src/sage/combinat/tutorial.py @@ -1270,27 +1270,18 @@ sage: from builtins import map, filter +but they should rather be avoided, using list comprehension instead. + To apply a function to all the elements, one can do:: - sage: from builtins import map - sage: list(map(lambda z: z.cycle_type(), Permutations(3))) + sage: list(z.cycle_type() for z in Permutations(3)) [[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]] and similarly to select the elements satisfying a certain condition:: - sage: from builtins import filter - sage: list(filter(lambda z: z.has_pattern([1,2]), Permutations(3))) + sage: list(z for z in Permutations(3) if z.has_pattern([1,2])) [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2]] -In all these situations, ``attrcall`` can be an advantageous alternative -to creating an anonymous function:: - - sage: from builtins import map - sage: list(map(lambda z: z.cycle_type(), Permutations(3))) - [[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]] - sage: list(map(attrcall("cycle_type"), Permutations(3))) - [[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]] - Implementation of new iterators ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/sage/combinat/words/abstract_word.py b/src/sage/combinat/words/abstract_word.py index 4dd0b0f092e..23ed90125f4 100644 --- a/src/sage/combinat/words/abstract_word.py +++ b/src/sage/combinat/words/abstract_word.py @@ -39,8 +39,11 @@ from sage.combinat.words.word_options import word_options from itertools import islice, groupby from sage.rings.all import Integers, ZZ, Infinity +from sage.structure.richcmp import (richcmp_method, rich_to_bool, + richcmp, op_LT, op_GT) +@richcmp_method class Word_class(SageObject): def parent(self): r""" @@ -258,93 +261,43 @@ def __len__(self): raise TypeError(msg) return int(L) - def __cmp__(self, other): + def __richcmp__(self, other, op): r""" - Compares two words lexicographically according to the ordering - defined by the parent of self. This corresponds to Python's built-in + Compare two words lexicographically according to the ordering + defined by the parent of ``self``. + + This corresponds to Python's built-in ordering when no parent nor alphabet was used to defined the word. Provides for all normal comparison operators. .. NOTE:: - This function will not terminate if self and other are equal - infinite words! + This function will not terminate if ``self`` and ``other`` + are equal infinite words! EXAMPLES:: sage: W = Word sage: from itertools import count - sage: W(range(1,10)).__cmp__(W(range(10))) > 0 + sage: W(range(1,10)) > W(range(10)) True - sage: W(range(10)).__cmp__(W(range(1,10))) < 0 + sage: W(range(10)) < W(range(1,10)) True - sage: W(range(10)).__cmp__(W(range(10))) == 0 + sage: W(range(10)) == W(range(10)) True - sage: W(range(10)).__cmp__(W(count())) < 0 + sage: W(range(10)) < W(count()) True - sage: W(count()).__cmp__(W(range(10))) > 0 + sage: W(count()) > W(range(10)) True :: sage: W = Words(['a', 'b', 'c']) - sage: W('a').__cmp__(W([])) - 1 - sage: W([]).__cmp__(W('a')) - -1 - """ - if not isinstance(other, Word_class): - return NotImplemented - self_it, other_it = iter(self), iter(other) - cmp_key = self._parent.sortkey_letters - while True: - try: - cs = next(self_it) - except StopIteration: - try: - co = next(other_it) - except StopIteration: - # If both self_it and other_it are exhausted then - # self == other. Return 0. - return 0 - else: - # If self_it is exhausted, but not other_it, then - # self is a proper prefix of other: return -1 - return -1 - else: - try: - co = next(other_it) - except StopIteration: - # If self_it is not exhausted but other_it is, then - # other is a proper prefix of self: return 1. - return 1 - else: - key_cs = cmp_key(cs) - key_co = cmp_key(co) - if key_cs < key_co: - return -1 - elif key_cs > key_co: - return 1 - - def __eq__(self, other): - r""" - Returns True if self is equal to other and False otherwise. - - INPUT: - - - ``other`` - a word - - OUTPUT: - - boolean - - .. NOTE:: - - This function will not terminate if self and other are equal - infinite words! - - EXAMPLES:: + sage: W('a') > W([]) + True + sage: W([]) < W('a') + True sage: Word('abc') == Word(['a','b','c']) True @@ -369,11 +322,21 @@ def __eq__(self, other): sage: Word(lambda n:n) == Word(range(20)) False - Beware the following does not halt!:: + Beware the following does not halt! :: sage: from itertools import count sage: Word(lambda n:n) == Word(count()) #not tested + Examples for unequality:: + + sage: w = Word(range(10)) + sage: z = Word(range(10)) + sage: w != z + False + sage: u = Word(range(12)) + sage: u != w + True + TESTS:: sage: Word(count())[:20] == Word(range(20)) @@ -388,6 +351,7 @@ def __eq__(self, other): if not isinstance(other, Word_class): return NotImplemented self_it, other_it = iter(self), iter(other) + cmp_key = self._parent.sortkey_letters while True: try: cs = next(self_it) @@ -397,50 +361,25 @@ def __eq__(self, other): except StopIteration: # If both self_it and other_it are exhausted then # self == other. Return 0. - return True + return rich_to_bool(op, 0) else: # If self_it is exhausted, but not other_it, then # self is a proper prefix of other: return -1 - return False + return rich_to_bool(op, -1) else: try: co = next(other_it) except StopIteration: # If self_it is not exhausted but other_it is, then # other is a proper prefix of self: return 1. - return False + return rich_to_bool(op, 1) else: - if cs != co: - return False - - def __ne__(self, other): - r""" - Returns True if self is not equal to other and False otherwise. - - INPUT: - - - ``other`` - a word - - OUTPUT: - - boolean - - .. NOTE:: - - This function will not terminate if self and other are equal - infinite words! - - EXAMPLES:: - - sage: w = Word(range(10)) - sage: z = Word(range(10)) - sage: w != z - False - sage: u = Word(range(12)) - sage: u != w - True - """ - return not self == other + key_cs = cmp_key(cs) + key_co = cmp_key(co) + if key_cs < key_co: + return rich_to_bool(op, -1) + elif key_cs > key_co: + return rich_to_bool(op, 1) def _longest_common_prefix_iterator(self, other): r""" @@ -470,9 +409,7 @@ def _longest_common_prefix_iterator(self, other): if b == c: yield b else: - raise StopIteration - else: - raise StopIteration + break def longest_common_prefix(self, other, length='unknown'): r""" @@ -600,11 +537,11 @@ def _longest_periodic_prefix_iterator(self, period=1): sage: list(Word([1,2,1,2,1,3])._longest_periodic_prefix_iterator(2)) [1, 2, 1, 2, 1] """ - for i,l in enumerate(self): - if self[i%period] == l: + for i, l in enumerate(self): + if self[i % period] == l: yield l else: - raise StopIteration + break def longest_periodic_prefix(self, period=1): r""" @@ -770,7 +707,7 @@ def lex_less(self, other): sage: t[:10].lex_less(t) True """ - return self < other + return richcmp(self, other, op_LT) def lex_greater(self, other): r""" @@ -800,9 +737,9 @@ def lex_greater(self, other): sage: t.lex_greater(t[:10]) True """ - return self > other + return richcmp(self, other, op_GT) - def apply_morphism(self,morphism): + def apply_morphism(self, morphism): r""" Returns the word obtained by applying the morphism to self. @@ -874,13 +811,14 @@ def _delta_iterator(self): def delta(self): r""" - Returns the image of self under the delta morphism. This is the - word composed of the length of consecutive runs of the same letter - in a given word. + Returns the image of self under the delta morphism. + + This is the word composed of the length of consecutive runs of + the same letter in a given word. OUTPUT: - Word over integers + Word over integers EXAMPLES: @@ -903,7 +841,8 @@ def delta(self): word: 1211222112112112221122211222112112112221... """ from sage.combinat.words.word import Word - return Word(self._delta_iterator()) + from sage.rings.semirings.non_negative_integer_semiring import NN + return Word(self._delta_iterator(), alphabet=NN) def _iterated_right_palindromic_closure_iterator(self, f=None): r""" diff --git a/src/sage/combinat/words/alphabet.py b/src/sage/combinat/words/alphabet.py index fd7d97ac78a..9e84451f6af 100644 --- a/src/sage/combinat/words/alphabet.py +++ b/src/sage/combinat/words/alphabet.py @@ -142,7 +142,7 @@ def build_alphabet(data=None, names=None, name=None): The other families for the option ``name`` are among 'lower', 'upper', 'space', 'underscore', 'punctuation', 'printable', 'binary', 'octal', 'decimal', 'hexadecimal', 'radix64' which refer to standard set of - charaters. Theses names may be combined by separating them by a space:: + characters. Theses names may be combined by separating them by a space:: sage: build_alphabet(name="lower") {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'} diff --git a/src/sage/combinat/words/word_datatypes.pyx b/src/sage/combinat/words/word_datatypes.pyx index 9d9654f7270..5ba87408f43 100644 --- a/src/sage/combinat/words/word_datatypes.pyx +++ b/src/sage/combinat/words/word_datatypes.pyx @@ -174,24 +174,15 @@ cdef class WordDatatype_list(WordDatatype): http://docs.cython.org/docs/special_methods.html """ - if op == Py_EQ: - if isinstance(other, WordDatatype_list): + if isinstance(other, WordDatatype_list): + if op == Py_EQ: return self._data == other._data - else: - # Otherwise, force FiniteWord_class.__eq__ to do it - # (if we don't force it, then __cmp__ is called before) - from sage.combinat.words.word import FiniteWord_class - return FiniteWord_class.__eq__(self, other) - elif op == Py_NE: - if isinstance(other, WordDatatype_list): + elif op == Py_NE: return self._data != other._data - else: - # Otherwise, force FiniteWord_class.__eq__ to do it - # (if we don't force it, then __cmp__ is called before) - from sage.combinat.words.word import FiniteWord_class - return not FiniteWord_class.__eq__(self,other) - else: - return NotImplemented + + # Otherwise, force FiniteWord_class.__richcmp__ to do it + from sage.combinat.words.word import FiniteWord_class + return FiniteWord_class.__richcmp__(self, other, op) def __len__(self): r""" @@ -385,24 +376,15 @@ cdef class WordDatatype_str(WordDatatype): http://docs.cython.org/docs/special_methods.html """ - if op == Py_EQ: - if isinstance(other, WordDatatype_str): + if isinstance(other, WordDatatype_str): + if op == Py_EQ: return self._data == other._data - else: - # Otherwise, force FiniteWord_class.__eq__ to do it - # (if we don't force it, then __cmp__ is called before) - from sage.combinat.words.word import FiniteWord_class - return FiniteWord_class.__eq__(self,other) - elif op == Py_NE: - if isinstance(other, WordDatatype_str): + elif op == Py_NE: return self._data != other._data - else: - # Otherwise, force FiniteWord_class.__eq__ to do it - # (if we don't force it, then __cmp__ is called before) - from sage.combinat.words.word import FiniteWord_class - return not FiniteWord_class.__eq__(self,other) - else: - return NotImplemented + + # Otherwise, force FiniteWord_class.__richcmp__ to do it + from sage.combinat.words.word import FiniteWord_class + return FiniteWord_class.__richcmp__(self, other, op) def __contains__(self, a): r""" @@ -998,24 +980,15 @@ cdef class WordDatatype_tuple(WordDatatype): http://docs.cython.org/docs/special_methods.html """ - if op == Py_EQ: - if isinstance(other, WordDatatype_tuple): + if isinstance(other, WordDatatype_tuple): + if op == Py_EQ: return self._data == other._data - else: - # Otherwise, force FiniteWord_class.__eq__ to do it - # (if we don't force it, then __cmp__ is called before) - from sage.combinat.words.word import FiniteWord_class - return FiniteWord_class.__eq__(self,other) - elif op == Py_NE: - if isinstance(other, WordDatatype_tuple): + elif op == Py_NE: return self._data != other._data - else: - # Otherwise, force FiniteWord_class.__eq__ to do it - # (if we don't force it, then __cmp__ is called before) - from sage.combinat.words.word import FiniteWord_class - return not FiniteWord_class.__eq__(self,other) - else: - return NotImplemented + + # Otherwise, force FiniteWord_class.__richcmp__ to do it + from sage.combinat.words.word import FiniteWord_class + return FiniteWord_class.__richcmp__(self, other, op) def __len__(self): r""" diff --git a/src/sage/cpython/string.pxd b/src/sage/cpython/string.pxd index d8157669932..eefc2d685ea 100644 --- a/src/sage/cpython/string.pxd +++ b/src/sage/cpython/string.pxd @@ -15,31 +15,33 @@ from libc.string cimport strlen from cpython.bytes cimport PyBytes_AS_STRING, PyBytes_FromString from cpython.unicode cimport PyUnicode_Decode, PyUnicode_AsEncodedString -IF PY_MAJOR_VERSION >= 3: - cdef extern from "Python.h": - # Missing from cpython.unicode in Cython 0.27.3 - char* PyUnicode_AsUTF8(object s) - str PyUnicode_DecodeLocale(const char* s, const char* errors) - bytes PyUnicode_EncodeLocale(object s, const char* errors) + +cdef extern from "Python.h": + # Missing from cpython.unicode in Cython 0.27.3 + char* PyUnicode_AsUTF8(object s) cdef inline str char_to_str(const char* c, encoding=None, errors=None): IF PY_MAJOR_VERSION <= 2: return PyBytes_FromString(c) ELSE: - cdef char* err + cdef const char* err + cdef const char* enc + if errors is None: err = NULL # implies "strict" else: err = PyUnicode_AsUTF8(errors) if encoding is None: - return PyUnicode_DecodeLocale(c, err) + enc = NULL # default to utf-8 + else: + enc = PyUnicode_AsUTF8(encoding) - return PyUnicode_Decode(c, strlen(c), PyUnicode_AsUTF8(encoding), err) + return PyUnicode_Decode(c, strlen(c), enc, err) -cpdef inline bytes_to_str(b, encoding=None, errors=None): +cpdef inline str bytes_to_str(b, encoding=None, errors=None): r""" Convert ``bytes`` to ``str``. @@ -66,49 +68,71 @@ cpdef inline bytes_to_str(b, encoding=None, errors=None): raise TypeError(f"expected bytes, {type(b).__name__} found") IF PY_MAJOR_VERSION <= 2: - return b + return b ELSE: return char_to_str(PyBytes_AS_STRING(b), encoding=encoding, errors=errors) -cpdef inline str_to_bytes(s, encoding=None, errors=None): +cpdef inline bytes str_to_bytes(s, encoding=None, errors=None): r""" - Convert ``str`` to ``bytes``. + Convert ``str`` or ``unicode`` to ``bytes``. + + On Python 3 this encodes the given ``str`` to a Python 3 ``bytes`` + using the specified encoding. - On Python 2 this is a no-op since ``str is bytes``. On Python 3 - this encodes the given ``str`` to a Python 3 ``bytes`` using the - specified encoding. + On Python 2 this is a no-op on ``str`` input since ``str is bytes``. + However, this function also accepts Python 2 ``unicode`` objects and + treats them the same as Python 3 unicode ``str`` objects. EXAMPLES:: sage: import six sage: from sage.cpython.string import str_to_bytes sage: if six.PY2: - ....: b = str_to_bytes('\xcf\x80') + ....: bs = [str_to_bytes('\xcf\x80'), str_to_bytes(u'π')] ....: else: - ....: b = str_to_bytes(u'π') - sage: b == b'\xcf\x80' + ....: bs = [str_to_bytes(u'π')] + sage: all(b == b'\xcf\x80' for b in bs) True sage: str_to_bytes([]) Traceback (most recent call last): ... - TypeError: expected str, list found + TypeError: expected str ... list found """ - # Make this check explicit to avoid obscure error message below - if not isinstance(s, str): - raise TypeError(f"expected str, {type(s).__name__} found") + cdef const char* err + cdef const char* enc IF PY_MAJOR_VERSION <= 2: - return s + # Make this check explicit to avoid obscure error message below + if isinstance(s, str): + # On Python 2 str is already bytes so this should be a no-op + return s + elif not isinstance(s, unicode): + raise TypeError( + f"expected str or unicode, {type(s).__name__} found") + + if errors is None: + err = NULL # implies "strict" + else: + err = errors + + if encoding is None: + enc = 'utf-8' + else: + enc = encoding ELSE: - cdef char* err + if not isinstance(s, str): + raise TypeError(f"expected str, {type(s).__name__} found") + if errors is None: err = NULL # implies "strict" else: err = PyUnicode_AsUTF8(errors) if encoding is None: - return PyUnicode_EncodeLocale(s, err) + enc = NULL # default to utf-8 + else: + enc = PyUnicode_AsUTF8(encoding) - return PyUnicode_AsEncodedString(s, PyUnicode_AsUTF8(encoding), err) + return PyUnicode_AsEncodedString(s, enc, err) diff --git a/src/sage/cpython/string.pyx b/src/sage/cpython/string.pyx index db7164126a7..0cc5e57d68e 100644 --- a/src/sage/cpython/string.pyx +++ b/src/sage/cpython/string.pyx @@ -19,7 +19,7 @@ import sys # Provide this as a shortcut to calling sys.getfilesystemencoding(), which -# after interpeter initialization is constant. +# after interpreter initialization is constant. FS_ENCODING = sys.getfilesystemencoding() # Functions in this module are implemented in the .pxd file for inlining. diff --git a/src/sage/crypto/boolean_function.pyx b/src/sage/crypto/boolean_function.pyx index f3ab09ffd5e..35a1fcc1790 100644 --- a/src/sage/crypto/boolean_function.pyx +++ b/src/sage/crypto/boolean_function.pyx @@ -636,14 +636,14 @@ cdef class BooleanFunction(SageObject): 1 sage: B([1,0]) 1 - sage: B(7) + sage: B(4) Traceback (most recent call last): ... IndexError: index out of bound """ if isinstance(x, (int,long,Integer)): - if x > self._truth_table.size: + if x >= self._truth_table.size: raise IndexError("index out of bound") return bitset_in(self._truth_table,x) elif isinstance(x, list): diff --git a/src/sage/data_structures/blas_dict.pyx b/src/sage/data_structures/blas_dict.pyx index ca2355731e6..5dfa06dbd86 100644 --- a/src/sage/data_structures/blas_dict.pyx +++ b/src/sage/data_structures/blas_dict.pyx @@ -132,7 +132,7 @@ cpdef int iaxpy(a, dict X, dict Y, bint remove_zeros=True, bint factor_on_left=T else: value = value*a if not value: - continue # a is a zero divizor + continue # a is a zero divisor # assert value if key in Y: Y[key] += value diff --git a/src/sage/databases/sql_db.py b/src/sage/databases/sql_db.py index db2b7317d31..a95b3502b92 100644 --- a/src/sage/databases/sql_db.py +++ b/src/sage/databases/sql_db.py @@ -772,7 +772,7 @@ def _merge_queries(self, other, ret, join_table, join_dict, operator): if re.search(pattern, self.__query_string__) \ or re.search(pattern, other.__query_string__): raise TypeError('Input queries have joins but join ' \ - + 'paramaters are NoneType') + + 'parameters are NoneType') s = ((self.__query_string__).upper()).split('FROM ') o = ((other.__query_string__).upper()).split('FROM ') s = s[1].split(' WHERE ') diff --git a/src/sage/databases/stein_watkins.py b/src/sage/databases/stein_watkins.py index 3bf373a1d14..eeb2bcb5981 100644 --- a/src/sage/databases/stein_watkins.py +++ b/src/sage/databases/stein_watkins.py @@ -300,7 +300,7 @@ def iter_levels(self): except StopIteration: if C != []: yield C - raise StopIteration + return if E.conductor != N: if C != []: yield C diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 71088fc9102..8d880c3dd74 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -113,6 +113,51 @@ def remove_unicode_u(string): return string +_type_repr_re = re.compile(r"[^']+)'>") + +def normalize_type_repr(s): + r""" + Convert the repr of type objects (e.g. ``int``, ``float``) from their + Python 2 representation to their Python 3 representation. + + In Python 2, the repr of built-in types like ``int`` is like + ````, whereas user-defined pure Python classes are displayed + as ````. On Python 3 this was normalized so that + built-in types are represented the same as user-defined classes (e.g. + ````. + + This simply normalizes all class/type reprs to the Python 3 convention for + the sake of output checking. + + EXAMPLES:: + + sage: from sage.doctest.parsing import normalize_type_repr + sage: s = "" + sage: normalize_type_repr(s) + "" + sage: normalize_type_repr(repr(float)) + "" + + This can work on multi-line output as well:: + + sage: s = "The desired output was \n" + sage: s += "The received output was " + sage: print(normalize_type_repr(s)) + The desired output was + The received output was + + And should work when types are embedded in other nested expressions:: + + sage: normalize_type_repr(repr([Integer, float])) + "[, ]" + """ + + def subst(m): + return "".format(m.group('name')) + + return _type_repr_re.sub(subst, s) + + def parse_optional_tags(string): """ Returns a set consisting of the optional tags from the following @@ -879,6 +924,14 @@ def check_output(self, want, got, optionflags): [u'Fermat', u'Euler'] sage: c = u'you'; c u'you' + + Also allowance for the difference in reprs of ``type`` instances (i.e. + classes) between Python 2 and Python 3:: + + sage: int + + sage: float + """ got = self.human_readable_escape_sequences(got) if isinstance(want, MarkedOutput): @@ -904,13 +957,33 @@ def check_output(self, want, got, optionflags): return all(a.overlaps(b) for a, b in zip(want_intervals, got_values)) ok = doctest.OutputChecker.check_output(self, want, got, optionflags) - if ok or ('u"' not in want and "u'" not in want): + + if ok: return ok - # accept the same answer where strings have unicode prefix u - # for smoother transition to python3 - if not six.PY2: - want = remove_unicode_u(want) + # Possibly fix up the desired output to account for the difference in + # reprs of some objects between Python 2 and Python 3 + # Since most of the tests are currently written for Python 2 the only + # fixups we perform right now are on Python 3 + if six.PY2: + repr_fixups = [] + else: + repr_fixups = [ + (lambda g, w: 'u"' in w or "u'" in w, remove_unicode_u), + (lambda g, w: ' vertices[-1][0]: return vertices[-1][1] + lastslope * (x - vertices[-1][0]) - a = 0; b = len(vertices) + a = 0 + b = len(vertices) while b - a > 1: - c = floor((a+b)/2) + c = (a + b) // 2 if vertices[c][0] < x: a = c else: diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index f94b3ffaf6a..3f47e629064 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -23,6 +23,7 @@ from sage.misc.all import cached_method, prod from sage.misc.package import is_package_installed, PackageNotFoundError +from sage.misc.randstate import current_randstate from sage.rings.all import QQ, ZZ, AA from sage.rings.real_double import RDF @@ -38,6 +39,8 @@ from sage.misc.superseded import deprecated_function_alias +from sage.categories.sets_cat import EmptySetError + ######################################################################### # Notes if you want to implement your own backend: # @@ -3085,7 +3088,7 @@ def dilation(self, scalar): TESTS: - Dilation of empty polyhedrons works, see :trac:`14987`:: + Dilation of empty polyhedra works, see :trac:`14987`:: sage: p = Polyhedron(ambient_dim=2); p The empty polyhedron in ZZ^2 @@ -5315,6 +5318,157 @@ def integral_points(self, threshold=100000): # assert all(self.contains(p) for p in points) # slow return tuple(points) + def get_integral_point(self, index, **kwds): + r""" + Return the ``index``-th integral point in this polyhedron. + + This is equivalent to ``sorted(self.integral_points())[index]``. + However, so long as self.integral_points_count() does not need to + enumerate all integral points, neither does this method. Hence it can + be significantly faster. If the polyhedron is not compact, a + ``ValueError`` is raised. + + INPUT: + + - ``index`` -- integer. The index of the integral point to be found. If + this is not in [0, ``self.integral_point_count()``), an ``IndexError`` + is raised. + + - ``**kwds`` -- optional keyword parameters that are passed to + :meth:`self.integral_points_count`. + + ALGORITHM: + + The function computes each of the components of the requested point in + turn. To compute x_i, the ith component, it bisects the upper and lower + bounds on x_i given by the bounding box. At each bisection, it uses + :meth:`integral_points_count` to determine on which side of the + bisecting hyperplane the requested point lies. + + .. SEEALSO:: + + :meth:`integral_points_count`. + + EXAMPLES:: + + sage: P = Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)]) + sage: P.get_integral_point(1) + (0, 0) + sage: P.get_integral_point(4) + (1, 1) + sage: sorted(P.integral_points()) + [(-1, -1), (0, 0), (0, 1), (1, 0), (1, 1)] + sage: P.get_integral_point(5) + Traceback (most recent call last): + ... + IndexError: ... + + sage: Q = Polyhedron([(1,3), (2, 7), (9, 77)]) + sage: [Q.get_integral_point(i) for i in range(Q.integral_points_count())] == sorted(Q.integral_points()) + True + sage: Q.get_integral_point(0, explicit_enumeration_threshold=0, triangulation='cddlib') # optional - latte_int + (1, 3) + sage: Q.get_integral_point(0, explicit_enumeration_threshold=0, triangulation='cddlib', foo=True) # optional - latte_int + Traceback (most recent call last): + ... + RuntimeError: ... + + sage: R = Polyhedron(vertices=[[1/2, 1/3]], rays=[[1, 1]]) + sage: R.get_integral_point(0) + Traceback (most recent call last): + ... + ValueError: ... + """ + + if not self.is_compact(): + raise ValueError('Can only enumerate points in a compact polyhedron.') + + if not 0 <= index < self.integral_points_count(**kwds): + raise IndexError('polytope index out of range') + + D = self.ambient_dim() + lower_bounds, upper_bounds = self.bounding_box() + coordinate = [] + P = self + S = self.parent() + for i in range(D): # Now compute x_i, the ith component of coordinate. + lower, upper = ceil(lower_bounds[i]), floor(upper_bounds[i]) + 1 # So lower <= x_i < upper. + while lower < upper-1: + guess = (lower + upper) // 2 # > lower. + # Build new polyhedron by intersecting P with the halfspace {x_i < guess}. + P_lt_guess = P.intersection(S(None, ([[guess-1] + [0] * i + [-1] + [0] * (D - i - 1)], []))) + # Avoid computing P_geq_guess = P.intersection({x_i >= guess}) right now, it might not be needed. + P_lt_guess_count = P_lt_guess.integral_points_count(**kwds) + if P_lt_guess_count > index: # Move upper down to guess. + upper = guess + index -= 0 + P = P_lt_guess + else: # P_lt_guess_count <= index: # Move lower up to guess. + lower = guess + index -= P_lt_guess_count + P_geq_guess = P.intersection(S(None, ([[-guess] + [0] * i + [1] + [0] * (D - i - 1)], []))) + P = P_geq_guess + coordinate.append(lower) # Record the new component that we have found. + point = vector(ZZ, coordinate) + point.set_immutable() + return point + + def random_integral_point(self, **kwds): + r""" + Return an integral point in this polyhedron chosen uniformly at random. + + INPUT: + + - ``**kwds`` -- optional keyword parameters that are passed to + :meth:`self.get_integral_point`. + + OUTPUT: + + The integral point in the polyhedron chosen uniformly at random. If the + polyhedron is not compact, a ``ValueError`` is raised. If the + polyhedron does not contain any integral points, an ``EmptySetError`` is + raised. + + .. SEEALSO:: + + :meth:`get_integral_point`. + + EXAMPLES:: + + sage: P = Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)]) + sage: P.random_integral_point() # random + (0, 0) + sage: P.random_integral_point() in P.integral_points() + True + sage: P.random_integral_point(explicit_enumeration_threshold=0, triangulation='cddlib') # random, optional - latte_int + (1, 1) + sage: P.random_integral_point(explicit_enumeration_threshold=0, triangulation='cddlib', foo=7) # optional - latte_int + Traceback (most recent call last): + ... + RuntimeError: ... + + sage: Q = Polyhedron(vertices=[(2, 1/3)], rays=[(1, 2)]) + sage: Q.random_integral_point() + Traceback (most recent call last): + ... + ValueError: ... + + sage: R = Polyhedron(vertices=[(1/2, 0), (1, 1/2), (0, 1/2)]) + sage: R.random_integral_point() + Traceback (most recent call last): + ... + EmptySetError: ... + """ + + if not self.is_compact(): + raise ValueError('Can only sample integral points in a compact polyhedron.') + + count = self.integral_points_count() + if count == 0: + raise EmptySetError('Polyhedron does not contain any integral points.') + + return self.get_integral_point(current_randstate().python_random().randint(0, count-1), **kwds) + @cached_method def combinatorial_automorphism_group(self, vertex_graph_only=False): """ diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index 2a51bf6540e..03092097093 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -1243,18 +1243,28 @@ def render_3d(self, point_opts={}, line_opts={}, polygon_opts={}): Graphics3d Object sage: Polyhedron(vertices=[[1,1,1]]).plot() # point in R^3 Graphics3d Object + + The origin is not included, if it is not in the polyhedron (:trac:`23555`):: + + sage: Q = Polyhedron([[100],[101]]) + sage: P = Q*Q*Q; P + A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices + sage: p = P.plot() + sage: p.bounding_box() + ((100.0, 100.0, 100.0), (101.0, 101.0, 101.0)) """ - from sage.plot.plot3d.base import Graphics3d - plt = Graphics3d() + pplt = None + lplt = None + pgplt = None if isinstance(point_opts, dict): point_opts.setdefault('width', 3) - plt += self.render_vertices_3d(**point_opts) + pplt = self.render_vertices_3d(**point_opts) if isinstance(line_opts, dict): line_opts.setdefault('width', 3) - plt += self.render_wireframe_3d(**line_opts) + lplt = self.render_wireframe_3d(**line_opts) if isinstance(polygon_opts, dict): - plt += self.render_solid_3d(**polygon_opts) - return plt + pgplt = self.render_solid_3d(**polygon_opts) + return sum(_ for _ in [pplt, lplt, pgplt] if _ != None) def tikz(self, view=[0, 0, 1], angle=0, scale=2, edge_color='blue!95!black', facet_color='blue!95!black', diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py index 019bff803e2..e8084b221b3 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py @@ -363,7 +363,7 @@ def is_isomorphic(self, polytope): def sub_polytopes(self): """ - Returns a list of all lattice sub-polygons up to isomorphsm. + Return a list of all lattice sub-polygons up to isomorphism. OUTPUT: diff --git a/src/sage/geometry/pseudolines.py b/src/sage/geometry/pseudolines.py index 27a6dcb2f74..9e69bdba70c 100644 --- a/src/sage/geometry/pseudolines.py +++ b/src/sage/geometry/pseudolines.py @@ -265,7 +265,7 @@ def __init__(self, seq, encoding = "auto"): seq = deepcopy(seq) self._n = len(seq) - ordering = range(self._n) + ordering = list(range(self._n)) self._permutations = [[] for i in range(self._n)] diff --git a/src/sage/geometry/toric_plotter.py b/src/sage/geometry/toric_plotter.py index 867b3b0b419..8c9204a2dba 100644 --- a/src/sage/geometry/toric_plotter.py +++ b/src/sage/geometry/toric_plotter.py @@ -979,9 +979,11 @@ def options(option=None, **kwds): - ``font_size`` -- an integer, the size of font used for labels; - - ``ray_label`` -- a string or a list of strings used for ray labels; + - ``ray_label`` -- a string or a list of strings used for ray labels; use + ``None`` to hide labels; - - ``wall_label`` -- a string or a list of strings used for wall labels; + - ``wall_label`` -- a string or a list of strings used for wall labels; use + ``None`` to hide labels; - ``radius`` -- a positive number, the radius of the cut-off region for "round" mode; diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 74c4518d079..f84d2d42d93 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -661,7 +661,7 @@ def _TOPCOM_exec(cls, executable, input_string, verbose=True): yield line.strip() except GeneratorExit: proc.close(force=True) - raise StopIteration + return if verbose: print("#######################") diff --git a/src/sage/graphs/centrality.pyx b/src/sage/graphs/centrality.pyx index c5c9d355eff..67db9819d8d 100644 --- a/src/sage/graphs/centrality.pyx +++ b/src/sage/graphs/centrality.pyx @@ -233,7 +233,7 @@ cdef dict centrality_betweenness_C(G, numerical_type _, normalize=True): for j in range(layer_current_beginning,layer_current_end): u = queue[j] - # List the neighors of u + # List the neighbors of u p_tmp = g.neighbors[u] while p_tmp n*n: good_input = False - elif m > n*n/2: + elif 2*m > n*n: is_dense = True m = n*n - m else: if m > n*(n-1): good_input = False - elif m > n*(n-1)/2: + elif m > (n * (n - 1)) // 2: is_dense = True m = n*(n-1) - m diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 8777b95c4be..e108f2d57f9 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -237,24 +237,22 @@ def CycleGraph(n): r""" Returns a cycle graph with n nodes. - A cycle graph is a basic structure which is also typically called - an n-gon. + A cycle graph is a basic structure which is also typically called an + `n`-gon. - PLOTTING: Upon construction, the position dictionary is filled to - override the spring-layout algorithm. By convention, each cycle - graph will be displayed with the first (0) node at the top, with - the rest following in a counterclockwise manner. + PLOTTING: Upon construction, the position dictionary is filled to override + the spring-layout algorithm. By convention, each cycle graph will be + displayed with the first (0) node at the top, with the rest following in a + counterclockwise manner. - The cycle graph is a good opportunity to compare efficiency of - filling a position dictionary vs. using the spring-layout algorithm - for plotting. Because the cycle graph is very symmetric, the - resulting plots should be similar (in cases of small n). + The cycle graph is a good opportunity to compare efficiency of filling a + position dictionary vs. using the spring-layout algorithm for + plotting. Because the cycle graph is very symmetric, the resulting plots + should be similar (in cases of small `n`). - Filling the position dictionary in advance adds O(n) to the - constructor. + Filling the position dictionary in advance adds `O(n)` to the constructor. - EXAMPLES: Compare plotting using the predefined layout and - networkx:: + EXAMPLES: Compare plotting using the predefined layout and networkx:: sage: import networkx sage: n = networkx.cycle_graph(23) @@ -263,9 +261,8 @@ def CycleGraph(n): sage: spring23.show() # long time sage: posdict23.show() # long time - We next view many cycle graphs as a Sage graphics array. First we - use the ``CycleGraph`` constructor, which fills in the - position dictionary:: + We next view many cycle graphs as a Sage graphics array. First we use the + ``CycleGraph`` constructor, which fills in the position dictionary:: sage: g = [] sage: j = [] @@ -295,14 +292,33 @@ def CycleGraph(n): ....: j.append(n) sage: G = sage.plot.graphics.GraphicsArray(j) sage: G.show() # long time + + TESTS: + + The input parameter must be a positive integer:: + + sage: G = graphs.CycleGraph(-1) + Traceback (most recent call last): + ... + ValueError: parameter n must be a positive integer """ - pos_dict = {} - for i in range(n): - x = float(cos((pi/2) + ((2*pi)/n)*i)) - y = float(sin((pi/2) + ((2*pi)/n)*i)) - pos_dict[i] = (x, y) - G = graph.Graph(n, pos=pos_dict, name="Cycle graph") - G.add_cycle(list(range(n))) + if n < 0: + raise ValueError("parameter n must be a positive integer") + + G = Graph(n, name="Cycle graph") + if n == 1: + G.set_pos({0:(0, 0)}) + elif n == 2: + G.add_edge(0, 1) + G.set_pos({0:(0, 1), 1:(0, -1)}) + else: + pos_dict = {} + for i in range(n): + x = float(cos((pi/2) + ((2*pi)/n)*i)) + y = float(sin((pi/2) + ((2*pi)/n)*i)) + pos_dict[i] = (x, y) + G.set_pos(pos_dict) + G.add_cycle(list(range(n))) return G def CompleteGraph(n): diff --git a/src/sage/graphs/generators/chessboard.py b/src/sage/graphs/generators/chessboard.py index c902f369e61..4d4b9e3c6be 100644 --- a/src/sage/graphs/generators/chessboard.py +++ b/src/sage/graphs/generators/chessboard.py @@ -84,7 +84,7 @@ def ChessboardGraphGenerator(dim_list, sage: G.is_isomorphic( graphs.CompleteGraph(4) ) True - A Rook's Graph in 2 dimensions is isomporphic to the Cartesian product of 2 + A Rook's Graph in 2 dimensions is isomorphic to the Cartesian product of 2 complete graphs:: sage: G, _ = graphs.ChessboardGraphGenerator( [3,4], rook=True, rook_radius=None, bishop=False, knight=False ) diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 8a3f67170ce..0c036ac22ee 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -49,9 +49,7 @@ def SymplecticPolarGraph(d, q, algorithm=None): Computation of the spectrum of `Sp(6,2)`:: - sage: g = graphs.SymplecticGraph(6,2) - doctest:...: DeprecationWarning: SymplecticGraph is deprecated. Please use sage.graphs.generators.classical_geometries.SymplecticPolarGraph instead. - See http://trac.sagemath.org/19136 for details. + sage: g = graphs.SymplecticPolarGraph(6,2) sage: g.is_strongly_regular(parameters=True) (63, 30, 13, 15) sage: set(g.spectrum()) == {-5, 3, 30} @@ -112,8 +110,6 @@ def SymplecticPolarGraph(d, q, algorithm=None): G.relabel() return G -from sage.misc.superseded import deprecated_function_alias -SymplecticGraph = deprecated_function_alias(19136, SymplecticPolarGraph) def AffineOrthogonalPolarGraph(d,q,sign="+"): r""" diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 103f487933d..131ef8f5028 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2478,24 +2478,22 @@ def WheelGraph(n): """ Returns a Wheel graph with n nodes. - A Wheel graph is a basic structure where one node is connected to - all other nodes and those (outer) nodes are connected cyclically. + A Wheel graph is a basic structure where one node is connected to all other + nodes and those (outer) nodes are connected cyclically. - This constructor depends on NetworkX numeric labels. + PLOTTING: Upon construction, the position dictionary is filled to override + the spring-layout algorithm. By convention, each wheel graph will be + displayed with the first (0) node in the center, the second node at the top, + and the rest following in a counterclockwise manner. - PLOTTING: Upon construction, the position dictionary is filled to - override the spring-layout algorithm. By convention, each wheel - graph will be displayed with the first (0) node in the center, the - second node at the top, and the rest following in a - counterclockwise manner. + With the wheel graph, we see that it doesn't take a very large n at all for + the spring-layout to give a counter-intuitive display. (See Graphics Array + examples below). - With the wheel graph, we see that it doesn't take a very large n at - all for the spring-layout to give a counter-intuitive display. (See - Graphics Array examples below). + EXAMPLES: - EXAMPLES: We view many wheel graphs with a Sage Graphics Array, - first with this constructor (i.e., the position dictionary - filled):: + We view many wheel graphs with a Sage Graphics Array, first with this + constructor (i.e., the position dictionary filled):: sage: g = [] sage: j = [] @@ -2539,15 +2537,16 @@ def WheelGraph(n): sage: spring23.show() # long time sage: posdict23.show() # long time """ - pos_dict = {} - pos_dict[0] = (0,0) - for i in range(1,n): - x = float(cos((pi/2) + ((2*pi)/(n-1))*(i-1))) - y = float(sin((pi/2) + ((2*pi)/(n-1))*(i-1))) - pos_dict[i] = (x,y) - import networkx - G = networkx.wheel_graph(n) - return Graph(G, pos=pos_dict, name="Wheel graph") + from sage.graphs.generators.basic import CycleGraph + if n < 4: + G = CycleGraph(n) + else: + G = CycleGraph(n-1) + G.relabel(perm=list(range(1, n)), inplace=True) + G.add_edges([(0, i) for i in range(1, n)]) + G._pos[0] = (0, 0) + G.name("Wheel graph") + return G def WindmillGraph(k, n): r""" diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index 0428f69ee5b..bf86674d765 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -4902,7 +4902,7 @@ def JankoKharaghaniGraph(v): q = m*t+1 K = GF(q,'alpha') a = K.primitive_element() - Ci= [[K(0)]] + map(set,[[a**(k*j+i) for j in range(t)] for i in range(m)]) + Ci= [[K(0)]] + [set(a**(k*j+i) for j in range(t)) for i in range(m)] Kelem_to_Ci = {v:i for i,s in enumerate(Ci) for v in s} # maps v to [0,...,12] W = ([[0]+ [1]*(len(K))] + diff --git a/src/sage/graphs/generators/world_map.py b/src/sage/graphs/generators/world_map.py index 39e48d50d16..3dc1b6977f5 100644 --- a/src/sage/graphs/generators/world_map.py +++ b/src/sage/graphs/generators/world_map.py @@ -18,6 +18,83 @@ # import from Sage library from sage.graphs.graph import Graph +def AfricaMap(continental=False, year=2018): + """ + Return African states as a graph of common border. + + "African state" here is defined as an independent + state having the capital city in Africa. The graph + has an edge between those countries that have common + *land* border. + + INPUT: + + - ``continental``, a Boolean -- if set, only return states in + the continental Africa + - ``year`` -- reserved for future use + + EXAMPLES:: + + sage: Africa = graphs.AfricaMap(); Africa + Africa Map: Graph on 54 vertices + sage: sorted(Africa.neighbors('Libya')) + ['Algeria', 'Chad', 'Egypt', 'Niger', 'Sudan', 'Tunisia'] + + sage: cont_Africa = graphs.AfricaMap(continental=True) + sage: cont_Africa.order() + 48 + sage: 'Madagaskar' in cont_Africa + False + """ + if year != 2018: + raise ValueError("currently only year 2018 is implemented") + + common_border = { + 'Algeria': ['Libya', 'Mali', 'Mauritania', 'Morocco', 'Niger', 'Tunisia'], + 'Angola': ['Namibia', 'Zambia'], + 'Benin': ['Burkina Faso', 'Niger', 'Nigeria', 'Togo'], + 'Botswana': ['Namibia', 'South Africa', 'Zimbabwe'], + 'Burkina Faso': ['Ghana', 'Ivory Coast', 'Mali', 'Niger', 'Togo'], + 'Cameroon': ['Central Africa', 'Chad', 'Equatorial Guinea', 'Gabon', 'Nigeria'], + 'Central Africa': ['Chad', 'South Sudan', 'Sudan'], + 'Chad': ['Libya', 'Niger', 'Nigeria', 'Sudan'], + 'Republic of the Congo': ['Gabon', 'Cameroon', 'Central Africa', 'Angola', + 'Democratic Republic of the Congo'], + 'Democratic Republic of the Congo': ['Zambia', 'South Sudan', 'Tanzania', 'Burundi', + 'Rwanda', 'Uganda', 'Central Africa', 'Angola'], + 'Djibouti': ['Eritrea', 'Ethiopia', 'Somalia'], + 'Ethiopia': ['Eritrea', 'Kenya', 'Somalia', 'South Sudan', 'Sudan'], + 'Gabon': ['Equatorial Guinea'], + 'Ghana': ['Ivory Coast', 'Togo'], + 'Guinea': ['Guinea-Bissau', 'Ivory Coast', 'Liberia', 'Sierra Leone'], + 'Kenya': ['Somalia', 'South Sudan', 'Tanzania', 'Uganda'], + 'Liberia': ['Ivory Coast', 'Sierra Leone'], + 'Libya': ['Egypt', 'Niger', 'Sudan', 'Tunisia'], + 'Mali': ['Guinea', 'Ivory Coast', 'Mauritania', 'Niger', 'Senegal'], + 'Mozambique': ['Malawi', 'South Africa', 'Swaziland', 'Zimbabwe'], + 'Niger': ['Nigeria'], + 'Rwanda': ['Burundi', 'Tanzania', 'Uganda'], + 'Senegal': ['Guinea', 'Guinea-Bissau', 'Mauritania', 'Gambia'], + 'South Africa': ['Lesotho', 'Namibia', 'Swaziland', 'Zimbabwe'], + 'South Sudan': ['Uganda', 'Sudan', 'Democratic Republic of the Congo'], + 'Sudan': ['Egypt', 'Eritrea'], + 'Tanzania': ['Burundi', 'Malawi', 'Mozambique', 'Uganda', 'Zambia'], + 'Zambia': ['Malawi', 'Mozambique', 'Namibia', 'Zimbabwe'] + } + + no_land_border = ['Cape Verde', 'Seychelles', 'Mauritius', 'S\xc3\xa3o Tom\xc3\xa9 and Pr\xc3\xadncipe', 'Madagascar', 'Comoros'] + + G = Graph(common_border, format='dict_of_lists') + + if continental: + G = G.subgraph(G.connected_component_containing_vertex('Central Africa')) + G.name(new="Continental Africa Map") + else: + G.add_vertices(no_land_border) + G.name(new="Africa Map") + + return G + def EuropeMap(continental=False, year=2018): """ Return European states as a graph of common border. diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 6cfe42a0952..70b38e2c45c 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -312,7 +312,7 @@ :meth:`~GenericGraph.subgraph_search_iterator` | Return an iterator over the labelled copies of ``G`` in ``self``. :meth:`~GenericGraph.characteristic_polynomial` | Return the characteristic polynomial of the adjacency matrix of the (di)graph. :meth:`~GenericGraph.genus` | Return the minimal genus of the graph. - :meth:`~GenericGraph.crossing_number` | Return the minimun number of edge crossings needed to draw the graph. + :meth:`~GenericGraph.crossing_number` | Return the minimum number of edge crossings needed to draw the graph. Methods ------- @@ -1532,7 +1532,7 @@ def to_dictionary(self, edge_labels=False, multiple_edges=False): .. NOTE:: When used on directed graphs, the explanations above can be understood - by replacing the word "neigbours" by "out-neighbors" + by replacing the word "neighbors" by "out-neighbors" EXAMPLES:: @@ -4892,7 +4892,7 @@ def crossing_number(self): """ Return the crossing number of the graph. - The crossing number of a graph is the minimun number of + The crossing number of a graph is the minimum number of edge crossings needed to draw the graph on a plane. It can be seen as a measure of non-planarity; a planar graph has crossing number zero. @@ -9125,7 +9125,7 @@ def disjoint_routed_paths(self,pairs, solver=None, verbose=0): Given a set of pairs `(s_i,t_i)`, a set of disjoint routed paths is a set of - `s_i-t_i` paths which can interset at their endpoints + `s_i-t_i` paths which can intersect at their endpoints and are vertex-disjoint otherwise. INPUT: @@ -14743,7 +14743,16 @@ def center(self, by_weight=False, algorithm=None, weight_function=None, - ``check_weight`` (boolean) - if ``True``, we check that the weight_function outputs a number for each edge. - EXAMPLES:: + EXAMPLES: + + Is Central African Republic in the center of Africa in graph theoretic + sense? Yes:: + + sage: A = graphs.AfricaMap(continental=True) + sage: sorted(A.center()) + ['Cameroon', 'Central Africa'] + + Some other graphs. Center can be the whole graph:: sage: G = graphs.DiamondGraph() sage: G.center() @@ -14754,6 +14763,9 @@ def center(self, by_weight=False, algorithm=None, weight_function=None, sage: S = graphs.StarGraph(19) sage: S.center() [0] + + TESTS:: + sage: G = Graph() sage: G.center() [] diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx index cce996ed280..f31e6e2b743 100644 --- a/src/sage/graphs/generic_graph_pyx.pyx +++ b/src/sage/graphs/generic_graph_pyx.pyx @@ -31,6 +31,7 @@ include "sage/data_structures/binary_matrix.pxi" from libc.math cimport sqrt, fabs from libc.string cimport memset +from sage.cpython.string cimport char_to_str from sage.libs.gmp.mpz cimport * from sage.misc.prandom import random from sage.ext.memory_allocator cimport MemoryAllocator @@ -398,10 +399,11 @@ def int_to_binary_string(n): '11111010111' """ cdef mpz_t i + cdef char* s mpz_init(i) - mpz_set_ui(i,n) - cdef char* s=mpz_get_str(NULL, 2, i) - t=str(s) + mpz_set_ui(i, n) + s = mpz_get_str(NULL, 2, i) + t = char_to_str(s) sig_free(s) mpz_clear(i) return t diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index ebcfa88dd7d..852e8a06dc9 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -3379,7 +3379,7 @@ def is_semi_symmetric(self): """ Returns true if self is semi-symmetric. - A graph is semi-symmetric if it is regular, edge-transitve but not + A graph is semi-symmetric if it is regular, edge-transitive but not vertex-transitive. See :wikipedia:`the wikipedia article on semi-symmetric graphs diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 751d19d1833..b3ec5ac8ef1 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -15,7 +15,7 @@ More interestingly, one can get the list of all graphs that Sage knows how to build by typing ``graphs.`` in Sage and then hitting tab. """ -from __future__ import print_function, absolute_import +from __future__ import print_function, absolute_import, division from six.moves import range # This method appends a list of methods to the doc as a 3xN table. @@ -336,7 +336,8 @@ def __append_to_doc(methods): __append_to_doc( ["WorldMap", - "EuropeMap"] + "EuropeMap", + "AfricaMap"] ) __doc__ += """ @@ -858,7 +859,7 @@ def nauty_geng(self, options="", debug=False): sage: next(gen) Traceback (most recent call last): ... - StopIteration: Exhausted list of graphs from nauty geng + StopIteration A list of all graphs on 7 vertices. This agrees with :oeis:`A000088`. :: @@ -895,7 +896,8 @@ def nauty_geng(self, options="", debug=False): try: s = next(gen) except StopIteration: - raise StopIteration("Exhausted list of graphs from nauty geng") + # Exhausted list of graphs from nauty geng + return G = graph.Graph(s[:-1], format='graph6') yield G @@ -2045,7 +2047,6 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None NonisotropicUnitaryPolarGraph = staticmethod(sage.graphs.generators.classical_geometries.NonisotropicUnitaryPolarGraph) OrthogonalPolarGraph = staticmethod(sage.graphs.generators.classical_geometries.OrthogonalPolarGraph) SymplecticDualPolarGraph = staticmethod(sage.graphs.generators.classical_geometries.SymplecticDualPolarGraph) - SymplecticGraph = staticmethod(sage.graphs.generators.classical_geometries.SymplecticGraph) SymplecticPolarGraph = staticmethod(sage.graphs.generators.classical_geometries.SymplecticPolarGraph) TaylorTwographDescendantSRG = \ staticmethod(sage.graphs.generators.classical_geometries.TaylorTwographDescendantSRG) @@ -2106,6 +2107,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None import sage.graphs.generators.world_map WorldMap = staticmethod(sage.graphs.generators.world_map.WorldMap) EuropeMap = staticmethod(sage.graphs.generators.world_map.EuropeMap) + AfricaMap = staticmethod(sage.graphs.generators.world_map.AfricaMap) ########################################################################### # Degree Sequence @@ -2231,7 +2233,7 @@ def canaug_traverse_vert(g, aut_gens, max_verts, property, dig=False, loops=Fals edges = [] if dig: index = 0 - while index < possibilities/2: + while 2 * index < possibilities: if (1 << index)&i: edges.append((index,n)) index += 1 diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py index d131b56a1c8..658c5c0bb90 100644 --- a/src/sage/graphs/hypergraph_generators.py +++ b/src/sage/graphs/hypergraph_generators.py @@ -150,7 +150,8 @@ def nauty(self, number_of_sets, number_of_vertices, try: s = next(gen) except StopIteration: - raise StopIteration("Exhausted list of graphs from nauty geng") + # Exhausted list of graphs from nauty geng + return from sage.graphs.graph import Graph G = Graph(s[:-1], format='graph6') diff --git a/src/sage/graphs/linearextensions.py b/src/sage/graphs/linearextensions.py index f5368aeb1bb..113a2cd731d 100644 --- a/src/sage/graphs/linearextensions.py +++ b/src/sage/graphs/linearextensions.py @@ -93,16 +93,16 @@ def __init__(self, dag): #Pruesse and Ruskey while dag_copy.num_verts() != 0: #Find all the minimal elements of dag_copy - minimial_elements = [] + minimal_elements = [] for node in dag_copy.vertices(): if len(dag_copy.incoming_edges(node)) == 0: - minimial_elements.append(node) - if len(minimial_elements) == 1: - le.append(minimial_elements[0]) - dag_copy.delete_vertex(minimial_elements[0]) + minimal_elements.append(node) + if len(minimal_elements) == 1: + le.append(minimal_elements[0]) + dag_copy.delete_vertex(minimal_elements[0]) else: - ap = minimial_elements[0] - bp = minimial_elements[1] + ap = minimal_elements[0] + bp = minimal_elements[1] a.append(ap) b.append(bp) le.append(ap) diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index 7da68c8977a..f7dea6add46 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1649,9 +1649,8 @@ def is_switch_OA_srg(int v, int k, int l, int mu): not orthogonal_array(c+1,n,existence=True,resolvable=True)): return None - def switch_OA_srg(c,n): - from builtins import zip - OA = map(tuple,orthogonal_array(c+1,n,resolvable=True)) + def switch_OA_srg(c, n): + OA = map(tuple, orthogonal_array(c+1, n, resolvable=True)) g = Graph([OA, lambda x,y: any(xx==yy for xx,yy in zip(x,y))], loops=False) g.add_vertex(0) @@ -1660,6 +1659,7 @@ def is_switch_OA_srg(int v, int k, int l, int mu): return (switch_OA_srg,c,n) + def is_nowhere0_twoweight(int v, int k, int l, int mu): r""" Test whether some graph of nowhere 0 words is `(v,k,\lambda,\mu)`-strongly regular. @@ -2343,7 +2343,7 @@ def SRG_280_117_44_52(): """ from sage.graphs.hypergraph_generators import hypergraphs - # V is the set of partions {{a,b,c},{d,e,f},{g,h,i}} of {0,...,8} + # V is the set of partitions {{a,b,c},{d,e,f},{g,h,i}} of {0,...,8} H = hypergraphs.CompleteUniform(9,3) g = H.intersection_graph() V = g.complement().cliques_maximal() diff --git a/src/sage/groups/abelian_gps/abelian_group_morphism.py b/src/sage/groups/abelian_gps/abelian_group_morphism.py index c7d4688bc05..725adaf9c75 100644 --- a/src/sage/groups/abelian_gps/abelian_group_morphism.py +++ b/src/sage/groups/abelian_gps/abelian_group_morphism.py @@ -1,11 +1,11 @@ """ Homomorphisms of abelian groups -TODO: +.. TODO:: -- there must be a homspace first + - there must be a homspace first -- there should be hom and Hom methods in abelian group + - there should be hom and Hom methods in abelian group AUTHORS: @@ -28,8 +28,10 @@ from sage.misc.all import prod + def is_AbelianGroupMorphism(f): - return isinstance(f, AbelianGroupMorphism); + return isinstance(f, AbelianGroupMorphism) + class AbelianGroupMap(Morphism): """ @@ -44,6 +46,7 @@ def __init__(self, parent): def _repr_type(self): return "AbelianGroup" + class AbelianGroupMorphism_id(AbelianGroupMap): """ Return the identity homomorphism from X to itself. @@ -54,7 +57,8 @@ def __init__(self, X): AbelianGroupMorphism.__init__(self, X.Hom(X)) def _repr_defn(self): - return "Identity map of "+str(X) + return "Identity map of " + str(X) + class AbelianGroupMorphism(Morphism): """ @@ -72,11 +76,17 @@ class AbelianGroupMorphism(Morphism): Multiplicative Abelian group isomorphic to C2 x C3 sage: x,y = H.gens() - :: - sage: from sage.groups.abelian_gps.abelian_group_morphism import AbelianGroupMorphism sage: phi = AbelianGroupMorphism(H,G,[x,y],[a,b]) + TESTS:: + + sage: G. = AbelianGroup(2,[2,3]) + sage: H. = AbelianGroup(3,[2,3,4]) + sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) + sage: Hom(G,H) == phi.parent() + True + AUTHORS: - David Joyner (2006-02) @@ -100,11 +110,11 @@ class AbelianGroupMorphism(Morphism): # raise TypeError, "Sorry, the list %s must generate G."%genss #TypeError: Sorry, the list [a*b, c^2] must generate G. - def __init__(self, G, H, genss, imgss ): + def __init__(self, G, H, genss, imgss): from sage.categories.homset import Hom Morphism.__init__(self, Hom(G, H)) if len(genss) != len(imgss): - raise TypeError("Sorry, the lengths of %s, %s must be equal."%(genss,imgss)) + raise TypeError("Sorry, the lengths of %s, %s must be equal." % (genss, imgss)) self._domain = G self._codomain = H if not(G.is_abelian()): @@ -113,14 +123,14 @@ def __init__(self, G, H, genss, imgss ): raise TypeError("Sorry, the groups must be abelian groups.") G_domain = G.subgroup(genss) if G_domain.order() != G.order(): - raise TypeError("Sorry, the list %s must generate G."%genss) + raise TypeError("Sorry, the list %s must generate G." % genss) # self.domain_invs = G.gens_orders() # self.codomaininvs = H.gens_orders() self.domaingens = genss self.codomaingens = imgss for i in range(len(self.domaingens)): if (self.domaingens[i]).order() != (self.codomaingens[i]).order(): - raise TypeError("Sorry, the orders of the corresponding elements in %s, %s must be equal."%(genss,imgss)) + raise TypeError("Sorry, the orders of the corresponding elements in %s, %s must be equal." % (genss, imgss)) def _gap_init_(self): """ @@ -140,22 +150,22 @@ def _gap_init_(self): """ G = (self.domain())._gap_init_() H = (self.codomain())._gap_init_() - s3 = 'G:=%s; H:=%s'%(G,H) + s3 = 'G:=%s; H:=%s' % (G, H) gap.eval(s3) - gensG = self.domain().variable_names() ## the Sage group generators + gensG = self.domain().variable_names() # the Sage group generators gensH = self.codomain().variable_names() - s1 = "gensG := GeneratorsOfGroup(G)" ## the GAP group generators + s1 = "gensG := GeneratorsOfGroup(G)" # the GAP group generators gap.eval(s1) s2 = "gensH := GeneratorsOfGroup(H)" gap.eval(s2) - for i in range(len(gensG)): ## making the Sage group gens - cmd = ("%s := gensG["+str(i+1)+"]")%gensG[i] ## correspond to the Sage group gens + for i in range(len(gensG)): # making the Sage group gens + cmd = ("%s := gensG["+str(i+1)+"]") % gensG[i] # correspond to the Sage group gens gap.eval(cmd) for i in range(len(gensH)): - cmd = ("%s := gensH["+str(i+1)+"]")%gensH[i] + cmd = ("%s := gensH[" + str(i + 1) + "]") % gensH[i] gap.eval(cmd) - args = str(self.domaingens)+","+ str(self.codomaingens) - gap.eval("phi := GroupHomomorphismByImages(G,H,"+args+")") + args = str(self.domaingens) + "," + str(self.codomaingens) + gap.eval("phi := GroupHomomorphismByImages(G,H," + args + ")") self.gap_hom_string = "phi := GroupHomomorphismByImages(G,H,"+args+")" return self.gap_hom_string @@ -166,8 +176,9 @@ def kernel(self): """ Only works for finite groups. - TODO: not done yet; returns a gap object but should return a Sage - group. + .. TODO:: + + not done yet; returns a gap object but should return a Sage group. EXAMPLES:: @@ -180,35 +191,43 @@ def kernel(self): sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) sage: phi.kernel() 'Group([ ])' + + sage: H = AbelianGroup(3,[2,2,2],names="abc") + sage: a,b,c = H.gens() + sage: G = AbelianGroup(2,[2,2],names="x") + sage: x,y = G.gens() + sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,a]) + sage: phi.kernel() + 'Group([ f1*f2 ])' """ cmd = self._gap_init_() gap.eval(cmd) return gap.eval("Kernel(phi)") - def image(self, J): + def image(self, S): """ - Only works for finite groups. + Return the image of the subgroup ``S`` by the morphism. + + This only works for finite groups. - J must be a subgroup of G. Computes the subgroup of H which is the - image of J. + INPUT: + + - ``S`` -- a subgroup of the domain group ``G`` EXAMPLES:: sage: G = AbelianGroup(2,[2,3],names="xy") sage: x,y = G.gens() + sage: subG = G.subgroup([x]) sage: H = AbelianGroup(3,[2,3,4],names="abc") sage: a,b,c = H.gens() sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) + sage: phi.image(subG) + Multiplicative Abelian subgroup isomorphic to C2 generated by {a} """ - G = self.domain() - gensJ = J.gens() - for g in gensJ: - print(g) - print(self(g), "\n") - L = [self(g) for g in gensJ] - return G.subgroup(L) - - def _call_( self, g ): + return self.codomain().subgroup([self(g) for g in S.gens()]) + + def _call_(self, g): """ Some python code for wrapping GAP's Images function but only for permutation groups. Returns an error if g is not in G. @@ -225,10 +244,7 @@ def _call_( self, g ): sage: phi(y^2) b^2 """ - G = g.parent() - w = g.word_problem(self.domaingens) - n = len(w) # g.word_problem is faster in general than word_problem(g) gens = self.codomaingens - h = prod([gens[(self.domaingens).index(w[i][0])]**(w[i][1]) for i in range(n)]) - return h + return prod(gens[(self.domaingens).index(wi[0])]**wi[1] + for wi in g.word_problem(self.domaingens)) diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index 1c76552994f..59fe82e7523 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -429,7 +429,7 @@ class RewritingSystem(object): A rewriting system is a set of rules that allow to transform one word in the group to an equivalent one. - If the rewriting system is confluent, then the transformated + If the rewriting system is confluent, then the transformed word is a unique reduced form of the element of the group. .. WARNING:: diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index ae24e75385d..4c4837f03f0 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -1110,7 +1110,7 @@ def reynolds_operator(self, poly, chi=None): sage: G.reynolds_operator(f, chi) Traceback (most recent call last): ... - NotImplementedError: nontrivial characters not implemented for charateristic > 0 + NotImplementedError: nontrivial characters not implemented for characteristic > 0 sage: G.reynolds_operator(f) x^6 @@ -1194,7 +1194,7 @@ def reynolds_operator(self, poly, chi=None): L1 = fields[0].composite_fields(fields[1])[0] L = L1.composite_fields(fields[2])[0] else: - raise NotImplementedError("nontrivial characters not implemented for charateristic > 0") + raise NotImplementedError("nontrivial characters not implemented for characteristic > 0") poly = poly.change_ring(L) poly_gens = vector(poly.parent().gens()) F = L.zero() diff --git a/src/sage/groups/perm_gps/partn_ref/data_structures.pyx b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx index 0db8f9efe4f..9a1c29923c7 100644 --- a/src/sage/groups/perm_gps/partn_ref/data_structures.pyx +++ b/src/sage/groups/perm_gps/partn_ref/data_structures.pyx @@ -1287,10 +1287,10 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, ....: m = n//3 ....: perm1 = list(range(2*m)) ....: shuffle(perm1) - ....: perm1 += range(2*m,n) - ....: perm2 = range(m,n) + ....: perm1 += list(range(2*m,n)) + ....: perm2 = list(range(m,n)) ....: shuffle(perm2) - ....: perm2 = range(m) + perm2 + ....: perm2 = list(range(m)) + perm2 ....: SC_test_list_perms([perm1, perm2], n, limit, gap, 0, contains) sage: for n in [4..9]: # long time ....: for _ in range(2): # long time diff --git a/src/sage/groups/perm_gps/symgp_conjugacy_class.py b/src/sage/groups/perm_gps/symgp_conjugacy_class.py index 7bd1a42e0f4..3b55bcf178b 100644 --- a/src/sage/groups/perm_gps/symgp_conjugacy_class.py +++ b/src/sage/groups/perm_gps/symgp_conjugacy_class.py @@ -292,6 +292,7 @@ def default_representative(part, G): # once SymmetricGroup is a proper parent. return PermutationGroupElement(cycles, G, check=False) + def conjugacy_class_iterator(part, S=None): r""" Return an iterator over the conjugacy class associated to @@ -319,12 +320,10 @@ def conjugacy_class_iterator(part, S=None): [(1, 3), (2, 4)] [(1, 4), (2, 3)] - In order to get permutations, one can use ``map`` - from the Python module ``builtins`` (works with Python 2 and Python 3):: + In order to get permutations, one just has to wrap:: - sage: from builtins import map sage: S = SymmetricGroup(5) - sage: for p in map(S, conjugacy_class_iterator([3,2])): print(p) + sage: for p in conjugacy_class_iterator([3,2]): print(S(p)) (1,2)(3,4,5) (1,2)(3,5,4) (1,3)(2,4,5) diff --git a/src/sage/homology/simplicial_complex.py b/src/sage/homology/simplicial_complex.py index 007402a0d89..6462d2fe9d6 100644 --- a/src/sage/homology/simplicial_complex.py +++ b/src/sage/homology/simplicial_complex.py @@ -839,7 +839,7 @@ class SimplicialComplex(Parent, GenericCellComplex): (or tuples, etc.) of vertices. Maximal faces are also known as 'facets'. - Alternatively, the maximal faces can be defined from a monotome boolean + Alternatively, the maximal faces can be defined from a monotone boolean function on the subsets of a set `X`. While defining ``maximal_faces=None``, you can thus set ``from_characteristic_function=(f,X)`` where ``X`` is the set of points and ``f`` a boolean monotone hereditary function that accepts diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index 2202f45964b..434ac77f884 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -1129,7 +1129,8 @@ def __init__(self, max_workspace_size=None, def set_seed(self,seed=None): """ - Sets the seed for gap interpeter. + Set the seed for gap interpreter. + The seed should be an integer. EXAMPLES:: diff --git a/src/sage/interfaces/giac.py b/src/sage/interfaces/giac.py index 0742cf896e6..0649a26d991 100644 --- a/src/sage/interfaces/giac.py +++ b/src/sage/interfaces/giac.py @@ -714,14 +714,14 @@ def _true_symbol(self): EXAMPLES:: sage: giac._true_symbol() - '1' + 'true' :: sage: giac(2) == giac(2) True """ - return '1' + return 'true' def _assign_symbol(self): """ diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index ad5bf3d9c73..53381d96308 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -221,7 +221,8 @@ def __init__(self, stacksize=10000000, # 10MB def set_seed(self, seed=None): """ - Sets the seed for gp interpeter. + Set the seed for gp interpreter. + The seed should be an integer. EXAMPLES:: diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index 78f87d27998..7d8f9131e83 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -366,7 +366,8 @@ def __init__(self, script_subdirectory=None, def set_seed(self, seed=None): """ - Sets the seed for the Magma interpeter. + Set the seed for the Magma interpreter. + The seed should be an integer. EXAMPLES:: diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py index 8c6d589babc..8b54d985aaa 100644 --- a/src/sage/interfaces/r.py +++ b/src/sage/interfaces/r.py @@ -362,7 +362,8 @@ def __init__(self, def set_seed(self, seed=None): """ - Sets the seed for R interpeter. + Set the seed for R interpreter. + The seed should be an integer. EXAMPLES:: @@ -1889,7 +1890,7 @@ def _sage_(self): # c is an ordered list # list is a dictionary (where _Names give the entries names. # map entries in names to (value, name) in each entry? - # structure is .. see above .. strucuture(DATA,**kw) + # structure is .. see above .. structure(DATA,**kw) # TODO: thinking of just replacing c( with ( to get a long tuple? diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py index 8d9e9605cf4..466347bd9a5 100644 --- a/src/sage/interfaces/scilab.py +++ b/src/sage/interfaces/scilab.py @@ -236,7 +236,8 @@ def __init__(self, maxread=None, script_subdirectory=None, def set_seed(self, seed=None): """ - Sets the seed for gp interpeter. + Set the seed for gp interpreter. + The seed should be an integer. EXAMPLES:: diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index 8a02c1b9db0..18f8384c508 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -400,7 +400,8 @@ def __init__(self, maxread=None, script_subdirectory=None, def set_seed(self,seed=None): """ - Sets the seed for singular interpeter. + Set the seed for singular interpreter. + The seed should be an integer at least 1 and not more than 30 bits. See diff --git a/src/sage/interfaces/tests.py b/src/sage/interfaces/tests.py index af9797abcdf..6bcbfef37b2 100644 --- a/src/sage/interfaces/tests.py +++ b/src/sage/interfaces/tests.py @@ -37,10 +37,11 @@ 0 sage: subprocess.call("echo syntax error | gp", **kwds) 0 - sage: subprocess.call("echo syntax error | ipython", **kwds) in (0,1) + sage: subprocess.call("echo syntax error | ipython", **kwds) in (0, 1, 120) True sage: subprocess.call("echo syntax error | Singular", **kwds) 0 + sage: f.close() """ from __future__ import print_function from __future__ import absolute_import diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index f60eff48e48..5fa23cd3f15 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -559,6 +559,18 @@ def __eq__(self, other): return True return self.braid() == other.braid() + def __hash__(self): + """ + Return the hash of ``self``. + + EXAMPLES:: + + sage: B = BraidGroup(8) + sage: L1 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) + sage: H = hash(L1) + """ + return hash(self.braid()) + def __ne__(self, other): """ Check inequality. diff --git a/src/sage/lfunctions/all.py b/src/sage/lfunctions/all.py index d7d4d065841..9281f97ebbe 100644 --- a/src/sage/lfunctions/all.py +++ b/src/sage/lfunctions/all.py @@ -1,9 +1,6 @@ -from __future__ import absolute_import +from sage.misc.lazy_import import lazy_import as _lazy_import_ -from .dokchitser import Dokchitser - -from .lcalc import lcalc - -from .sympow import sympow - -from .zero_sums import LFunctionZeroSum +_lazy_import_("sage.lfunctions.dokchitser", "Dokchitser") +_lazy_import_("sage.lfunctions.sympow", "sympow") +_lazy_import_("sage.lfunctions.zero_sums", "LFunctionZeroSum") +_lazy_import_("sage.lfunctions.lcalc", "lcalc") diff --git a/src/sage/libs/flint/fmpz_poly.pyx b/src/sage/libs/flint/fmpz_poly.pyx index fee3b2cf5b7..3d83acd4505 100644 --- a/src/sage/libs/flint/fmpz_poly.pyx +++ b/src/sage/libs/flint/fmpz_poly.pyx @@ -23,6 +23,7 @@ from cpython.sequence cimport * from cysignals.memory cimport sig_free from sage.arith.long cimport pyobject_to_long +from sage.cpython.string cimport char_to_str, str_to_bytes from sage.structure.sage_object cimport SageObject from sage.rings.integer cimport Integer from sage.libs.flint.fmpz_poly cimport * @@ -51,7 +52,7 @@ cdef class Fmpz_poly(SageObject): cdef long c cdef Integer w if isinstance(v, str): - if not fmpz_poly_set_str(self.poly, v): + if not fmpz_poly_set_str(self.poly, str_to_bytes(v)): return else: raise ValueError("Unable to create Fmpz_poly from that string.") @@ -117,7 +118,7 @@ cdef class Fmpz_poly(SageObject): 8 0 0 0 0 0 0 0 1 """ cdef char* ss = fmpz_poly_get_str(self.poly) - cdef object s = ss + cdef object s = char_to_str(ss) sig_free(ss) return s diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index c7ca311ad52..e6f1e483925 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -2617,7 +2617,7 @@ cdef class GapElement_List(GapElement): """ Return the list as a vector. - GAP does not have a special vetor data type, they are just + GAP does not have a special vector data type, they are just lists. This function converts a GAP list to a Sage vector. OUTPUT: diff --git a/src/sage/libs/gap/util.pyx b/src/sage/libs/gap/util.pyx index abc04d331e4..7bffcfc00d7 100644 --- a/src/sage/libs/gap/util.pyx +++ b/src/sage/libs/gap/util.pyx @@ -391,7 +391,7 @@ cdef inline void DEBUG_CHECK(libGAP_Obj obj): cpdef memory_usage(): """ - Return information about the memory useage. + Return information about the memory usage. See :meth:`~sage.libs.gap.libgap.Gap.mem` for details. """ diff --git a/src/sage/libs/homfly.pyx b/src/sage/libs/homfly.pyx index a10e2c59760..172783f60c4 100644 --- a/src/sage/libs/homfly.pyx +++ b/src/sage/libs/homfly.pyx @@ -32,8 +32,10 @@ AUTHORS: from cysignals.signals cimport sig_on, sig_off +from sage.cpython.string cimport str_to_bytes, char_to_str + cdef extern from "homfly.h": - ctypedef int word; + ctypedef int word; ctypedef signed long int sb4; ctypedef unsigned short int ub2; ctypedef signed short int sb2; @@ -67,12 +69,12 @@ def homfly_polynomial_string(link): sage: homfly_polynomial_string(trefoil) # optional - libhomfly ' - L^-4 - 2L^-2 + M^2L^-2' """ - cdef char* c_string = link + link = str_to_bytes(link) sig_on() - cdef char* c_output = homfly_str(c_string) + cdef char* c_output = homfly_str(link) sig_off() - output = c_output - return output + return char_to_str(c_output) + def homfly_polynomial_dict(link): """ @@ -93,10 +95,10 @@ def homfly_polynomial_dict(link): sage: homfly_polynomial_dict(trefoil) # optional - libhomfly {(-4, 0): -1, (-2, 0): -2, (-2, 2): 1} """ - cdef char* c_string = link + link = str_to_bytes(link) cdef Term ter sig_on() - cdef Poly* c_output = homfly(c_string) + cdef Poly* c_output = homfly(link) sig_off() cdef int l = c_output.len d = dict() diff --git a/src/sage/libs/mpc.pxd b/src/sage/libs/mpc.pxd deleted file mode 100644 index 24fb0f82816..00000000000 --- a/src/sage/libs/mpc.pxd +++ /dev/null @@ -1,133 +0,0 @@ -from sage.libs.gmp.types cimport * -from sage.libs.mpfr.types cimport * - -cdef extern from "mpc.h": - ctypedef struct __mpc_struct: - mpfr_t re - mpfr_t im - ctypedef __mpc_struct mpc_t[1] - ctypedef __mpc_struct* mpc_ptr - ctypedef __mpc_struct* mpc_srcptr - - ctypedef enum mpc_rnd_t: - MPC_RNDNN = 0 - MPC_RNDZN = 1 - MPC_RNDUN = 2 - MPC_RNDDN = 3 - MPC_RNDNZ = 16 - MPC_RNDZZ = 17 - MPC_RNDUZ = 18 - MPC_RNDDZ = 19 - MPC_RNDNU = 32 - MPC_RNDZU = 33 - MPC_RNDUU = 34 - MPC_RNDDU = 35 - MPC_RNDND = 48 - MPC_RNDZD = 49 - MPC_RNDUD = 50 - MPC_RNDDD = 51 - - # Memory management - void mpc_init (mpc_t) - void mpc_init2 (mpc_t, mpfr_prec_t) - void mpc_clear (mpc_t) - - # Precision accessors - mpfr_prec_t mpc_get_prec (mpc_t) - void mpc_set_prec (mpc_t, mpfr_prec_t) - - # Set real part to given value and imaginary part to +0 - int mpc_set_ui (mpc_t, unsigned long int, mpc_rnd_t) - int mpc_set_si (mpc_t, long int, mpc_rnd_t) - int mpc_set_z (mpc_t, mpz_t, mpc_rnd_t) - int mpc_set_d (mpc_t, double, mpc_rnd_t) - int mpc_set_fr (mpc_t, mpfr_t, mpc_rnd_t) - # Set value - int mpc_set (mpc_t, mpc_t, mpc_rnd_t) - int mpc_set_ui_ui (mpc_t, unsigned long int, unsigned long int, mpc_rnd_t) - int mpc_set_si_si (mpc_t, long int, long int, mpc_rnd_t) - int mpc_set_d_d (mpc_t, double, double, mpc_rnd_t) - int mpc_set_fr_fr (mpc_t, mpfr_t, mpfr_t, mpc_rnd_t) - void mpc_set_nan(mpc_t) - void mpc_swap(mpc_t, mpc_t) - - # Comparisons - int mpc_cmp (mpc_t, mpc_t) - int mpc_cmp_si_si (mpc_t, long int, long int) - int mpc_cmp_si (mpc_t, long int) - - # Projection - int mpc_real (mpfr_t rop, mpc_t op, mpfr_rnd_t rnd) - int mpc_imag (mpfr_t rop, mpc_t op, mpfr_rnd_t rnd) - mpfr_t mpc_realref (mpc_t op) - mpfr_t mpc_imagref (mpc_t op) - int mpc_arg (mpfr_t rop, mpc_t op, mpfr_rnd_t rnd) - int mpc_proj (mpc_t rop, mpc_t op, mpc_rnd_t rnd) - - # Arithmetic - int mpc_neg (mpc_t, mpc_t, mpc_rnd_t) - int mpc_conj (mpc_t, mpc_t, mpc_rnd_t) - - int mpc_add (mpc_t, mpc_t, mpc_t, mpc_rnd_t) - int mpc_sub (mpc_t, mpc_t, mpc_t, mpc_rnd_t) - int mpc_mul (mpc_t, mpc_t, mpc_t, mpc_rnd_t) - int mpc_div (mpc_t, mpc_t, mpc_t, mpc_rnd_t) - int mpc_sqr (mpc_t, mpc_t, mpc_rnd_t) - - int mpc_add_fr (mpc_t, mpc_t, mpfr_t, mpc_rnd_t) - int mpc_add_ui (mpc_t, mpc_t, unsigned long int, mpc_rnd_t) - int mpc_add_si (mpc_t, mpc_t, unsigned long, mpc_rnd_t) - int mpc_sub_fr (mpc_t, mpc_t, mpfr_t, mpc_rnd_t) - int mpc_fr_sub (mpc_t, mpfr_t, mpc_t, mpc_rnd_t) - int mpc_sub_ui (mpc_t, mpc_t, unsigned long int, mpc_rnd_t) - int mpc_ui_sub (mpc_t, unsigned long int, mpc_t, mpc_rnd_t) - int mpc_ui_ui_sub (mpc_t, unsigned long int, unsigned long int, mpc_t, mpc_rnd_t) - int mpc_mul_fr (mpc_t, mpc_t, mpfr_t, mpc_rnd_t) - int mpc_mul_ui (mpc_t, mpc_t, unsigned long int, mpc_rnd_t) - int mpc_mul_si (mpc_t, mpc_t, long int, mpc_rnd_t) - int mpc_mul_i (mpc_t, mpc_t, int, mpc_rnd_t) - int mpc_ui_div (mpc_t, unsigned long int, mpc_t, mpc_rnd_t) - int mpc_div_fr (mpc_t, mpc_t, mpfr_t, mpc_rnd_t) - int mpc_fr_div (mpc_t, mpfr_t, mpc_t, mpc_rnd_t) - int mpc_div_ui (mpc_t, mpc_t, unsigned long int, mpc_rnd_t) - int mpc_ui_div (mpc_t, unsigned long int, mpc_t, mpc_rnd_t) - int mpc_div_2ui (mpc_t, mpc_t, unsigned long int, mpc_rnd_t) - int mpc_div_2si (mpc_t, mpc_t, long int, mpc_rnd_t) - int mpc_mul_2ui (mpc_t, mpc_t, unsigned long int, mpc_rnd_t) - int mpc_mul_2si (mpc_t, mpc_t, long int, mpc_rnd_t) - # - int mpc_abs (mpfr_t, mpc_t, mpfr_rnd_t) - int mpc_norm (mpfr_t, mpc_t, mpfr_rnd_t) - - - # Power functions and logarithm - int mpc_sqrt (mpc_t, mpc_t, mpc_rnd_t) - int mpc_exp (mpc_t, mpc_t, mpc_rnd_t) - int mpc_log (mpc_t, mpc_t, mpc_rnd_t) - int mpc_pow (mpc_t rop, mpc_t op1, mpc_t op2, mpc_rnd_t rnd) - int mpc_pow_si (mpc_t rop, mpc_t op1, long op2, mpc_rnd_t rnd) - int mpc_pow_ui (mpc_t rop, mpc_t op1, unsigned long op2, mpc_rnd_t rnd) - int mpc_pow_z (mpc_t rop, mpc_t op1, mpz_t, mpc_rnd_t rnd) - int mpc_pow_d (mpc_t rop, mpc_t op1, double, mpc_rnd_t rnd) - int mpc_pow_fr (mpc_t rop, mpc_t op1, mpfr_t op2, mpc_rnd_t rnd) - - # Trigonometric functions - void mpc_sin (mpc_t, mpc_t, mpc_rnd_t) - void mpc_cos (mpc_t, mpc_t, mpc_rnd_t) - void mpc_tan (mpc_t, mpc_t, mpc_rnd_t) - void mpc_sinh (mpc_t, mpc_t, mpc_rnd_t) - void mpc_cosh (mpc_t, mpc_t, mpc_rnd_t) - void mpc_tanh (mpc_t, mpc_t, mpc_rnd_t) - void mpc_asin (mpc_t, mpc_t, mpc_rnd_t) - void mpc_acos (mpc_t, mpc_t, mpc_rnd_t) - void mpc_atan (mpc_t, mpc_t, mpc_rnd_t) - void mpc_asinh (mpc_t, mpc_t, mpc_rnd_t) - void mpc_acosh (mpc_t, mpc_t, mpc_rnd_t) - void mpc_atanh (mpc_t, mpc_t, mpc_rnd_t) - - # Random Function - int mpc_urandom (mpc_t, gmp_randstate_t) - - # utility - int MPC_INEX_RE(int) - int MPC_INEX_IM(int) diff --git a/src/sage/libs/mpc/__init__.pxd b/src/sage/libs/mpc/__init__.pxd new file mode 100644 index 00000000000..4930a636c41 --- /dev/null +++ b/src/sage/libs/mpc/__init__.pxd @@ -0,0 +1,113 @@ +# distutils: libraries = gmp mpfr mpc + +from sage.libs.gmp.types cimport * +from sage.libs.mpfr.types cimport * +from sage.libs.mpc.types cimport * + +cdef extern from "mpc.h": + int mpc_add(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t) + int mpc_add_fr(mpc_ptr, mpc_srcptr, mpfr_srcptr, mpc_rnd_t) + int mpc_add_si(mpc_ptr, mpc_srcptr, long int, mpc_rnd_t) + int mpc_add_ui(mpc_ptr, mpc_srcptr, unsigned long int, mpc_rnd_t) + int mpc_sub(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t) + int mpc_sub_fr(mpc_ptr, mpc_srcptr, mpfr_srcptr, mpc_rnd_t) + int mpc_fr_sub(mpc_ptr, mpfr_srcptr, mpc_srcptr, mpc_rnd_t) + int mpc_sub_ui(mpc_ptr, mpc_srcptr, unsigned long int, mpc_rnd_t) + int mpc_ui_sub(mpc_ptr, unsigned long int, mpc_srcptr, mpc_rnd_t) + int mpc_ui_ui_sub(mpc_ptr, unsigned long int, unsigned long int, mpc_srcptr, mpc_rnd_t) + int mpc_mul(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t) + int mpc_mul_fr(mpc_ptr, mpc_srcptr, mpfr_srcptr, mpc_rnd_t) + int mpc_mul_ui(mpc_ptr, mpc_srcptr, unsigned long int, mpc_rnd_t) + int mpc_mul_si(mpc_ptr, mpc_srcptr, long int, mpc_rnd_t) + int mpc_mul_i(mpc_ptr, mpc_srcptr, int, mpc_rnd_t) + int mpc_sqr(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_div(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t) + int mpc_pow(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t) + int mpc_pow_fr(mpc_ptr, mpc_srcptr, mpfr_srcptr, mpc_rnd_t) + int mpc_pow_ld(mpc_ptr, mpc_srcptr, long double, mpc_rnd_t) + int mpc_pow_d(mpc_ptr, mpc_srcptr, double, mpc_rnd_t) + int mpc_pow_si(mpc_ptr, mpc_srcptr, long, mpc_rnd_t) + int mpc_pow_ui(mpc_ptr, mpc_srcptr, unsigned long, mpc_rnd_t) + int mpc_pow_z(mpc_ptr, mpc_srcptr, mpz_srcptr, mpc_rnd_t) + int mpc_div_fr(mpc_ptr, mpc_srcptr, mpfr_srcptr, mpc_rnd_t) + int mpc_fr_div(mpc_ptr, mpfr_srcptr, mpc_srcptr, mpc_rnd_t) + int mpc_div_ui(mpc_ptr, mpc_srcptr, unsigned long int, mpc_rnd_t) + int mpc_ui_div(mpc_ptr, unsigned long int, mpc_srcptr, mpc_rnd_t) + int mpc_div_2ui(mpc_ptr, mpc_srcptr, unsigned long int, mpc_rnd_t) + int mpc_mul_2ui(mpc_ptr, mpc_srcptr, unsigned long int, mpc_rnd_t) + int mpc_div_2si(mpc_ptr, mpc_srcptr, long int, mpc_rnd_t) + int mpc_mul_2si(mpc_ptr, mpc_srcptr, long int, mpc_rnd_t) + int mpc_conj(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_neg(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_norm(mpfr_ptr, mpc_srcptr, mpfr_rnd_t) + int mpc_abs(mpfr_ptr, mpc_srcptr, mpfr_rnd_t) + int mpc_sqrt(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_set(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_set_d(mpc_ptr, double, mpc_rnd_t) + int mpc_set_d_d(mpc_ptr, double, double, mpc_rnd_t) + int mpc_set_ld(mpc_ptr, long double, mpc_rnd_t) + int mpc_set_ld_ld(mpc_ptr, long double, long double, mpc_rnd_t) + int mpc_set_f(mpc_ptr, mpf_srcptr, mpc_rnd_t) + int mpc_set_f_f(mpc_ptr, mpf_srcptr, mpf_srcptr, mpc_rnd_t) + int mpc_set_fr(mpc_ptr, mpfr_srcptr, mpc_rnd_t) + int mpc_set_fr_fr(mpc_ptr, mpfr_srcptr, mpfr_srcptr, mpc_rnd_t) + int mpc_set_q(mpc_ptr, mpq_srcptr, mpc_rnd_t) + int mpc_set_q_q(mpc_ptr, mpq_srcptr, mpq_srcptr, mpc_rnd_t) + int mpc_set_si(mpc_ptr, long int, mpc_rnd_t) + int mpc_set_si_si(mpc_ptr, long int, long int, mpc_rnd_t) + int mpc_set_ui(mpc_ptr, unsigned long int, mpc_rnd_t) + int mpc_set_ui_ui(mpc_ptr, unsigned long int, unsigned long int, mpc_rnd_t) + int mpc_set_z(mpc_ptr, mpz_srcptr, mpc_rnd_t) + int mpc_set_z_z(mpc_ptr, mpz_srcptr, mpz_srcptr, mpc_rnd_t) + void mpc_swap(mpc_ptr, mpc_ptr) + int mpc_fma(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t) + + void mpc_set_nan(mpc_ptr) + + int mpc_real(mpfr_ptr, mpc_srcptr, mpfr_rnd_t) + int mpc_imag(mpfr_ptr, mpc_srcptr, mpfr_rnd_t) + int mpc_arg(mpfr_ptr, mpc_srcptr, mpfr_rnd_t) + int mpc_proj(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_cmp(mpc_srcptr, mpc_srcptr) + int mpc_cmp_si(mpc_srcptr, long int) + int mpc_cmp_si_si(mpc_srcptr, long int, long int) + int mpc_cmp_abs(mpc_srcptr, mpc_srcptr) + int mpc_exp(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_log(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_log10(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_sin(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_cos(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_sin_cos(mpc_ptr, mpc_ptr, mpc_srcptr, mpc_rnd_t, mpc_rnd_t) + int mpc_tan(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_sinh(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_cosh(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_tanh(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_asin(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_acos(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_atan(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_asinh(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_acosh(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_atanh(mpc_ptr, mpc_srcptr, mpc_rnd_t) + int mpc_rootofunity(mpc_ptr, unsigned long int, unsigned long int, mpc_rnd_t) + void mpc_clear(mpc_ptr) + int mpc_urandom(mpc_ptr, gmp_randstate_t) + void mpc_init2(mpc_ptr, mpfr_prec_t) + void mpc_init3(mpc_ptr, mpfr_prec_t, mpfr_prec_t) + mpfr_prec_t mpc_get_prec(mpc_srcptr x) + void mpc_get_prec2(mpfr_prec_t *pr, mpfr_prec_t *pi, mpc_srcptr x) + void mpc_set_prec(mpc_ptr, mpfr_prec_t) + const char * mpc_get_version() + + int mpc_strtoc(mpc_ptr, const char *, char **, int, mpc_rnd_t) + int mpc_set_str(mpc_ptr, const char *, int, mpc_rnd_t) + char * mpc_get_str(int, size_t, mpc_srcptr, mpc_rnd_t) + void mpc_free_str(char *) + + int mpc_inp_str(mpc_ptr, FILE *, size_t *, int, mpc_rnd_t) + size_t mpc_out_str(FILE *, int, size_t, mpc_srcptr, mpc_rnd_t) + + mpfr_t mpc_realref(mpc_t op) + mpfr_t mpc_imagref(mpc_t op) + + int MPC_INEX_RE(int) + int MPC_INEX_IM(int) diff --git a/src/sage/libs/mpc/types.pxd b/src/sage/libs/mpc/types.pxd new file mode 100644 index 00000000000..72565c08630 --- /dev/null +++ b/src/sage/libs/mpc/types.pxd @@ -0,0 +1,27 @@ +from sage.libs.mpfr.types cimport mpfr_t + +cdef extern from "mpc.h": + ctypedef struct __mpc_struct: + mpfr_t re + mpfr_t im + ctypedef __mpc_struct mpc_t[1] + ctypedef __mpc_struct* mpc_ptr + ctypedef __mpc_struct* mpc_srcptr + + ctypedef enum mpc_rnd_t: + MPC_RNDNN + MPC_RNDZN + MPC_RNDUN + MPC_RNDDN + MPC_RNDNZ + MPC_RNDZZ + MPC_RNDUZ + MPC_RNDDZ + MPC_RNDNU + MPC_RNDZU + MPC_RNDUU + MPC_RNDDU + MPC_RNDND + MPC_RNDZD + MPC_RNDUD + MPC_RNDDD diff --git a/src/sage/libs/mpfr/__init__.pxd b/src/sage/libs/mpfr/__init__.pxd index 12c7a655864..facac9aa6c7 100644 --- a/src/sage/libs/mpfr/__init__.pxd +++ b/src/sage/libs/mpfr/__init__.pxd @@ -96,6 +96,7 @@ cdef extern from "mpfr.h": int mpfr_sqrt(mpfr_t rop, mpfr_t op, mpfr_rnd_t rnd) int mpfr_sqrt_ui(mpfr_t rop, unsigned long int op, mpfr_rnd_t rnd) int mpfr_cbrt(mpfr_t rop, mpfr_t op, mpfr_rnd_t rnd) + int mpfr_rootn_ui(mpfr_t rop, mpfr_t op, unsigned long int k, mpfr_rnd_t rnd) int mpfr_root(mpfr_t rop, mpfr_t op, unsigned long int k, mpfr_rnd_t rnd) int mpfr_pow(mpfr_t rop, mpfr_t op1, mpfr_t op2, mpfr_rnd_t rnd) int mpfr_pow_ui(mpfr_t rop, mpfr_t op1, unsigned long int op2, mpfr_rnd_t rnd) diff --git a/src/sage/libs/ntl/ntl_GF2X.pyx b/src/sage/libs/ntl/ntl_GF2X.pyx index 5c3fc79d689..3b4892a132f 100644 --- a/src/sage/libs/ntl/ntl_GF2X.pyx +++ b/src/sage/libs/ntl/ntl_GF2X.pyx @@ -24,6 +24,7 @@ include 'decl.pxi' from cpython.object cimport Py_EQ, Py_NE from sage.rings.integer cimport Integer +from sage.misc.superseded import deprecation from .ntl_ZZ import unpickle_class_value from .ntl_GF2 cimport ntl_GF2 @@ -52,7 +53,8 @@ def GF2XHexOutput(have_hex=None): INPUT: have_hex if True hex representation will be used - EXAMPLES: + EXAMPLES:: + sage: m = ntl.GF2EContext(ntl.GF2X([1,1,0,1,1,0,0,0,1])) sage: x = ntl.GF2E([1,0,1,0,1], m) ; x [1 0 1 0 1] @@ -100,7 +102,8 @@ cdef class ntl_GF2X(object): OUTPUT: a new ntl.GF2X element - EXAMPLES: + EXAMPLES:: + sage: ntl.GF2X(ntl.ZZ_pX([1,1,3],2)) [1 1 1] sage: ntl.GF2X('0x1c') @@ -148,7 +151,7 @@ cdef class ntl_GF2X(object): x = x.list() # this is slow but cimport leads to circular imports elif isinstance(x, FiniteField): if x.characteristic() == 2: - x= list(x.modulus()) + x = list(x.modulus()) elif isinstance(x, FiniteField_givaroElement): x = "0x"+hex(x.integer_representation())[2:][::-1] elif isinstance(x, FiniteField_ntl_gf2eElement): @@ -159,7 +162,8 @@ cdef class ntl_GF2X(object): def __reduce__(self): """ - EXAMPLES: + EXAMPLES:: + sage: f = ntl.GF2X(ntl.ZZ_pX([1,1,3],2)) sage: loads(dumps(f)) == f True @@ -167,13 +171,14 @@ cdef class ntl_GF2X(object): sage: loads(dumps(f)) == f True """ - return unpickle_class_value, (ntl_GF2X, hex(self)) + return unpickle_class_value, (ntl_GF2X, self.hex()) def __repr__(self): """ Return the string representation of self. - EXAMPLES: + EXAMPLES:: + sage: ntl.GF2X(ntl.ZZ_pX([1,1,3],2)).__repr__() '[1 1 1]' """ @@ -181,7 +186,8 @@ cdef class ntl_GF2X(object): def __mul__(ntl_GF2X self, other): """ - EXAMPLES: + EXAMPLES:: + sage: f = ntl.GF2X([1,0,1,1]) ; g = ntl.GF2X([0,1]) sage: f*g ## indirect doctest [0 1 0 1 1] @@ -194,7 +200,8 @@ cdef class ntl_GF2X(object): def __truediv__(ntl_GF2X self, b): """ - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(4) sage: a / ntl.GF2X(2) [0 1] @@ -219,7 +226,8 @@ cdef class ntl_GF2X(object): def DivRem(ntl_GF2X self, b): """ - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(4) sage: a.DivRem( ntl.GF2X(2) ) ([0 1], []) @@ -237,7 +245,8 @@ cdef class ntl_GF2X(object): def __floordiv__(ntl_GF2X self, b): """ - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(4) sage: a // ntl.GF2X(2) [0 1] @@ -254,7 +263,8 @@ cdef class ntl_GF2X(object): def __mod__(ntl_GF2X self, b): """ - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(4) sage: a % ntl.GF2X(2) [] @@ -271,7 +281,8 @@ cdef class ntl_GF2X(object): def __sub__(ntl_GF2X self, other): """ - EXAMPLES: + EXAMPLES:: + sage: f = ntl.GF2X([1,0,1,1]) ; g = ntl.GF2X([0,1]) sage: f - g ## indirect doctest [1 1 1 1] @@ -286,7 +297,8 @@ cdef class ntl_GF2X(object): def __add__(ntl_GF2X self, other): """ - EXAMPLES: + EXAMPLES:: + sage: f = ntl.GF2X([1,0,1,1]) ; g = ntl.GF2X([0,1,0]) sage: f + g ## indirect doctest [1 1 1 1] @@ -299,7 +311,8 @@ cdef class ntl_GF2X(object): def __neg__(ntl_GF2X self): """ - EXAMPLES: + EXAMPLES:: + sage: f = ntl.GF2X([1,0,1,1]) sage: -f ## indirect doctest [1 0 1 1] @@ -312,7 +325,8 @@ cdef class ntl_GF2X(object): def __pow__(ntl_GF2X self, long e, ignored): """ - EXAMPLES: + EXAMPLES:: + sage: f = ntl.GF2X([1,0,1,1]) ; g = ntl.GF2X([0,1,0]) sage: f**3 ## indirect doctest [1 0 1 1 1 0 0 1 1 1] @@ -355,7 +369,8 @@ cdef class ntl_GF2X(object): INPUT: i -- offset/power of X - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(4); a [0 0 1] sage: a << 2 @@ -373,7 +388,8 @@ cdef class ntl_GF2X(object): INPUT: i -- offset/power of X - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(4); a [0 0 1] sage: a >> 1 @@ -390,7 +406,8 @@ cdef class ntl_GF2X(object): INPUT: other -- ntl.GF2X - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(10) sage: b = ntl.GF2X(4) sage: a.GCD(b) @@ -413,7 +430,8 @@ cdef class ntl_GF2X(object): INPUT: other -- ntl.GF2X - EXAMPLES: + EXAMPLES:: + sage: a = ntl.GF2X(10) sage: b = ntl.GF2X(4) sage: r,s,t = a.XGCD(b) @@ -435,7 +453,8 @@ cdef class ntl_GF2X(object): """ Returns the degree of this polynomial - EXAMPLES: + EXAMPLES:: + sage: ntl.GF2X([1,0,1,1]).deg() 3 """ @@ -445,7 +464,8 @@ cdef class ntl_GF2X(object): """ Represents this element as a list of binary digits. - EXAMPLES: + EXAMPLES:: + sage: e=ntl.GF2X([0,1,1]) sage: e.list() [0, 1, 1] @@ -467,7 +487,8 @@ cdef class ntl_GF2X(object): faster and preserves the HexOutput state as opposed to the above code. - EXAMPLES: + EXAMPLES:: + sage: e=ntl.GF2X([1,1,0,1,1,1,0,0,1]) sage: e.bin() '[1 1 0 1 1 1 0 0 1]' @@ -481,22 +502,32 @@ cdef class ntl_GF2X(object): GF2XHexOutput_c[0] = _hex return s - def __hex__(ntl_GF2X self): + def hex(ntl_GF2X self): """ - Returns hexadecimal representation of this element. It is - the same as setting \code{ntl.GF2XHexOutput(True)} and - representing this element afterwards. However it should be - faster and preserves the HexOutput state as opposed to - the above code. + Return an hexadecimal representation of this element. - EXAMPLES: - sage: e=ntl.GF2X([1,1,0,1,1,1,0,0,1]) - sage: hex(e) - '0xb31' + It is the same as setting \code{ntl.GF2XHexOutput(True)} and + representing this element afterwards. However it should be + faster and preserves the HexOutput state as opposed to the + above code. OUTPUT: - string representing this element in hexadecimal + string representing this element in hexadecimal + + EXAMPLES:: + + sage: e = ntl.GF2X([1,1,0,1,1,1,0,0,1]) + sage: e.hex() + '0xb31' + + TESTS:: + + sage: hex(e) + doctest:warning...: + DeprecationWarning: use the method .hex instead + See http://trac.sagemath.org/24514 for details. + '0xb31' """ cdef long _hex = GF2XHexOutput_c[0] GF2XHexOutput_c[0] = 1 @@ -504,8 +535,12 @@ cdef class ntl_GF2X(object): GF2XHexOutput_c[0] = _hex return s + def __hex__(self): + deprecation(24514, 'use the method .hex instead') + return self.hex() + def __hash__(self): - return hash(hex(self)) + return hash(self.hex()) def _sage_(ntl_GF2X self, R=None): """ @@ -521,7 +556,8 @@ cdef class ntl_GF2X(object): OUTPUT: polynomial in R - EXAMPLES: + EXAMPLES:: + sage: f = ntl.GF2X([1,0,1,1,0,1]) sage: f._sage_() x^5 + x^3 + x^2 + 1 @@ -542,7 +578,8 @@ cdef class ntl_GF2X(object): INPUT: i -- degree of X - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([0,1,0,1]) sage: e.coeff(0) 0 @@ -570,7 +607,8 @@ cdef class ntl_GF2X(object): Return the leading coefficient of self. This is always 1 except when self == 0. - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([0,1]) sage: e.LeadCoeff() 1 @@ -586,7 +624,8 @@ cdef class ntl_GF2X(object): """ Return the constant term of self. - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([1,0,1]) sage: e.ConstTerm() 1 @@ -602,7 +641,8 @@ cdef class ntl_GF2X(object): """ Return the constant term of self. - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([1,0,1]); e [1 0 1] sage: e.SetCoeff(1,1) @@ -643,7 +683,8 @@ cdef class ntl_GF2X(object): INPUT: hi -- bit position until which reverse is requested - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([1,0,1,1,0]) sage: e.reverse() [1 1 0 1] @@ -658,7 +699,8 @@ cdef class ntl_GF2X(object): """ Return the number of nonzero coefficients in self. - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([1,0,1,1,0]) sage: e.weight() 3 @@ -685,7 +727,8 @@ cdef class ntl_GF2X(object): """ returns number of bits of self, i.e., deg(self) + 1. - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([1,0,1,1,0]) sage: e.NumBits() 4 @@ -704,7 +747,8 @@ cdef class ntl_GF2X(object): """ Returns number of bytes of self, i.e., floor((NumBits(self)+7)/8) - EXAMPLES: + EXAMPLES:: + sage: e = ntl.GF2X([1,0,1,1,0,0,0,0,1,1,1,0,0,1,1,0,1,1]) sage: e.NumBytes() 3 diff --git a/src/sage/libs/pynac/pynac.pyx b/src/sage/libs/pynac/pynac.pyx index 419cc47829c..529386766c7 100644 --- a/src/sage/libs/pynac/pynac.pyx +++ b/src/sage/libs/pynac/pynac.pyx @@ -340,7 +340,7 @@ cdef stdstring* py_repr(o, int level): else: t = s # Python complexes are always printed with parentheses - # we try to avoid double parantheses + # we try to avoid double parentheses if type(o) is not complex and \ (' ' in t or '/' in t or '+' in t or '-' in t or '*' in t \ or '^' in t): diff --git a/src/sage/manifolds/differentiable/automorphismfield.py b/src/sage/manifolds/differentiable/automorphismfield.py index 62af1f3b2e3..94956dc89f8 100644 --- a/src/sage/manifolds/differentiable/automorphismfield.py +++ b/src/sage/manifolds/differentiable/automorphismfield.py @@ -106,7 +106,7 @@ class AutomorphismField(TensorField): sage: W = U.intersection(V) sage: a.add_comp_by_continuation(eV, W, c_uv) - At this stage, the automorphims field `a` is fully defined:: + At this stage, the automorphism field `a` is fully defined:: sage: a.display(eU) a = d/dx*dx + x d/dx*dy + 2 d/dy*dy diff --git a/src/sage/manifolds/differentiable/integrated_curve.py b/src/sage/manifolds/differentiable/integrated_curve.py index e8cf9507090..7b5011d702a 100644 --- a/src/sage/manifolds/differentiable/integrated_curve.py +++ b/src/sage/manifolds/differentiable/integrated_curve.py @@ -2378,7 +2378,7 @@ class IntegratedAutoparallelCurve(IntegratedCurve): the usual embedding of `\mathbb{S}^{2}` in `\mathbb{R}^{3}` thanks to using an orthonormal frame, since providing the components with respect to the coordinate basis - would require mutliplying the second component (i.e. the `\phi` + would require multiplying the second component (i.e. the `\phi` component) in order to picture the vector in the same way. This subtlety will need to be taken into account later when the numerical curve will be compared to the analytical solution. diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 125c82a392e..36b1e180342 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -305,8 +305,7 @@ cdef class Matrix_integer_dense(Matrix_dense): Actually it is only necessary that the input can be coerced to a list, so the following also works:: - sage: v = reversed(range(4)); type(v) - <... 'listreverseiterator'> + sage: v = reversed(range(4)) sage: A(v) [3 2] [1 0] diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index 5c3ad109868..7d79509451a 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -1786,7 +1786,7 @@ cdef class Matrix_rational_dense(Matrix_dense): def _echelonize_multimodular(self, height_guess=None, proof=None): """ - Echelonize self using mutlimodular recomposition + Echelonize ``self`` using multimodular recomposition. REFERENCE: diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index e34a9ba9506..d621c106c6a 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -157,7 +157,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): sage: get_matrix_class(GF(3), 2, 2, False, 'm4ri') Traceback (most recent call last): ... - ValueError: m4ri matrices are only available in characterstic 2 + ValueError: m4ri matrices are only available in characteristic 2 sage: get_matrix_class(Zmod(2**30), 2, 2, False, 'linbox-float') Traceback (most recent call last): ... @@ -227,7 +227,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): if implementation == 'm4ri': if R.order() != 2: - raise ValueError('m4ri matrices are only available in characterstic 2') + raise ValueError('m4ri matrices are only available in characteristic 2') else: return matrix_mod2_dense.Matrix_mod2_dense elif implementation == 'linbox-float': @@ -1322,7 +1322,7 @@ def __iter__(self): #yield the empty matrix in that case and return if number_of_entries == 0: yield self(0) - raise StopIteration + return import sage.combinat.integer_vector diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index ad7309185e8..c698ba5e97e 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -750,12 +750,12 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): sage: A.parent() Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring - Giving the entries improperly may first complain about not having a length. :: + Giving the entries improperly may first complain about not being iterable:: sage: diagonal_matrix(QQ, 5, 10) Traceback (most recent call last): ... - TypeError: unable to determine number of entries for diagonal matrix construction + TypeError: 'sage.rings.integer.Integer' object is not iterable Giving too many entries will raise an error. :: @@ -771,16 +771,21 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): ... ValueError: number of diagonal matrix entries (1) exceeds the requested matrix size (-2) - Types for the entries are limited, even though they may have a length. :: + Types for the entries need to be iterable (tuple, list, vector, NumPy array, + etc):: sage: diagonal_matrix(x^2) Traceback (most recent call last): ... - TypeError: diagonal matrix entries are not a supported type (list, tuple, vector, or NumPy array) + TypeError: 'sage.symbolic.expression.Expression' object is not iterable + + TESTS:: + + sage: A = diagonal_matrix(reversed(range(4))) AUTHOR: - - Rob Beezer (2011-01-11): total rewrite + - Rob Beezer (2011-01-11): total rewrite """ # Roll arguments leftward # @@ -801,6 +806,11 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): # Formats 1, 2, 3, 4 entries = arg0 + # sanity check for entries + from numpy import ndarray + if not isinstance(entries, (list, tuple, ndarray)): + entries = list(entries) + # Reconcile matrix size and number of entries try: nentries = len(entries) @@ -816,11 +826,6 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True): if len(entries) == 0 and ring is None: ring = rings.ZZ - # Sanity check on entries (partially, e.g. a list of lists will survive this check) - from numpy import ndarray - if not any([isinstance(entries, (list, tuple)), isinstance(entries, ndarray), is_Vector(entries)]): - raise TypeError('diagonal matrix entries are not a supported type (list, tuple, vector, or NumPy array)') - # Convert entries to a list v over a common ring from sage.modules.free_module_element import prepare v, ring = prepare(entries, ring) diff --git a/src/sage/matroids/graphic_matroid.py b/src/sage/matroids/graphic_matroid.py index e4667b27ecc..46ccea8ffd1 100644 --- a/src/sage/matroids/graphic_matroid.py +++ b/src/sage/matroids/graphic_matroid.py @@ -561,7 +561,7 @@ def _minor(self, contractions=frozenset([]), deletions=frozenset([])): def _has_minor(self, N, certificate=False): """ - Check if the matroid has a minor isomoprhic to M(H). + Check if the matroid has a minor isomorphic to M(H). INPUT: @@ -1079,9 +1079,9 @@ def _is_isomorphic(self, other, certificate=False): sage: M = Matroid(Graph(edgelist)) sage: N = Matroid(range(6), graphs.WheelGraph(4)) sage: M._is_isomorphic(N, certificate=True) - (True, {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}) + (True, {'a': 2, 'b': 4, 'c': 5, 'd': 0, 'e': 1, 'f': 3}) sage: N._is_isomorphic(M, certificate=True) - (True, {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}) + (True, {0: 'd', 1: 'e', 2: 'a', 3: 'f', 4: 'b', 5: 'c'}) sage: O = Matroid(range(6), graphs.CycleGraph(6)) sage: M._is_isomorphic(O) False @@ -1145,7 +1145,7 @@ def _isomorphism(self, other): sage: M = Matroid(Graph(edgelist)) sage: N = Matroid(range(6), graphs.WheelGraph(4)) sage: M._isomorphism(N) - {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5} + {'a': 2, 'b': 4, 'c': 5, 'd': 0, 'e': 1, 'f': 3} sage: O = Matroid(Graph(edgelist), regular=True) sage: M._isomorphism(O) {'a': 'a', 'b': 'c', 'c': 'b', 'd': 'e', 'e': 'd', 'f': 'f'} @@ -1497,7 +1497,8 @@ def graphic_coextension(self, u, v=None, X=None, element=None): EXAMPLES:: - sage: M = Matroid(range(8), graphs.WheelGraph(5)) + sage: G = Graph([(0, 1, 0), (0, 2, 1), (0, 3, 2), (0, 4, 3), (1, 2, 4), (1, 4, 5), (2, 3, 6), (3, 4, 7)]) + sage: M = Matroid(G) sage: M1 = M.graphic_coextension(0, X=[1,2], element='a') sage: M1.graph().edges() [(0, 1, 0), @@ -1625,7 +1626,8 @@ def graphic_coextensions(self, vertices=None, v=None, element=None, cosimple=Fal EXAMPLES:: - sage: M = Matroid(range(8), graphs.WheelGraph(5)) + sage: G = Graph([(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 4), (2, 3), (3, 4)]) + sage: M = Matroid(range(8), G) sage: I = M.graphic_coextensions(vertices=[0], element='a') sage: for N in I: ....: N.graph().edges_incident(0) diff --git a/src/sage/matroids/set_system.pyx b/src/sage/matroids/set_system.pyx index 0256f042470..62cfc4d359a 100644 --- a/src/sage/matroids/set_system.pyx +++ b/src/sage/matroids/set_system.pyx @@ -600,7 +600,7 @@ cdef class SetSystem: partition ``P``, and while ``P`` has a partition element ``p`` with more than one element, select an arbitrary ``e`` from the first such ``p`` and split ``p`` into ``p-e``. Then replace ``P`` with - the equitabele refinement of this partition. + the equitable refinement of this partition. INPUT: diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index 38b3b7577f7..831b20f6829 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -346,7 +346,8 @@ doctest:: Category of finite dimensional hopf algebras with basis over Rational Field, Category of finite enumerated permutation groups, Category of finite weyl groups, - Category of group algebras over Rational Field] + Category of group algebras over Rational Field, + Category of number fields] AUTHOR: diff --git a/src/sage/misc/gperftools.py b/src/sage/misc/gperftools.py index 142308c24d2..36cd36f1c39 100644 --- a/src/sage/misc/gperftools.py +++ b/src/sage/misc/gperftools.py @@ -242,7 +242,7 @@ def _executable(self): sage: from sage.misc.gperftools import Profiler sage: prof = Profiler() sage: prof._executable() - '.../python' + '.../python...' """ import sys return sys.executable diff --git a/src/sage/misc/mrange.py b/src/sage/misc/mrange.py index 08567bf5fd8..36cbf6c2232 100644 --- a/src/sage/misc/mrange.py +++ b/src/sage/misc/mrange.py @@ -82,7 +82,7 @@ def _is_finite(L, fallback=True): try: n = _len(L) - except (TypeError, AttributeError): + except (TypeError, AttributeError, NotImplementedError): # We usually assume L is finite for speed reasons return fallback diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 9bde19dc187..61791093840 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -680,7 +680,7 @@ def visit_BinOp(self, node): sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit(ast.parse(x).body[0].value) - sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # optional - python2 + sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # py2 [11, 15, 6, 2, 2, 48] """ op = node.op.__class__.__name__ diff --git a/src/sage/modular/btquotients/pautomorphicform.py b/src/sage/modular/btquotients/pautomorphicform.py index 98ccf4ddc18..9daf1e3f49c 100644 --- a/src/sage/modular/btquotients/pautomorphicform.py +++ b/src/sage/modular/btquotients/pautomorphicform.py @@ -45,7 +45,7 @@ Cameron Franc Ph.D. thesis, McGill University, 2011. """ -from __future__ import print_function +from __future__ import print_function, division from builtins import zip @@ -751,7 +751,7 @@ def __init__(self, X, k, prec=None, basis_matrix=None, base_field=None): self._U = Symk(self._k - 2, base=self._R, act_on_left=True, adjuster=_btquot_adjuster(), - dettwist=-ZZ((self._k - 2) / 2), act_padic=True) + dettwist=-ZZ((self._k - 2) // 2), act_padic=True) if basis_matrix is None: self.__rank = self._X.dimension_harmonic_cocycles(self._k) @@ -1302,9 +1302,9 @@ def __apply_hecke_operator(self, l, f): """ HeckeData, alpha = self._X._get_hecke_data(l) if self.level() % l == 0: - factor = QQ(l ** (Integer((self._k - 2) / 2)) / (l + 1)) + factor = QQ(l ** (Integer((self._k - 2) // 2)) / (l + 1)) else: - factor = QQ(l ** (Integer((self._k - 2) / 2))) + factor = QQ(l ** (Integer((self._k - 2) // 2))) p = self._X._p alphamat = self.embed_quaternion(alpha) tmp = [self._U(0) for jj in range(len(self._E))] @@ -1925,7 +1925,7 @@ def integrate(self, f, center=1, level=0, method='moments'): delta = e.determinant() verbose('%s' % (R2([e[0, 1], e[0, 0]]) / R2([e[1, 1], e[1, 0]]))) - tmp = ((c * x + d) ** n * delta ** -ZZ(n / 2)) * f((a * x + b) / (c * x + d)) + tmp = ((c * x + d) ** n * delta ** -ZZ(n // 2)) * f((a * x + b) / (c * x + d)) exp = R1(tmp.numerator()) / R1(tmp.denominator()) new = eval_dist_at_powseries(self.evaluate(e), exp) @@ -2283,12 +2283,12 @@ def __init__(self, domain, U, prec=None, t=None, R=None, prec_cap=U - 1 + t, act_on_left=True, adjuster=_btquot_adjuster(), - dettwist=-ZZ((U - 2) / 2), + dettwist=-ZZ((U - 2) // 2), act_padic=True) else: self._U = Symk(U - 2, base=self._R, act_on_left=True, adjuster=_btquot_adjuster(), - dettwist=-ZZ((U - 2) / 2), + dettwist=-ZZ((U - 2) // 2), act_padic=True) else: self._U = U diff --git a/src/sage/modular/hecke/module.py b/src/sage/modular/hecke/module.py index 98231db856d..113b5e19fed 100644 --- a/src/sage/modular/hecke/module.py +++ b/src/sage/modular/hecke/module.py @@ -154,7 +154,7 @@ def _compute_hecke_matrix_prime_power(self, p, r, **kwds): if eps is None: raise NotImplementedError("either character or _compute_hecke_matrix_prime_power must be overloaded in a derived class") k = self.weight() - Tpr2 = self._hecke_matrices[pow/p] + Tpr2 = self._hecke_matrices[pow // p] return Tp*Tpr1 - eps(p)*(p**(k-1)) * Tpr2 def _compute_hecke_matrix_general_product(self, F, **kwds): diff --git a/src/sage/modular/local_comp/liftings.py b/src/sage/modular/local_comp/liftings.py index d5f59f97ffb..10fcde9fb39 100644 --- a/src/sage/modular/local_comp/liftings.py +++ b/src/sage/modular/local_comp/liftings.py @@ -6,9 +6,11 @@ problems. """ -from sage.rings.all import ZZ, Zmod +from sage.rings.all import ZZ from sage.arith.all import crt, inverse_mod from sage.modular.modsym.p1list import lift_to_sl2z +from copy import copy + def lift_to_gamma1(g, m, n): r""" @@ -18,6 +20,12 @@ def lift_to_gamma1(g, m, n): `\begin{pmatrix} 1 & * \\ 0 & 1 \end{pmatrix} \pmod n`. Here `m` and `n` must be coprime. + INPUT: + + - ``g`` -- list of 4 integers defining a `2 \times 2` matrix + + - `m`, `n` -- coprime positive integers + Here `m` and `n` should be coprime positive integers. Either of `m` and `n` can be `1`. If `n = 1`, this still makes perfect sense; this is what is called by the function :func:`~lift_matrix_to_sl2z`. If `m = 1` this is a @@ -56,15 +64,17 @@ def lift_to_gamma1(g, m, n): [1, 0, 0, 1] """ if m == 1: - return [ZZ(1),ZZ(0),ZZ(0),ZZ(1)] - a,b,c,d = [ZZ(x) for x in g] - if not (a*d - b*c) % m == 1: - raise ValueError( "Determinant is {0} mod {1}, should be 1".format((a*d - b*c) % m, m) ) + return [ZZ.one(), ZZ.zero(), ZZ.zero(), ZZ.one()] + a, b, c, d = [ZZ(x) for x in g] + det = (a * d - b * c) % m + if det != 1: + raise ValueError("Determinant is {0} mod {1}, should be 1".format(det, m)) c2 = crt(c, 0, m, n) d2 = crt(d, 1, m, n) - a3,b3,c3,d3 = [ZZ(_) for _ in lift_to_sl2z(c2,d2,m*n)] + a3,b3,c3,d3 = [ZZ(_) for _ in lift_to_sl2z(c2, d2, m * n)] r = (a3*b - b3*a) % m - return [a3 + r*c3, b3 + r*d3, c3, d3] + return [a3 + r * c3, b3 + r * d3, c3, d3] + def lift_matrix_to_sl2z(A, N): r""" @@ -74,7 +84,13 @@ def lift_matrix_to_sl2z(A, N): This is a special case of :func:`~lift_to_gamma1`, and is coded as such. - TESTS:: + INPUT: + + - ``A`` -- list of 4 integers defining a `2 \times 2` matrix + + - `N` -- positive integer + + EXAMPLES:: sage: from sage.modular.local_comp.liftings import lift_matrix_to_sl2z sage: lift_matrix_to_sl2z([10, 11, 3, 11], 19) @@ -88,6 +104,7 @@ def lift_matrix_to_sl2z(A, N): """ return lift_to_gamma1(A, N, 1) + def lift_gen_to_gamma1(m, n): r""" Return four integers defining a matrix in `\mathrm{SL}_2(\ZZ)` which is @@ -97,6 +114,10 @@ def lift_gen_to_gamma1(m, n): This is a special case of :func:`~lift_to_gamma1`, and is coded as such. + INPUT: + + - `m`, `n` -- coprime positive integers + EXAMPLES:: sage: from sage.modular.local_comp.liftings import lift_gen_to_gamma1 @@ -114,6 +135,7 @@ def lift_gen_to_gamma1(m, n): """ return lift_to_gamma1([0,-1,1,0], m, n) + def lift_uniformiser_odd(p, u, n): r""" Construct a matrix over `\ZZ` whose determinant is `p`, and which is @@ -132,7 +154,7 @@ def lift_uniformiser_odd(p, u, n): """ g = lift_gen_to_gamma1(p**u, n) - return [p*g[0], g[1], p*g[2], g[3]] + return [p * g[0], g[1], p * g[2], g[3]] def lift_ramified(g, p, u, n): @@ -156,9 +178,116 @@ def lift_ramified(g, p, u, n): sage: type(lift_ramified([8,2,12,2], 3, 2, 23)[0]) """ - a,b,c,d = lift_to_gamma1(g, p**u, n) - r = crt( (c - g[2]) / p**u * inverse_mod(a, p), 0, p, n) + a, b, c, d = lift_to_gamma1(g, p**u, n) + r = crt((c - g[2]) / p**u * inverse_mod(a, p), 0, p, n) c = c - p**u * r * a d = d - p**u * r * b # assert (c - g[2]) % p**(u+1) == 0 - return [a,b,c,d] + return [a, b, c, d] + + +def lift_for_SL(A, N=None): + r""" + Lift a matrix `A` from `SL_m(\ZZ / N\ZZ)` to `SL_m(\ZZ)`. + + This follows [Shi1971]_, Lemma 1.38, p. 21. + + INPUT: + + - ``A`` -- a square matrix with coefficients in `\ZZ / N\ZZ` (or `\ZZ`) + + - ``N`` -- the modulus (optional) required only if the matrix ``A`` + has coefficients in `\ZZ` + + EXAMPLES:: + + sage: from sage.modular.local_comp.liftings import lift_for_SL + sage: A = matrix(Zmod(11), 4, 4, [6, 0, 0, 9, 1, 6, 9, 4, 4, 4, 8, 0, 4, 0, 0, 8]) + sage: A.det() + 1 + sage: L = lift_for_SL(A) + sage: L.det() + 1 + sage: (L - A) == 0 + True + + sage: B = matrix(Zmod(19), 4, 4, [1, 6, 10, 4, 4, 14, 15, 4, 13, 0, 1, 15, 15, 15, 17, 10]) + sage: B.det() + 1 + sage: L = lift_for_SL(B) + sage: L.det() + 1 + sage: (L - B) == 0 + True + + TESTS:: + + sage: lift_for_SL(matrix(3,3,[1,2,0,3,4,0,0,0,1]),3) + [10 14 3] + [ 9 10 3] + [ 3 3 1] + + sage: A = matrix(Zmod(7), 2, [1,0,0,1]) + sage: L = lift_for_SL(A) + sage: L.parent() + Full MatrixSpace of 2 by 2 dense matrices over Integer Ring + + sage: A = matrix(Zmod(7), 1, [1]) + sage: L = lift_for_SL(A); L + [1] + + sage: A = matrix(ZZ, 2, [1,0,0,1]) + sage: lift_for_SL(A) + Traceback (most recent call last): + ... + ValueError: you must choose the modulus + + sage: for _ in range(100): + ....: d = randint(0, 10) + ....: p = choice([2,3,5,7,11]) + ....: M = random_matrix(Zmod(p), d, algorithm='unimodular') + ....: assert lift_for_SL(M).det() == 1 + """ + from sage.matrix.constructor import matrix + from sage.matrix.special import (identity_matrix, diagonal_matrix, + block_diagonal_matrix) + from sage.misc.misc_c import prod + + ring = A.parent().base_ring() + if N is None: + if ring is ZZ: + raise ValueError('you must choose the modulus') + else: + N = ring.characteristic() + + m = A.nrows() + if m <= 1: + return identity_matrix(ZZ, m) + + AZZ = A .change_ring(ZZ) + D, U, V = AZZ.smith_form() + diag = diagonal_matrix([-1] + [1] * (m - 1)) + if U.det() == -1: + U = diag * U + if V.det() == -1: + V = V * diag + + a = [U.row(i) * AZZ * V.column(i) for i in range(m)] + b = prod(a[1:]) + + Winv = identity_matrix(m) + Winv[1, 0] = 1 - b + Winv[0, 1] = -1 + Winv[1, 1] = b + + Xinv = identity_matrix(m) + Xinv[0, 1] = a[1] + + Cp = diagonal_matrix(a[1:]) + Cp[0, 0] *= a[0] + C = lift_for_SL(Cp, N) + + Cpp = block_diagonal_matrix(identity_matrix(1), C) + Cpp[1, 0] = 1 - a[0] + + return (~U * Winv * Cpp * Xinv * ~V).change_ring(ZZ) diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index 67aa2e90c46..0d103f49d64 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -24,7 +24,7 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import absolute_import +from __future__ import absolute_import, division from six.moves import range import sage.modular.hecke.element as element @@ -2661,8 +2661,8 @@ def __compute_weight2_trivial_character(self, X): v.append(F(t-1)/F(24)) else: an = sigma(n,1) - if n%t == 0: - an -= t * sigma(n/t,1) + if n % t == 0: + an -= t * sigma(n//t,1) v.append(an) return v diff --git a/src/sage/modular/modform_hecketriangle/graded_ring_element.py b/src/sage/modular/modform_hecketriangle/graded_ring_element.py index a23d922460f..ca15bf9e13a 100644 --- a/src/sage/modular/modform_hecketriangle/graded_ring_element.py +++ b/src/sage/modular/modform_hecketriangle/graded_ring_element.py @@ -1944,8 +1944,8 @@ def evaluate(self, tau, prec = None, num_prec = None, check=False): 2.525...e-10 - 3.884...e-6*I sage: f_i(i) 0 - sage: f_i(i + 1e-1000) - -6.084...e-14 - 4.101...e-1000*I + sage: f_i(i + 1e-1000) # rel tol 5e-2 + -6.08402217494586e-14 - 4.10147008296517e-1000*I sage: f_inf(infinity) 0 diff --git a/src/sage/monoids/automatic_semigroup.py b/src/sage/monoids/automatic_semigroup.py index 2de54a47b73..3f7e745b776 100644 --- a/src/sage/monoids/automatic_semigroup.py +++ b/src/sage/monoids/automatic_semigroup.py @@ -680,7 +680,12 @@ def _iter_concurrent(self): # been called before we move on to the next line i += 1 if i == len(self._elements) and not self._constructed: - next(self._iter) + try: + next(self._iter) + except StopIteration: + # Don't allow StopIteration to bubble up from generator + # see PEP-479 + break def cardinality(self): """ diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index e4bf95f1314..f1ac8335740 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -231,11 +231,10 @@ def __iter__(self): [S, H, R, U, B, B, E, R, Y] """ l = len(self._element_list) - i=0 + i = 0 while i < l: yield self[i] - i+=1 - raise StopIteration + i += 1 def __getitem__(self, n): """ diff --git a/src/sage/numerical/backends/coin_backend.pyx b/src/sage/numerical/backends/coin_backend.pyx index da527137d21..0e95c7fd02b 100644 --- a/src/sage/numerical/backends/coin_backend.pyx +++ b/src/sage/numerical/backends/coin_backend.pyx @@ -445,7 +445,7 @@ cdef class CoinBackend(GenericBackend): INPUT: - - ``constraints`` -- an interable containing the indices of the rows to remove + - ``constraints`` -- an iterable containing the indices of the rows to remove EXAMPLES:: diff --git a/src/sage/numerical/backends/cvxopt_backend.pyx b/src/sage/numerical/backends/cvxopt_backend.pyx index 6194549c1a2..cd41098557f 100644 --- a/src/sage/numerical/backends/cvxopt_backend.pyx +++ b/src/sage/numerical/backends/cvxopt_backend.pyx @@ -322,7 +322,7 @@ cdef class CVXOPTBackend(GenericBackend): INPUT: - - ``indices`` (list of integers) -- this list constains the + - ``indices`` (list of integers) -- this list contains the indices of the constraints in which the variable's coefficient is nonzero diff --git a/src/sage/numerical/backends/glpk_backend.pyx b/src/sage/numerical/backends/glpk_backend.pyx index 64781bd3a8a..0e81c13dad5 100644 --- a/src/sage/numerical/backends/glpk_backend.pyx +++ b/src/sage/numerical/backends/glpk_backend.pyx @@ -154,7 +154,7 @@ cdef class GLPKBackend(GenericBackend): Add ``number`` new variables. This amounts to adding new columns to the matrix. By default, - the variables are both positive, real and theor coefficient in + the variables are both positive, real and their coefficient in the objective function is 0.0. INPUT: @@ -786,7 +786,7 @@ cdef class GLPKBackend(GenericBackend): INPUT: - - ``indices`` (list of integers) -- this list constains the + - ``indices`` (list of integers) -- this list contains the indices of the constraints in which the variable's coefficient is nonzero diff --git a/src/sage/numerical/backends/glpk_graph_backend.pyx b/src/sage/numerical/backends/glpk_graph_backend.pyx index 52a4b6e8e97..65ca73706f6 100644 --- a/src/sage/numerical/backends/glpk_graph_backend.pyx +++ b/src/sage/numerical/backends/glpk_graph_backend.pyx @@ -626,7 +626,7 @@ cdef class GLPKGraphBackend(object): - ``edges`` -- An iterable container of pairs of the form ``(u, v)``, where ``u`` is name (as ``str``) of the tail vertex and ``v`` is the - name (as ``str``) of the head vertex or an interable container of + name (as ``str``) of the head vertex or an iterable container of triples of the form ``(u, v, params)`` where params is a ``dict`` as described in ``add_edge``. diff --git a/src/sage/numerical/backends/ppl_backend.pyx b/src/sage/numerical/backends/ppl_backend.pyx index 4e4b5707af6..1d089baa2be 100644 --- a/src/sage/numerical/backends/ppl_backend.pyx +++ b/src/sage/numerical/backends/ppl_backend.pyx @@ -562,7 +562,7 @@ cdef class PPLBackend(GenericBackend): INPUT: - - ``indices`` (list of integers) -- this list constains the + - ``indices`` (list of integers) -- this list contains the indices of the constraints in which the variable's coefficient is nonzero diff --git a/src/sage/numerical/interactive_simplex_method.py b/src/sage/numerical/interactive_simplex_method.py index 9ead04316ed..852ff329193 100644 --- a/src/sage/numerical/interactive_simplex_method.py +++ b/src/sage/numerical/interactive_simplex_method.py @@ -1631,7 +1631,7 @@ def plot_feasible_set(self, xmin=None, xmax=None, ymin=None, ymax=None, b = b.n().change_ring(QQ) F = self.feasible_set() if ymax is None: - ymax = max(map(abs, b) + [v[1] for v in F.vertices()]) + ymax = max([abs(bb) for bb in b] + [v[1] for v in F.vertices()]) if ymin is None: ymin = min([-ymax/4.0] + [v[1] for v in F.vertices()]) if xmax is None: diff --git a/src/sage/numerical/linear_functions.pyx b/src/sage/numerical/linear_functions.pyx index de1bf534ff9..4120cf67fdf 100644 --- a/src/sage/numerical/linear_functions.pyx +++ b/src/sage/numerical/linear_functions.pyx @@ -1570,7 +1570,7 @@ cdef class LinearConstraint(LinearFunctionOrConstraint): 3 == x_2 """ if not self.is_equation() or self.is_trivial(): - raise StopIteration + return term_iter = iter(self) lhs = next(term_iter) rhs = next(term_iter) @@ -1603,7 +1603,7 @@ cdef class LinearConstraint(LinearFunctionOrConstraint): 3 <= x_2 """ if not self.is_less_or_equal() or self.is_trivial(): - raise StopIteration + return term_iter = iter(self) lhs = next(term_iter) rhs = next(term_iter) diff --git a/src/sage/numerical/sdp.pyx b/src/sage/numerical/sdp.pyx index 9075d9bbf19..30b40d3081a 100644 --- a/src/sage/numerical/sdp.pyx +++ b/src/sage/numerical/sdp.pyx @@ -740,8 +740,7 @@ cdef class SemidefiniteProgram(SageObject): for l in lists: if isinstance(l, SDPVariable): c = {} - for (k,v) in l.items(): - #c[k] = self._values[v] if self._values.has_key(v) else None + for k, v in l.items(): c[k] = self._backend.get_variable_value(self._variables[v]) val.append(c) elif isinstance(l, list): diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 43229875ace..33d22191655 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -3301,7 +3301,6 @@ def list_plot_semilogy(data, plotjoined=False, **kwds): sage: list_plot_semilogy(list(zip(xl[1:],yl[1:]))) Graphics object consisting of 1 graphics primitive - :: sage: list_plot_semilogy([2, 4, 6, 8, 16, 31], base=2) # with base 2 @@ -3315,6 +3314,7 @@ def list_plot_semilogy(data, plotjoined=False, **kwds): """ return list_plot(data, plotjoined=plotjoined, scale='semilogy', **kwds) + def to_float_list(v): """ Given a list or tuple or iterable v, coerce each element of v to a diff --git a/src/sage/plot/plot3d/list_plot3d.py b/src/sage/plot/plot3d/list_plot3d.py index 50a4b9196ea..193a5d08429 100644 --- a/src/sage/plot/plot3d/list_plot3d.py +++ b/src/sage/plot/plot3d/list_plot3d.py @@ -213,6 +213,7 @@ def list_plot3d(v, interpolation_type='default', texture="automatic", point_list return list_plot3d_array_of_arrays(v, interpolation_type, texture, **kwds) raise TypeError("v must be a matrix or list") + def list_plot3d_matrix(m, texture, **kwds): """ A 3-dimensional plot of a surface defined by a matrix ``M`` @@ -249,6 +250,23 @@ def list_plot3d_matrix(m, texture, **kwds): Graphics3d Object sage: list_plot3d(m, texture='yellow', interpolation_type='linear') # indirect doctest Graphics3d Object + + Here is a colored example, using a colormap and a coloring function + which must take values in (0, 1):: + + sage: cm = colormaps.rainbow + sage: n = 20 + sage: cf = lambda x, y: ((2*(x-y)/n)**2) % 1 + sage: list_plot3d(matrix(RDF, n, [cos(pi*(i+j)/n) for i in [1..n] + ....: for j in [1..n]]), color=(cf,cm)) + Graphics3d Object + + .. PLOT:: + + cm = colormaps.rainbow + cf = lambda x, y: ((2*(x-y)/20)**2) % 1 + expl = list_plot3d(matrix(RDF,20,20,[cos(pi*(i+j)/20) for i in range(1,21) for j in range(1,21)]),color=(cf,cm)) + sphinx_plot(expl) """ from .parametric_surface import ParametricSurface f = lambda i,j: (i, j, float(m[int(i), int(j)])) @@ -257,6 +275,7 @@ def list_plot3d_matrix(m, texture, **kwds): G._set_extra_kwds(kwds) return G + def list_plot3d_array_of_arrays(v, interpolation_type, texture, **kwds): """ A 3-dimensional plot of a surface defined by a list of lists ``v`` diff --git a/src/sage/plot/plot3d/platonic.py b/src/sage/plot/plot3d/platonic.py index 4744ee3abe2..c15fdc3af32 100644 --- a/src/sage/plot/plot3d/platonic.py +++ b/src/sage/plot/plot3d/platonic.py @@ -222,7 +222,7 @@ def tetrahedron(center=(0, 0, 0), size=1, **kwds): sphinx_plot(tetrahedron(color='red') + tetrahedron((0,0,-2)).scale([1,1,-1])) - A Dodecahedral complex of 5 tetrahedrons (a more elaborate example + A Dodecahedral complex of 5 tetrahedra (a more elaborate example from Peter Jipsen):: sage: v=(sqrt(5.)/2-5/6, 5/6*sqrt(3.)-sqrt(15.)/2, sqrt(5.)/3) @@ -579,7 +579,7 @@ def icosahedron(center=(0, 0, 0), size=1, **kwds): sphinx_plot(icosahedron()) - Two icosahedrons at different positions of different sizes. :: + Two icosahedra at different positions of different sizes. :: sage: p = icosahedron((-1/2,0,1), color='orange') sage: p += icosahedron((2,0,1), size=1/2, color='red', aspect_ratio=[1,1,1]) diff --git a/src/sage/plot/plot3d/shapes2.py b/src/sage/plot/plot3d/shapes2.py index 1dde57433ae..f42658d1dfa 100644 --- a/src/sage/plot/plot3d/shapes2.py +++ b/src/sage/plot/plot3d/shapes2.py @@ -93,7 +93,7 @@ def line3d(points, thickness=1, radius=None, arrow_head=False, **kwds): ....: color='green') + line3d([(0,1,0), (1,0,2)]) Graphics3d Object - A Dodecahedral complex of 5 tetrahedrons (a more elaborate example + A Dodecahedral complex of 5 tetrahedra (a more elaborate example from Peter Jipsen):: sage: def tetra(col): diff --git a/src/sage/plot/plot3d/tachyon.py b/src/sage/plot/plot3d/tachyon.py index cdee141efa1..81ef81e7a61 100644 --- a/src/sage/plot/plot3d/tachyon.py +++ b/src/sage/plot/plot3d/tachyon.py @@ -698,7 +698,7 @@ def texfunc(self, type=0, center=(0,0,0), rotate=(0,0,0), scale=(1,1,1), - ``scale`` - (default: (1,1,1)) - EXAMPLES: We draw an infinite checkboard:: + EXAMPLES: We draw an infinite checkerboard:: sage: t = Tachyon(camera_center=(2,7,4), look_at=(2,0,0)) sage: t.texture('black', color=(0,0,0), texfunc=1) diff --git a/src/sage/quivers/morphism.py b/src/sage/quivers/morphism.py index b6cd04e27bd..18232b2413f 100644 --- a/src/sage/quivers/morphism.py +++ b/src/sage/quivers/morphism.py @@ -515,6 +515,25 @@ def __eq__(self, other): # If all that holds just check the vectors return self._vector == other._vector + def __hash__(self): + """ + Return the hash of ``self``. + + EXAMPLES:: + + sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup() + sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1} + sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]} + sage: M = Q.representation(QQ, spaces, maps) + sage: spaces2 = {2: QQ^1, 3: QQ^1} + sage: S = Q.representation(QQ, spaces2) + sage: x = M({2: (1, -1)}) + sage: y = M({3: (1,)}) + sage: g = S.hom([x, y], M) + sage: H = hash(g) + """ + return hash(tuple(self._vector)) + def __ne__(self, other): """ This function overrides the ``!=`` operator diff --git a/src/sage/repl/display/jsmol_iframe.py b/src/sage/repl/display/jsmol_iframe.py index 48831ca6611..b664bc6897b 100644 --- a/src/sage/repl/display/jsmol_iframe.py +++ b/src/sage/repl/display/jsmol_iframe.py @@ -155,13 +155,16 @@ def script(self): if line.startswith('pmesh'): command, obj, meshfile = line.split(' ', 3) assert command == 'pmesh' - assert meshfile.startswith('"') and meshfile.endswith('"\n') - meshfile = meshfile[1:-2] # strip quotes - script += [ - 'pmesh {0} inline "'.format(obj), - self._zip.open(meshfile).read(), - '"\n' - ] + if meshfile not in ['dots\n', 'mesh\n']: + assert meshfile.startswith('"') and meshfile.endswith('"\n') + meshfile = meshfile[1:-2] # strip quotes + script += [ + 'pmesh {0} inline "'.format(obj), + self._zip.open(meshfile).read(), + '"\n' + ] + else: + script += [line] else: script += [line] return ''.join(script) diff --git a/src/sage/repl/load.py b/src/sage/repl/load.py index e54e14cf005..e6028426aef 100644 --- a/src/sage/repl/load.py +++ b/src/sage/repl/load.py @@ -98,9 +98,9 @@ def load(filename, globals, attach=False): sage: t = tmp_filename(ext='.py') sage: _ = open(t,'w').write("print 'hi', 2/3; z = -2/7") sage: z = 1 - sage: sage.repl.load.load(t, globals()) # optional - python2 + sage: sage.repl.load.load(t, globals()) # py2 hi 0 - sage: z # optional - python2 + sage: z # py2 -1 A ``.sage`` file *is* preparsed:: diff --git a/src/sage/rings/asymptotic/growth_group.py b/src/sage/rings/asymptotic/growth_group.py index acddb7a7e60..44ab16e2d1a 100644 --- a/src/sage/rings/asymptotic/growth_group.py +++ b/src/sage/rings/asymptotic/growth_group.py @@ -1463,9 +1463,6 @@ def __classcall__(cls, base, var=None, category=None, ignore_variables=None): sage: P3 = MonomialGrowthGroup(ZZ, SR.var('x')) sage: P1 is P2 and P2 is P3 True - sage: P4 = MonomialGrowthGroup(ZZ, buffer('xylophone', 0, 1)) - sage: P1 is P4 - True sage: P5 = MonomialGrowthGroup(ZZ, 'x ') sage: P1 is P5 True diff --git a/src/sage/rings/complex_mpc.pxd b/src/sage/rings/complex_mpc.pxd index 11e1c162b59..762c38afbdc 100644 --- a/src/sage/rings/complex_mpc.pxd +++ b/src/sage/rings/complex_mpc.pxd @@ -1,4 +1,4 @@ -from sage.libs.mpc cimport mpc_t, mpc_rnd_t +from sage.libs.mpc.types cimport mpc_t, mpc_rnd_t cimport sage.structure.element cimport sage.rings.ring diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 824fe55a382..014c7efdf6d 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -2142,7 +2142,7 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): cdef RealNumber a,r a = self.argument()/n r = self.abs() - mpfr_root(r.value, r.value, n, rrnd) + mpfr_rootn_ui(r.value, r.value, n, rrnd) cdef MPComplexNumber z z = self._new() @@ -2297,7 +2297,7 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): def agm(self, right, algorithm="optimal"): """ - Returns the algebraic geometrc mean of ``self`` and ``right``. + Return the algebro-geometric mean of ``self`` and ``right``. EXAMPLES:: diff --git a/src/sage/rings/complex_number.pyx b/src/sage/rings/complex_number.pyx index 16604510037..6df884420a0 100644 --- a/src/sage/rings/complex_number.pyx +++ b/src/sage/rings/complex_number.pyx @@ -2217,7 +2217,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): rho = abs(self) arg = self.argument() / n mpfr_init2(r, self._prec) - mpfr_root(r, rho.value, n, rnd) + mpfr_rootn_ui(r, rho.value, n, rnd) mpfr_sin_cos(z.__im, z.__re, arg.value, rnd) mpfr_mul(z.__re, z.__re, r, rnd) diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index 90e2aabc69a..1c2d5facece 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -918,7 +918,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): def _element(self): """ - Returns the int interally representing this element. + Return the int internally representing this element. EXAMPLES:: diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index fca808361c8..67e72a18e73 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -574,6 +574,17 @@ def _element_constructor_(self, x, y=None, coerce=True): sage: R. = PolynomialRing(B,'x') sage: (a*d*x^2+a+e+1).resultant(-4*c^2*x+1) a*d + 16*c^4*e + 16*a*c^4 + 16*c^4 + + Check that :trac:`24539` is fixed:: + + sage: tau = polygen(QQ, 'tau') + sage: R = PolynomialRing(CyclotomicField(2), 'z').fraction_field()( + ....: tau/(1+tau)) + Traceback (most recent call last): + ... + TypeError: cannot convert tau/(tau + 1)/1 to an element of Fraction + Field of Univariate Polynomial Ring in z over Cyclotomic Field of + order 2 and degree 1 """ if y is None: if isinstance(x, Element) and x.parent() is self: @@ -619,8 +630,8 @@ def _element_constructor_(self, x, y=None, coerce=True): x = x0.numerator()*y0.denominator() y = y0.numerator()*x0.denominator() except AttributeError: - raise TypeError("cannot convert {!r}/{!r} to an element of {}", - x0, y0, self) + raise TypeError("cannot convert {!r}/{!r} to an element of {}".format( + x0, y0, self)) try: return self._element_class(self, x, y, coerce=coerce) except TypeError: @@ -933,7 +944,7 @@ class FractionFieldEmbedding(DefaultConvertMap_unique): Coercion map: From: Univariate Polynomial Ring in x over Rational Field To: Fraction Field of Univariate Polynomial Ring in x over Rational Field - + TESTS:: sage: from sage.rings.fraction_field import FractionFieldEmbedding @@ -1008,7 +1019,7 @@ def _richcmp_(self, other, op): sage: f = R.fraction_field().coerce_map_from(R) sage: S. = GF(2)[] sage: g = S.fraction_field().coerce_map_from(S) - + sage: f == g # indirect doctest False sage: f == f @@ -1045,7 +1056,7 @@ class FractionFieldEmbeddingSection(Section): Section map: From: Fraction Field of Univariate Polynomial Ring in x over Rational Field To: Univariate Polynomial Ring in x over Rational Field - + TESTS:: sage: from sage.rings.fraction_field import FractionFieldEmbeddingSection @@ -1123,7 +1134,7 @@ def _richcmp_(self, other, op): sage: f = R.fraction_field().coerce_map_from(R).section() sage: S. = GF(2)[] sage: g = S.fraction_field().coerce_map_from(S).section() - + sage: f == g # indirect doctest False sage: f == f diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index ca90682b5e4..e79308952d0 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -1483,9 +1483,11 @@ def genus(self): sage: L.genus() 3 """ - # unfortunately singular can not compute the genus with the polynomial_ring()._singular_ - # object because genus method only accepts a ring of transdental degree 2 over a prime field - # not a ring of transdental degree 1 over a rational function field of one variable + # unfortunately singular can not compute the genus with the + # polynomial_ring()._singular_ object because genus method + # only accepts a ring of transcendental degree 2 over a prime + # field not a ring of transcendental degree 1 over a rational + # function field of one variable if is_RationalFunctionField(self._base_field) and self._base_field.constant_field().is_prime_field(): diff --git a/src/sage/rings/invariant_theory.py b/src/sage/rings/invariant_theory.py index 63ad78ae3bb..d4d202a4ee8 100644 --- a/src/sage/rings/invariant_theory.py +++ b/src/sage/rings/invariant_theory.py @@ -3318,7 +3318,8 @@ def quaternary_biquadratic(self, quadratic1, quadratic2, *args, **kwds): INPUT: - - ``quadratic1``, ``quadratic2`` -- two polynomias. Either homogeneous quadratic + - ``quadratic1``, ``quadratic2`` -- two polynomials. + Either homogeneous quadratic in 4 homogeneous variables, or inhomogeneous quadratic in 3 variables. diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index bc059af3404..3959e80ba67 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -1913,7 +1913,7 @@ cdef class FrobeniusEndomorphism_generic(RingHomomorphism): raise TypeError("The base ring must be a commutative ring") self._p = domain.characteristic() if not self._p.is_prime(): - raise TypeError("The caracteristic of the base ring must be prime") + raise TypeError("the characteristic of the base ring must be prime") try: n = Integer(n) except TypeError: diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 5d782490360..85064c88916 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -120,6 +120,7 @@ from sage.misc.misc_c import prod from sage.categories.homset import End from sage.rings.all import Infinity +from sage.categories.number_fields import NumberFields import sage.rings.ring from sage.misc.latex import latex_variable_name @@ -143,6 +144,7 @@ from builtins import zip from sage.misc.superseded import deprecated_function_alias +_NumberFields = NumberFields() def is_NumberFieldHomsetCodomain(codomain): """ @@ -521,6 +523,18 @@ def NumberField(polynomial, name=None, check=True, names=None, embedding=None, l ... TypeError: You must specify the name of the generator. + Check that we can construct morphisms to matrix space (:trac:`23418`):: + + sage: t = polygen(QQ) + sage: K = NumberField(t^4 - 2, 'a') + sage: K.hom([K.gen().matrix()]) + Ring morphism: + From: Number Field in a with defining polynomial x^4 - 2 + To: Full MatrixSpace of 4 by 4 dense matrices over Rational Field + Defn: a |--> [0 1 0 0] + [0 0 1 0] + [0 0 0 1] + [2 0 0 0] """ if names is not None: name = names @@ -1202,7 +1216,7 @@ class NumberField_generic(WithEqualityById, number_field_base.NumberField): sage: NumberField(QQ['x'].0^4 + 23, 'a') == NumberField(QQ['y'].0^4 + 23, 'a') False - sage: x = var('x'); y = ZZ['y'].gen() + sage: x = polygen(QQ); y = ZZ['y'].gen() sage: NumberField(x^3 + x + 5, 'a') == NumberField(y^3 + y + 5, 'a') False sage: NumberField(x^3 + x + 5, 'a') == NumberField(y^4 + y + 5, 'a') @@ -1328,8 +1342,7 @@ def __init__(self, polynomial, name, latex_name, self._assume_disc_small = assume_disc_small self._maximize_at_primes = maximize_at_primes self._structure = structure - from sage.categories.number_fields import NumberFields - default_category = NumberFields() + default_category = _NumberFields if category is None: category = default_category else: @@ -3470,8 +3483,8 @@ def primes_of_bounded_norm_iter(self, B): except (TypeError, AttributeError): raise TypeError("%s is not valid bound on prime ideals" % B) - if B<2: - raise StopIteration + if B < 2: + return if self is QQ: for p in arith.primes(B+1): @@ -5050,7 +5063,7 @@ def extension(self, poly, name=None, names=None, *args, **kwds): sage: k. = NumberField(x^2 + 1); k Number Field in a with defining polynomial x^2 + 1 - sage: y = var('y') + sage: y = polygen(QQ,'y') sage: m. = k.extension(y^2 + 2); m Number Field in b with defining polynomial y^2 + 2 over its base field @@ -5589,45 +5602,40 @@ def reduced_basis(self, prec=None): [-1, -1/2*t^5 + 1/2*t^4 + 3*t^3 - 3/2*t^2 - 4*t - 1/2, t, 1/2*t^5 + 1/2*t^4 - 4*t^3 - 5/2*t^2 + 7*t + 1/2, 1/2*t^5 - 1/2*t^4 - 2*t^3 + 3/2*t^2 - 1/2, 1/2*t^5 - 1/2*t^4 - 3*t^3 + 5/2*t^2 + 4*t - 5/2] sage: CyclotomicField(12).reduced_basis() [1, zeta12^2, zeta12, zeta12^3] - """ - if self.is_totally_real(): - try: - return self.__reduced_basis - except AttributeError: - pass - else: - try: - if self.__reduced_basis_precision >= prec: - return self.__reduced_basis - except AttributeError: - pass - from sage.matrix.constructor import matrix + TESTS: + Check that the bug reported at :trac:`10017` is fixed:: + + sage: x = polygen(QQ) + sage: k. = NumberField(x^6 + 2218926655879913714112*x^4 - 32507675650290949030789018433536*x^3 + 4923635504174417014460581055002374467948544*x^2 - 36066074010564497464129951249279114076897746988630016*x + 264187244046129768986806800244258952598300346857154900812365824) + sage: new_basis = k.reduced_basis(prec=120) + sage: [c.minpoly() for c in new_basis] + [x - 1, + x^2 - x + 1, + x^6 + 3*x^5 - 102*x^4 - 103*x^3 + 10572*x^2 - 59919*x + 127657, + x^6 - 3*x^5 - 102*x^4 + 315*x^3 + 10254*x^2 - 80955*x + 198147, + x^3 - 171*x + 848, + x^6 + 171*x^4 + 1696*x^3 + 29241*x^2 + 145008*x + 719104] + sage: R = k.order(new_basis) + sage: R.discriminant()==k.discriminant() + True + """ + ZK = self.integral_basis() d = self.absolute_degree() - Z_basis = self.integral_basis() - ## If self is totally real, then we can use (x*y).trace() as - ## the inner product on the Minkowski embedding, which is - ## faster than computing all the conjugates, etc ... + # If self is totally real, then we can use (x*y).trace() as + # the inner product on the Minkowski embedding, which is + # faster than computing all the conjugates, etc ... + if self.is_totally_real(): - T = pari(matrix(ZZ, d, d, [[(x*y).trace() for x in Z_basis] - for y in Z_basis])).qflllgram() - self.__reduced_basis = [ sum([ ZZ(T[i][j]) * Z_basis[j] - for j in range(d)]) - for i in range(d)] + from sage.matrix.constructor import matrix + T = pari(matrix(ZZ, d, d, [[(x*y).trace() for x in ZK] for y in ZK])).qflllgram() else: - M = self.minkowski_embedding(self.integral_basis(), prec=prec) - T = pari(M).qflll().sage() - self.__reduced_basis = [ self(v.list()) for v in T.columns() ] - if prec is None: - ## this is the default choice for minkowski_embedding - self.__reduced_basis_prec = 53 - else: - self.__reduced_basis_prec = prec - - return self.__reduced_basis + M = self.minkowski_embedding(ZK, prec=prec) + T = pari(M).qflll() + return [ sum([ ZZ(T[i][j]) * ZK[j] for j in range(d)]) for i in range(d)] def reduced_gram_matrix(self, prec=None): r""" @@ -5684,14 +5692,13 @@ def reduced_gram_matrix(self, prec=None): :: - sage: var('x') - x + sage: x = polygen(QQ) sage: F. = NumberField(x^4+x^2+712312*x+131001238) sage: F.reduced_gram_matrix(prec=128) - [ 4.0000000000000000000000000000000000000 0.00000000000000000000000000000000000000 -2.1369360000000000000000000000000000000e6 -3.3122478000000000000000000000000000000e7] - [ 0.00000000000000000000000000000000000000 46721.539331563218381658483353092335550 -2.2467769057394530109094755223395819322e7 -3.4807276041138450473611629088647496430e8] - [-2.1369360000000000000000000000000000000e6 -2.2467769057394530109094755223395819322e7 7.0704285924714907491782135494859351061e12 1.1256639928034037006027526953641297995e14] - [-3.3122478000000000000000000000000000000e7 -3.4807276041138450473611629088647496430e8 1.1256639928034037006027526953641297995e14 1.7923838231014970520503146603069479547e15] + [ 4.0000000000000000000000000000000000000 0.00000000000000000000000000000000000000 -1.9999999999999999999999999999999999037 -0.99999999999999999999999999999999383702] + [ 0.00000000000000000000000000000000000000 46721.539331563218381658483353092335550 -11488.910026551724275122749703614966768 -418.12718083977141198754424579680468382] + [ -1.9999999999999999999999999999999999037 -11488.910026551724275122749703614966768 5.5658915310500611768713076521847709187e8 1.4179092271494070050433368847682152174e8] + [ -0.99999999999999999999999999999999383702 -418.12718083977141198754424579680468382 1.4179092271494070050433368847682152174e8 1.3665897267919181137884111201405279175e12] """ if self.is_totally_real(): try: diff --git a/src/sage/rings/number_field/order.py b/src/sage/rings/number_field/order.py index dcbe495df62..d717eb7618d 100644 --- a/src/sage/rings/number_field/order.py +++ b/src/sage/rings/number_field/order.py @@ -1129,6 +1129,7 @@ def _element_constructor_(self, x): EXAMPLES:: + sage: x = polygen(QQ) sage: k. = NumberField(x^2 - 389) sage: m = k.order(3*z); m Order in Number Field in z with defining polynomial x^2 - 389 @@ -1136,9 +1137,26 @@ def _element_constructor_(self, x): 6*z sage: k(m(6*z)) 6*z + + If ``x`` is a list or tuple the element constructed is the + linear combination of the generators with these coefficients + (see :trac:`10017`):: + + sage: x = polygen(QQ) + sage: K. = NumberField(x^3-10) + sage: ZK = K.ring_of_integers() + sage: ZK.basis() + [1/3*a^2 + 1/3*a + 1/3, a, a^2] + sage: ZK([1,2,3]) + 10/3*a^2 + 7/3*a + 1/3 + sage: K([1,2,3]) + 3*a^2 + 2*a + 1 + """ if is_Element(x) and x.parent() is self: return x + if isinstance(x, (tuple, list)): + x = sum(xi*gi for xi,gi in zip(x,self.gens())) if not is_Element(x) or x.parent() is not self._K: x = self._K(x) V, _, embedding = self._K.vector_space() diff --git a/src/sage/rings/padics/padic_generic_element.pyx b/src/sage/rings/padics/padic_generic_element.pyx index 334e544bba2..fa5277899d7 100644 --- a/src/sage/rings/padics/padic_generic_element.pyx +++ b/src/sage/rings/padics/padic_generic_element.pyx @@ -852,7 +852,7 @@ cdef class pAdicGenericElement(LocalGenericElement): their greatest common divisor is in general not unique (not even up to units). For example `O(3)` is a representative for the elements 0 and 3 in the 3-adic ring `\ZZ_3`. The greatest common - divisior of `O(3)` and `O(3)` could be (among others) 3 or 0 which + divisor of `O(3)` and `O(3)` could be (among others) 3 or 0 which have different valuation. The algorithm implemented here, will return an element of minimal valuation among the possible greatest common divisors. @@ -1005,7 +1005,7 @@ cdef class pAdicGenericElement(LocalGenericElement): greatest common divisor is in general not unique (not even up to units). For example `O(3)` is a representative for the elements 0 and 3 in the 3-adic ring `\ZZ_3`. The greatest common - divisior of `O(3)` and `O(3)` could be (among others) 3 or 0 which + divisor of `O(3)` and `O(3)` could be (among others) 3 or 0 which have different valuation. The algorithm implemented here, will return an element of minimal valuation among the possible greatest common divisors. diff --git a/src/sage/rings/polynomial/pbori.pyx b/src/sage/rings/polynomial/pbori.pyx index 318ff62af75..89bf06a18d8 100644 --- a/src/sage/rings/polynomial/pbori.pyx +++ b/src/sage/rings/polynomial/pbori.pyx @@ -3144,7 +3144,6 @@ cdef class BooleanPolynomial(MPolynomial): sage: x != False True """ - from builtins import zip for lm, rm in zip(left, right): if lm != rm: return richcmp_not_equal(lm, rm, op) @@ -6416,7 +6415,7 @@ cdef class ReductionStrategy: - ``leading_terms`` - all leading terms of generators - - ``minimial_leading_terms`` - the reduced set of leading terms + - ``minimal_leading_terms`` - the reduced set of leading terms - ``monomials`` - diff --git a/src/sage/rings/polynomial/polydict.pyx b/src/sage/rings/polynomial/polydict.pyx index 3ce87c8862b..b045e6bc5e5 100644 --- a/src/sage/rings/polynomial/polydict.pyx +++ b/src/sage/rings/polynomial/polydict.pyx @@ -303,7 +303,7 @@ cdef class PolyDict: return min(_min) def total_degree(PolyDict self): - return max([-1] + map(sum, self.__repn.keys())) + return max([-1] + [sum(k) for k in self.__repn.keys()]) def monomial_coefficient(PolyDict self, mon): """ diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index afa54f54ac0..dd420918180 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -73,7 +73,7 @@ from sage.misc.abstract_method import abstract_method from sage.misc.latex import latex from sage.arith.long cimport pyobject_to_long from sage.structure.factorization import Factorization -from sage.structure.richcmp cimport (richcmp, richcmp_not_equal, +from sage.structure.richcmp cimport (richcmp, richcmp_item, rich_to_bool, rich_to_bool_sgn) from sage.interfaces.singular import singular as singular_default, is_SingularElement @@ -964,13 +964,49 @@ cdef class Polynomial(CommutativeAlgebraElement): False sage: R(0) == R(0) True + + TESTS:: + + Test that comparisons are consistent when using interval + coefficients:: + + sage: R. = RIF[] + sage: a = RIF(0,1) * x + sage: b = RIF(1,2) * x + sage: a == a + False + sage: a != a + False + sage: a == b + False + sage: a < b + False + sage: a > b + False + sage: a <= b + True + sage: a >= b + False + sage: a != b + False + + For ``RBF``, identical elements are considered equal:: + + sage: R. = RBF[] + sage: pol = RBF(1.0, 0.1) + sage: pol == pol + True + sage: pol == copy(pol) + False """ + cdef Polynomial pol = other + cdef Py_ssize_t d1 = self.degree() - cdef Py_ssize_t d2 = other.degree() + cdef Py_ssize_t d2 = pol.degree() # Special case constant polynomials if d1 <= 0 and d2 <= 0: - return richcmp(self[0], other[0], op) + return richcmp(self[0], pol[0], op) # For different degrees, compare the degree if d1 != d2: @@ -979,9 +1015,10 @@ cdef class Polynomial(CommutativeAlgebraElement): cdef Py_ssize_t i for i in reversed(range(d1+1)): x = self.get_unsafe(i) - y = other[i] - if x != y: - return richcmp_not_equal(x, y, op) + y = pol.get_unsafe(i) + res = richcmp_item(x, y, op) + if res is not NotImplemented: + return res return rich_to_bool(op, 0) def __nonzero__(self): @@ -9451,7 +9488,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f.homogenize('x') 3*x^2 - In positive characterstic, the degree can drop in this case:: + In positive characteristic, the degree can drop in this case:: sage: R. = GF(2)[] sage: f = x + 1 diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index a5e76ea7f10..e71d85309ca 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -39,7 +39,7 @@ from sage.rings.polynomial.polynomial_singular_interface import Polynomial_singular_repr from sage.libs.pari.all import pari_gen -from sage.structure.richcmp import richcmp, richcmp_not_equal, rich_to_bool, rich_to_bool_sgn +from sage.structure.richcmp import richcmp, richcmp_item, rich_to_bool, rich_to_bool_sgn from sage.structure.element import coerce_binop from sage.rings.infinity import infinity, Infinity @@ -687,8 +687,9 @@ def _richcmp_(self, other, op): for i in sorted(degs, reverse=True): x = self[i] y = other[i] - if x != y: - return richcmp_not_equal(x, y, op) + res = richcmp_item(x, y, op) + if res is not NotImplemented: + return res return rich_to_bool(op, 0) def shift(self, n): diff --git a/src/sage/rings/power_series_pari.pyx b/src/sage/rings/power_series_pari.pyx index 5a242b1a5fe..e37e0a37186 100644 --- a/src/sage/rings/power_series_pari.pyx +++ b/src/sage/rings/power_series_pari.pyx @@ -400,8 +400,8 @@ cdef class PowerSeries_pari(PowerSeries): """ if len(kwds) >= 1: name = self._parent.variable_name() - if kwds.has_key(name): # the series variable is specified by a keyword - if len(x) > 0: + if name in kwds: # the series variable is specified by a keyword + if len(x): raise ValueError("must not specify %s keyword and positional argument" % name) x = [kwds[name]] del kwds[name] diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 64be36a52bc..3e66bf4df67 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -39,6 +39,8 @@ True sage: RationalField() is RationalField() True + sage: Q in Fields().Infinite() + True AUTHORS: @@ -531,8 +533,8 @@ def primes_of_bounded_norm_iter(self, B): except (TypeError, AttributeError): raise TypeError("%s is not valid bound on prime ideals" % B) - if B<2: - raise StopIteration + if B < 2: + return from sage.arith.all import primes for p in primes(B+1): diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index df9d736c5a4..d892c0985aa 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -190,16 +190,16 @@ def mpfr_prec_min(): sage: from sage.rings.real_mpfr import mpfr_prec_min sage: mpfr_prec_min() - 2 + 1 sage: R = RealField(2) sage: R(2) + R(1) 3.0 sage: R(4) + R(1) 4.0 - sage: R = RealField(1) + sage: R = RealField(0) Traceback (most recent call last): ... - ValueError: prec (=1) must be >= 2 and <= 2147483391 + ValueError: prec (=0) must be >= 1 and <= 2147483391 """ return MPFR_PREC_MIN @@ -218,7 +218,7 @@ def mpfr_prec_max(): sage: R = RealField(2^31-256) Traceback (most recent call last): ... - ValueError: prec (=2147483392) must be >= 2 and <= 2147483391 + ValueError: prec (=2147483392) must be >= 1 and <= 2147483391 """ global MY_MPFR_PREC_MAX return MY_MPFR_PREC_MAX @@ -353,7 +353,7 @@ mpfr_set_exp_max(mpfr_get_emax_max()) from sage.arith.long cimport pyobject_to_long cdef dict rounding_modes = dict(RNDN=MPFR_RNDN, RNDZ=MPFR_RNDZ, - RNDD=MPFR_RNDD, RNDU=MPFR_RNDU, RNDA=MPFR_RNDA) + RNDD=MPFR_RNDD, RNDU=MPFR_RNDU, RNDA=MPFR_RNDA, RNDF=MPFR_RNDF) cdef double LOG_TEN_TWO_PLUS_EPSILON = 3.321928094887363 # a small overestimate of log(10,2) @@ -384,6 +384,8 @@ cpdef RealField(int prec=53, int sci_not=0, rnd=MPFR_RNDN): - ``'RNDZ'`` -- round towards zero - ``'RNDU'`` -- round towards plus infinity - ``'RNDA'`` -- round away from zero + - ``'RNDF'`` -- faithful rounding (currently experimental; not + guaranteed correct for every operation) - for specialized applications, the rounding mode can also be given as an integer value of type ``mpfr_rnd_t``. However, the exact values are unspecified. @@ -472,6 +474,8 @@ cdef class RealField_class(sage.rings.ring.Field): Real Field with 100 bits of precision and rounding RNDD sage: RealField(100, rnd="RNDA") Real Field with 100 bits of precision and rounding RNDA + sage: RealField(100, rnd="RNDF") + Real Field with 100 bits of precision and rounding RNDF sage: RealField(100, rnd=0) Real Field with 100 bits of precision sage: RealField(100, rnd=1) @@ -482,14 +486,16 @@ cdef class RealField_class(sage.rings.ring.Field): Real Field with 100 bits of precision and rounding RNDD sage: RealField(100, rnd=4) Real Field with 100 bits of precision and rounding RNDA + sage: RealField(100, rnd=5) + Real Field with 100 bits of precision and rounding RNDF sage: RealField(100, rnd=3.14) Traceback (most recent call last): ... - ValueError: rounding mode (=3.14000000000000) must be one of ['RNDA', 'RNDZ', 'RNDD', 'RNDU', 'RNDN'] - sage: RealField(100, rnd=5) + ValueError: rounding mode (=3.14000000000000) must be one of ['RNDA', 'RNDD', 'RNDF', 'RNDN', 'RNDU', 'RNDZ'] + sage: RealField(100, rnd=6) Traceback (most recent call last): ... - ValueError: unknown rounding mode 5 + ValueError: unknown rounding mode 6 sage: RealField(100, rnd=10^100) Traceback (most recent call last): ... @@ -4419,7 +4425,7 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: r = -1.0 sage: r.eint() - NaN + -0.219383934395520 """ cdef RealNumber x = self._new() if (self._parent).__prec > SIG_PREC_THRESHOLD: sig_on() @@ -5275,7 +5281,7 @@ cdef class RealNumber(sage.structure.element.RingElement): if algorithm == 1: x = self._new() sig_on() - mpfr_root(x.value, self.value, n, (self._parent).rnd) + mpfr_rootn_ui(x.value, self.value, n, (self._parent).rnd) sig_off() return x diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 022cf77ccae..9764498d6d9 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -2628,7 +2628,7 @@ def isogeny_class(self): The array of isogenies themselves is not filled out but only contains those used to construct the class, the other entries - containing the interger 0. This will be changed when the + containing the integer 0. This will be changed when the class :class:`EllipticCurveIsogeny` allowed composition. In this case we used `2`-isogenies to go from 0 to 2 and from 1 to 3, and `3`-isogenies to go from 0 to 1 and from 2 to 3:: diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index 9004ce09745..ca268e1dd34 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -532,7 +532,7 @@ def _maybe_borels(E, L, patience=100): sage: sage.schemes.elliptic_curves.gal_reps_number_field._maybe_borels(E, primes(20)) [2, 3] - Here the curve really does possess isognies of degrees 2 and 3:: + Here the curve really does possess isogenies of degrees 2 and 3:: sage: [len(E.isogenies_prime_degree(l)) for l in [2,3]] [1, 1] diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index 10669a2794f..3d270ebf9d7 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -535,7 +535,7 @@ def inf_max_abs(f, g, D): INPUT: - - ``f``, ``g`` (polynomials) -- real univariate polynomaials + - ``f``, ``g`` (polynomials) -- real univariate polynomials - ``D`` (UnionOfIntervals) -- a subset of `\RR` diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py index ffe6553fe88..677d5b74ff6 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_class.py +++ b/src/sage/schemes/elliptic_curves/isogeny_class.py @@ -619,7 +619,7 @@ def __init__(self, E): The array of isogenies themselves is not filled out but only contains those used to construct the class, the other entries - containing the interger 0. This will be changed when the + containing the integer 0. This will be changed when the class :class:`EllipticCurveIsogeny` allowed composition. In this case we used `2`-isogenies to go from 0 to 2 and from 1 to 3, and `3`-isogenies to go from 0 to 1 and from 2 to 3:: diff --git a/src/sage/schemes/hyperelliptic_curves/mestre.py b/src/sage/schemes/hyperelliptic_curves/mestre.py index 6107c01c562..e916364e38d 100644 --- a/src/sage/schemes/hyperelliptic_curves/mestre.py +++ b/src/sage/schemes/hyperelliptic_curves/mestre.py @@ -108,7 +108,7 @@ def HyperellipticCurve_from_invariants(i, reduced=True, precision=None, TypeError: F (=0) must have degree 2 - Igusa-Clebsch invariants also only work over fields of charateristic + Igusa-Clebsch invariants also only work over fields of characteristic different from 2, 3, and 5, so another algorithm will be needed for fields of those characteristics. See also :trac:`12200`:: diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index 6de57b970fc..cb7802a3e57 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -742,7 +742,7 @@ def function_value(self, point): OUTPUT: - - an interger or a rational number. + - an integer or a rational number. EXAMPLES:: diff --git a/src/sage/schemes/toric/points.py b/src/sage/schemes/toric/points.py index 6d83d0af779..8ba5a8d876e 100644 --- a/src/sage/schemes/toric/points.py +++ b/src/sage/schemes/toric/points.py @@ -915,7 +915,7 @@ def solutions(self, inhomogeneous_equations, log_range): if len(log_range) <= 2: for log_t in self.solutions_serial(inhomogeneous_equations, log_range): yield log_t - raise StopIteration + return # Parallelize the outermost loop of the Cartesian product work = [([[r]] + log_range[1:],) for r in log_range[0]] from sage.parallel.decorate import Parallel diff --git a/src/sage/schemes/toric/sheaf/klyachko.py b/src/sage/schemes/toric/sheaf/klyachko.py index fcfe90901c9..572cc3cb9d5 100644 --- a/src/sage/schemes/toric/sheaf/klyachko.py +++ b/src/sage/schemes/toric/sheaf/klyachko.py @@ -948,7 +948,7 @@ def random_deformation(self, epsilon=None): OUTPUT: - A new Klyachko bundle with randomly perturbed moduly. In + A new Klyachko bundle with randomly perturbed moduli. In particular, the same Chern classes. EXAMPLES:: diff --git a/src/sage/sets/recursively_enumerated_set.pyx b/src/sage/sets/recursively_enumerated_set.pyx index d592ec0f7a6..27facd9fc13 100644 --- a/src/sage/sets/recursively_enumerated_set.pyx +++ b/src/sage/sets/recursively_enumerated_set.pyx @@ -281,7 +281,7 @@ def RecursivelyEnumeratedSet(seeds, successors, structure=None, TESTS: - The succesors method is an attribute:: + The successors method is an attribute:: sage: R = RecursivelyEnumeratedSet([1], lambda x: [x+1, x-1]) sage: R.successors(4) @@ -296,7 +296,8 @@ def RecursivelyEnumeratedSet(seeds, successors, structure=None, (1, 2, 3) """ if structure is None: - if enumeration is None: enumeration = 'breadth' + if enumeration is None: + enumeration = 'breadth' return RecursivelyEnumeratedSet_generic(seeds, successors, enumeration, max_depth, facade=facade, category=category) if structure == 'symmetric': diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index af800710aab..405080f1be5 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -3086,7 +3086,7 @@ cdef class CommutativeRingElement(RingElement): if not isinstance(P, IntegralDomain): raise NotImplementedError('sqrt() with all=True is only implemented for integral domains, not for %s' % P) if P.characteristic()==2 or sq_rt==0: - #0 has only one square root, and in charasteristic 2 everything also has only 1 root + #0 has only one square root, and in characteristic 2 everything also has only 1 root return [ sq_rt ] return [ sq_rt, -sq_rt ] return sq_rt diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 41f7421a12e..19229698f89 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -1853,10 +1853,9 @@ cdef class Parent(sage.structure.category_object.CategoryObject): We check that :trac:`23184` has been resolved:: sage: QQ['x', 'y']._generic_coerce_map(QQ).category_for() - Category of unique factorization domains + Category of infinite unique factorization domains sage: QQ[['x']].coerce_map_from(QQ).category_for() Category of euclidean domains - """ if isinstance(S, type): category = None diff --git a/src/sage/structure/richcmp.pxd b/src/sage/structure/richcmp.pxd index aa6115a1d37..a5730ebbeea 100644 --- a/src/sage/structure/richcmp.pxd +++ b/src/sage/structure/richcmp.pxd @@ -3,6 +3,8 @@ from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE from cpython.object cimport PyObject_RichCompare as richcmp +cpdef richcmp_item(x, y, int op) + cpdef inline richcmp_not_equal(x, y, int op): """ Like ``richcmp(x, y, op)`` but assuming that `x` is not equal to `y`. diff --git a/src/sage/structure/richcmp.pyx b/src/sage/structure/richcmp.pyx index 26015c52ab4..d5de65a7f20 100644 --- a/src/sage/structure/richcmp.pyx +++ b/src/sage/structure/richcmp.pyx @@ -105,6 +105,204 @@ def richcmp(x, y, int op): return PyObject_RichCompare(x, y, op) +cpdef richcmp_item(x, y, int op): + """ + This function is meant to implement lexicographic rich comparison + of sequences (lists, vectors, polynomials, ...). + The inputs ``x`` and ``y`` are corresponding items of such lists + which should compared. + + INPUT: + + - ``x``, ``y`` -- arbitrary Python objects. Typically, these are + ``X[i]`` and ``Y[i]`` for sequences ``X`` and ``Y``. + + - ``op`` -- comparison operator (one of ``op_LT`, ``op_LE``, + ``op_EQ``, ``op_NE``, ``op_GT``, ``op_GE``) + + OUTPUT: + + Assuming that ``x = X[i]`` and ``y = Y[i]``: + + - if the comparison ``X {op} Y`` (where ``op`` is the given + operation) could not be decided yet (i.e. we should compare the + next items in the list): return ``NotImplemented`` + + - otherwise, if the comparison ``X {op} Y`` could be decided: + return ``x {op} y``, which should then also be the result for + ``X {op} Y``. + + .. NOTE:: + + Since ``x {op} y`` cannot return ``NotImplemented``, the two + cases above are mutually exclusive. + + The semantics of the comparison is different from Python lists or + tuples in the case that the order is not total. Assume that ``A`` + and ``B`` are lists whose rich comparison is implemented using + ``richcmp_item`` (as in EXAMPLES below). Then + + - ``A == B`` iff ``A[i] == B[i]`` for all indices `i`. + + - ``A != B`` iff ``A[i] != B[i]`` for some index `i`. + + - ``A < B`` iff ``A[i] < B[i]`` for some index `i` and + for all `j < i`, ``A[j] <= B[j]``. + + - ``A <= B`` iff ``A < B`` or ``A[i] <= B[i]`` for all `i`. + + - ``A > B`` iff ``A[i] > B[i]`` for some index `i` and + for all `j < i`, ``A[j] >= B[j]``. + + - ``A >= B`` iff ``A > B`` or ``A[i] >= B[i]`` for all `i`. + + See below for a detailed description of the exact semantics of + ``richcmp_item`` in general. + + EXAMPLES:: + + sage: from sage.structure.richcmp import * + sage: @richcmp_method + ....: class Listcmp(list): + ....: def __richcmp__(self, other, op): + ....: for i in range(len(self)): # Assume equal lengths + ....: res = richcmp_item(self[i], other[i], op) + ....: if res is not NotImplemented: + ....: return res + ....: return rich_to_bool(op, 0) # Consider the lists to be equal + sage: a = Listcmp([0, 1, 3]) + sage: b = Listcmp([0, 2, 1]) + sage: a == a + True + sage: a != a + False + sage: a < a + False + sage: a <= a + True + sage: a > a + False + sage: a >= a + True + sage: a == b, b == a + (False, False) + sage: a != b, b != a + (True, True) + sage: a < b, b > a + (True, True) + sage: a <= b, b >= a + (True, True) + sage: a > b, b < a + (False, False) + sage: a >= b, b <= a + (False, False) + + The above tests used a list of integers, where the result of + comparisons are the same as for Python lists. + + If we want to see the difference, we need more general entries in + the list. The comparison rules are made to be consistent with + setwise operations. If `A` and `B` are sets, we define ``A {op} B`` + to be true if ``a {op} B`` is true for every `a` in `A` and + `b` in `B`. Interval comparisons are a special case of this. For + lists of non-empty(!) sets, we want that ``[A1, A2] {op} [B1, B2]`` + is true if and only if ``[a1, a2] {op} [b1, b2]`` is true for all + elements. We verify this:: + + sage: @richcmp_method + ....: class Setcmp(tuple): + ....: def __richcmp__(self, other, op): + ....: return all(richcmp(x, y, op) for x in self for y in other) + sage: sym = {op_EQ: "==", op_NE: "!=", op_LT: "<", op_GT: ">", op_LE: "<=", op_GE: ">="} + sage: for A1 in Set(range(4)).subsets(): # long time + ....: if not A1: continue + ....: for B1 in Set(range(4)).subsets(): + ....: if not B1: continue + ....: for A2 in Set(range(4)).subsets(): + ....: if not A2: continue + ....: for B2 in Set(range(3)).subsets(): + ....: if not B2: continue + ....: L1 = Listcmp([Setcmp(A1), Setcmp(A2)]) + ....: L2 = Listcmp([Setcmp(B1), Setcmp(B2)]) + ....: for op in range(6): + ....: reslist = richcmp(L1, L2, op) + ....: reselt = all(richcmp([a1, a2], [b1, b2], op) for a1 in A1 for a2 in A2 for b1 in B1 for b2 in B2) + ....: assert reslist is reselt + + EXACT SEMANTICS: + + Above, we only described how ``richcmp_item`` behaves when it is + used to compare sequences. Here, we specify the exact semantics. + First of all, recall that the result of ``richcmp_item(x, y, op)`` + is either ``NotImplemented`` or ``x {op} y``. + + - if ``op`` is ``==``: return ``NotImplemented`` if ``x == y``. + If ``x == y`` is false, then return ``x == y``. + + - if ``op`` is ``!=``: return ``NotImplemented`` if not ``x != y``. + If ``x != y`` is true, then return ``x != y``. + + - if ``op`` is ``<``: return ``NotImplemented`` if ``x == y``. + If ``x < y`` or not ``x <= y``, return ``x < y``. + Otherwise (if both ``x == y`` and ``x < y`` are false but + ``x <= y`` is true), return ``NotImplemented``. + + - if ``op`` is ``<=``: return ``NotImplemented`` if ``x == y``. + If ``x < y`` or not ``x <= y``, return ``x <= y``. + Otherwise (if both ``x == y`` and ``x < y`` are false but + ``x <= y`` is true), return ``NotImplemented``. + + - the ``>`` and ``>=`` operators are analogous to ``<`` and ``<=``. + """ + if op == Py_NE: + res = (x != y) + if not res: + return NotImplemented + return res # (x != y) --> True + + # If x and y are equal, we cannot decide + res = (x == y) + if res: + return NotImplemented + + if op == Py_EQ: + return res # not (x == y) --> False + + # At this point, {op} is < or <= or > or >=. In the comments below, + # we always refer to < and <= but > and >= are obviously analogous. + + # Compute x {op} y and convert to boolean (0 or 1) + res = PyObject_RichCompare(x, y, op) + cdef bint bres = res + + # true (1) for <= and >= and false (0) for < and > + cdef bint op_is_not_strict = op & 1 + + if bres != op_is_not_strict: + # If we are asked to compute (x < y) and (x < y) is true, + # return (x < y) which is true. + # If we are asked to compute (x <= y) and (x <= y) is false, + # return (x <= y) which is false. + return res + + # Finally, check the inequality with the other strictness + # (< becomes <= and vice versa; this corresponds to replacing op by + # op ^ 1). This check is redundant in the typical case that (x <= y) + # is equivalent to (x < y or x == y): since (x == y) returned false, + # we expect that this PyObject_RichCompare() call returns the same + # boolean result as the previous one. + cdef bint xres = PyObject_RichCompare(x, y, op ^ 1) + if xres == bres: # As expected + return res + + # OK, we are in a special case now. We checked that (x == y) is + # false, that (x < y) is false but (x <= y) is true. + # Since we want to give more importance to the < and <= results than + # the == result, we treat this case as equality. Therefore, we + # cannot decide. + return NotImplemented + + cdef slot_tp_richcompare(self, other, int op): """ Function to put in the ``tp_richcompare`` slot. diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index dfc65cc5f73..7130898086c 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -2208,7 +2208,7 @@ cdef class Expression(CommutativeRingElement): def _is_registered_constant_(self): """ - Return True if this symbolic expression is interally represented as + Return True if this symbolic expression is internally represented as a constant. This function is intended to provide an interface to query the internal diff --git a/src/sage/symbolic/series.pyx b/src/sage/symbolic/series.pyx index 6ebc12357f7..a0a5a510d3a 100644 --- a/src/sage/symbolic/series.pyx +++ b/src/sage/symbolic/series.pyx @@ -88,7 +88,7 @@ TESTS: Check that :trac:`20088` is fixed:: sage: ((1+x).series(x)^pi).series(x,3) - 1 + (pi)*x + (-1/2*pi + 1/2*pi^2)*x^2 + Order(x^3) + 1 + pi*x + (-1/2*pi + 1/2*pi^2)*x^2 + Order(x^3) Check that :trac:`14878` is fixed, this should take only microseconds:: @@ -281,7 +281,7 @@ cdef class SymbolicSeries(Expression): EXAMPLES:: sage: ex=(gamma(1-x)).series(x,3); ex - 1 + (euler_gamma)*x + (1/2*euler_gamma^2 + 1/12*pi^2)*x^2 + Order(x^3) + 1 + euler_gamma*x + (1/2*euler_gamma^2 + 1/12*pi^2)*x^2 + Order(x^3) sage: g=ex.power_series(SR); g 1 + euler_gamma*x + (1/2*euler_gamma^2 + 1/12*pi^2)*x^2 + O(x^3) sage: g.parent() diff --git a/src/sage/tensor/modules/free_module_linear_group.py b/src/sage/tensor/modules/free_module_linear_group.py index 156446b0ebb..efdcf021dff 100644 --- a/src/sage/tensor/modules/free_module_linear_group.py +++ b/src/sage/tensor/modules/free_module_linear_group.py @@ -1,7 +1,7 @@ r""" General linear group of a free module -The set `\mathrm{GL}(M)` of automorphisms (i.e. invertible endomorphims) of a +The set `\mathrm{GL}(M)` of automorphisms (i.e. invertible endomorphisms) of a free module of finite rank `M` is a group under composition of automorphisms, named the *general linear group* of `M`. In other words, `\mathrm{GL}(M)` is the group of units (i.e. invertible elements) of `\mathrm{End}(M)`, the @@ -41,7 +41,7 @@ class FreeModuleLinearGroup(UniqueRepresentation, Parent): Given a free module of finite rank `M` over a commutative ring `R`, the *general linear group* of `M` is the group `\mathrm{GL}(M)` of - automorphisms (i.e. invertible endomorphims) of `M`. It is the group of + automorphisms (i.e. invertible endomorphisms) of `M`. It is the group of units (i.e. invertible elements) of `\mathrm{End}(M)`, the endomorphism ring of `M`. diff --git a/src/sage/version.py b/src/sage/version.py index 4d100301684..1d98722b54f 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,4 +1,4 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '8.2.beta3' -date = '2018-01-17' +version = '8.2.beta4' +date = '2018-01-27' diff --git a/src/sage_setup/autogen/interpreters/__init__.py b/src/sage_setup/autogen/interpreters/__init__.py index 8535d0c8095..8dbdae26295 100644 --- a/src/sage_setup/autogen/interpreters/__init__.py +++ b/src/sage_setup/autogen/interpreters/__init__.py @@ -139,7 +139,7 @@ key=lambda c: c.name) # Tuple of (filename_root, extension, method) where filename_root is the -# root of the filename to be joined with "_".ext and +# root of the filename to be joined with "_".ext and # method is the name of a get_ method on InterpreterGenerator that returns # the contents of that file _INTERPRETER_SOURCES = [