diff --git a/.github/workflows/ci-cygwin-minimal.yml b/.github/workflows/ci-cygwin-minimal.yml index 97734216e85..c41e2617bd3 100644 --- a/.github/workflows/ci-cygwin-minimal.yml +++ b/.github/workflows/ci-cygwin-minimal.yml @@ -94,7 +94,7 @@ jobs: cygwin-stage-i-b: env: STAGE: i-b - TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi singledispatch pkgconfig pplpy + TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi pkgconfig pplpy LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} diff --git a/.github/workflows/ci-cygwin-standard.yml b/.github/workflows/ci-cygwin-standard.yml index 8268e0e75f1..9f7414961c2 100644 --- a/.github/workflows/ci-cygwin-standard.yml +++ b/.github/workflows/ci-cygwin-standard.yml @@ -94,7 +94,7 @@ jobs: cygwin-stage-i-b: env: STAGE: i-b - TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi singledispatch pkgconfig pplpy + TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi pkgconfig pplpy LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} diff --git a/.github/workflows/tox-gcc_spkg.yml b/.github/workflows/tox-gcc_spkg.yml index f9a9847f9a9..53efb6a7a6f 100644 --- a/.github/workflows/tox-gcc_spkg.yml +++ b/.github/workflows/tox-gcc_spkg.yml @@ -1,4 +1,4 @@ -name: Run SAGE_ROOT/tox.ini +name: Test Linux --without-system-gcc ## This GitHub Actions workflow runs SAGE_ROOT/tox.ini with select environments, ## whenever a GitHub pull request is opened or synchronized in a repository @@ -34,8 +34,9 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false + max-parallel: 5 matrix: - tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-eoan, ubuntu-focal, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, centos-7, centos-8, archlinux-latest, slackware-14.2, conda-forge, ubuntu-bionic-i386, ubuntu-eoan-i386, debian-buster-i386, centos-7-i386] + tox_system_factor: [ubuntu-trusty, ubuntu-focal, fedora-27, fedora-31, debian-buster-i386] tox_packages_factor: [minimal-gcc_spkg, standard-gcc_spkg] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} @@ -99,6 +100,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false + max-parallel: 1 matrix: tox_system_factor: [conda-forge-ubuntu] tox_packages_factor: [minimal-gcc_spkg, standard-gcc_spkg] diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index 445840229ef..25af9a97ff9 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -36,7 +36,7 @@ jobs: fail-fast: false max-parallel: 6 matrix: - tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-eoan, ubuntu-focal, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, centos-7, centos-8, archlinux-latest, slackware-14.2, conda-forge, ubuntu-bionic-i386, ubuntu-eoan-i386, debian-buster-i386, centos-7-i386] + tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-eoan, ubuntu-focal, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, centos-7, centos-8, gentoo, archlinux-latest, slackware-14.2, conda-forge, ubuntu-bionic-i386, ubuntu-eoan-i386, debian-buster-i386, centos-7-i386] tox_packages_factor: [maximal] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 67ad95c4c93..55ac5e8ee8b 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -36,7 +36,7 @@ jobs: fail-fast: false max-parallel: 20 matrix: - tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-eoan, ubuntu-focal, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, centos-7, centos-8, archlinux-latest, slackware-14.2, conda-forge, ubuntu-bionic-i386, ubuntu-eoan-i386, debian-buster-i386, centos-7-i386] + tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-eoan, ubuntu-focal, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, centos-7, centos-8, gentoo, archlinux-latest, slackware-14.2, conda-forge, ubuntu-bionic-i386, ubuntu-eoan-i386, debian-buster-i386, centos-7-i386] tox_packages_factor: [minimal, standard] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} diff --git a/.github/workflows/update-cygwin-yml.sh b/.github/workflows/update-cygwin-yml.sh index 247fe20e187..bc1d195a9f4 100755 --- a/.github/workflows/update-cygwin-yml.sh +++ b/.github/workflows/update-cygwin-yml.sh @@ -1,2 +1,2 @@ #!/usr/bin/env bash -for X in standard-python2 minimal; do sed 's/\[standard\]/['$X']/g;s/CI cygwin-standard/CI cygwin-'$X'/g;' ci-cygwin-standard.yml > ci-cygwin-$X.yml; done +for X in minimal; do sed 's/\[standard\]/['$X']/g;s/CI cygwin-standard/CI cygwin-'$X'/g;' ci-cygwin-standard.yml > ci-cygwin-$X.yml; done diff --git a/Makefile b/Makefile index 2e756b9f839..d9968fe48e2 100644 --- a/Makefile +++ b/Makefile @@ -110,6 +110,7 @@ bootstrap-clean: rm -rf config configure build/make/Makefile-auto.in rm -f src/doc/en/installation/*.txt rm -rf src/doc/en/reference/spkg/*.rst + rm -f src/doc/en/reference/repl/*.txt # Remove absolutely everything which isn't part of the git repo maintainer-clean: distclean bootstrap-clean diff --git a/VERSION.txt b/VERSION.txt index 444bcb34712..0f4841857d2 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 9.2.beta2, Release Date: 2020-06-26 +SageMath version 9.2.beta3, Release Date: 2020-07-04 diff --git a/bootstrap b/bootstrap index 60c65eb18f4..1e0fb4452ce 100755 --- a/bootstrap +++ b/bootstrap @@ -160,7 +160,7 @@ save () { # Create configure tarball echo "Creating $NEWCONFBALL..." mkdir -p upstream - tar zcf "$NEWCONFBALL" configure config/* build/make/Makefile-auto.in src/doc/en/installation/*.txt src/doc/en/reference/spkg/*.rst + tar zcf "$NEWCONFBALL" configure config/* build/make/Makefile-auto.in src/doc/en/installation/*.txt src/doc/en/reference/spkg/*.rst src/doc/en/reference/repl/*.txt # Update version echo "$NEWCONFVERSION" >$PKG/package-version.txt diff --git a/build/bin/sage-print-system-package-command b/build/bin/sage-print-system-package-command index fa3f1557494..ccbb4986f17 100755 --- a/build/bin/sage-print-system-package-command +++ b/build/bin/sage-print-system-package-command @@ -58,6 +58,9 @@ case $system:$command in @(fedora*|redhat*|centos*):install) [ -n "$system_packages" ] && echo "${PROMPT}${SUDO}yum install $system_packages" ;; + gentoo*:install) + [ -n "$system_packages" ] && echo "${PROMPT}${SUDO}emerge $system_packages" + ;; arch*:install) [ -n "$system_packages" ] && echo "${PROMPT}${SUDO}pacman -S $system_packages" ;; diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 3d47c0cc84b..7a9d35f8a3b 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -3,7 +3,7 @@ # sage-spkg: install a Sage package # # This script is typically invoked by giving the command -# sage -i ... +# sage {-i|-p} ... # # Options can be: # -s: do not delete temporary build directory @@ -75,12 +75,10 @@ export LC_ALL=C.UTF-8 usage() { cat < +Usage: sage {-i|-p} -If is a URL, download and install it. If it is a file -name, install it. Otherwise, search Sage's list of packages (see -'sage --package list') for a matching package, and if a match is -found, install it. +Search Sage's list of packages (see 'sage --package list') for a +matching package, and if a match is found, install it. Options: -s: do not delete the temporary build directory @@ -251,37 +249,16 @@ done # Figure out the package filename, download it if needed. ################################################################## # One should be able to install a package using -# sage -i where can be any of the -# following values: -# -# 1a. /path/to/-x.y.z.spkg, i.e. the package is found somewhere -# in your file system and you're giving an absolute path. -# 1b. relative/path/to/-x.y.z.spkg, the same with a relative -# path. -# 2a. -x.y.z, i.e. the name of the package plus the package's -# version numbers. -# 2b. -x.y.z.spkg, i.e. the name of the package in addition to -# the version numbers and the ".spkg" extension. -# 3. , i.e. the name of the package without a version number. -# 4. /-x.y.z.spkg, i.e. the full URL where the package -# is hosted. Any local packages matching are ignored. -# -# In cases 2a, 2b and 3 we first look locally inside spkg/* for a -# matching package. Otherwise, we try to download it. In all cases, -# we reduce to case 1a. -# -# See #7544 and #12602. -# +# sage -i PKG_SRC="$1" # Does PKG_SRC contain a slash? if echo "$PKG_SRC" | grep / >/dev/null; then - PKG_HAS_PATH=yes + echo >&2 "Error: Installing old-style SPKGs is no longer supported" + exit 1 fi -# PKG_NAME is the last path component without .spkg -# This already reduces case 2b to case 2a. -PKG_NAME=`basename "$PKG_SRC" | sed 's/\.spkg$//'` -PKG_BASE=`echo "$PKG_NAME" | sed 's/-.*//'` +PKG_NAME="$PKG_SRC" +PKG_BASE=`echo "$PKG_NAME" | sed 's/-.*//'` # strip version number # USE_LOCAL_SCRIPTS is a flag that if non-empty will cause # this script to try to install the package using local metadata @@ -289,39 +266,31 @@ PKG_BASE=`echo "$PKG_NAME" | sed 's/-.*//'` # the value of this flag is set in the next codeblock USE_LOCAL_SCRIPTS= -if [ -f "$PKG_SRC" ]; then - # PKG_SRC is a file. If it is given by a relative path, prepend `pwd` - # (reduce case 1b to 1a) - if ! echo "$PKG_SRC" | grep '^/' >/dev/null; then - PKG_SRC="`pwd`/$PKG_SRC" - fi -elif [ -z "$PKG_HAS_PATH" ]; then - # If PKG_SRC is not an existing file and doesn't contain a slash, - # we are in case 2a or 3. If version in 2a matches the version in - # build/pkgs or we are in case 3 use the local scripts, otherwise - # we try to find a package in upstream - PKG_VER="${PKG_NAME#${PKG_BASE}}" - PKG_VER="${PKG_VER#-}" - PKG_SCRIPTS="$SAGE_ROOT/build/pkgs/$PKG_BASE" - LOCAL_PKG_VER=`cat $PKG_SCRIPTS/package-version.txt 2>/dev/null` - if [ -n "$LOCAL_PKG_VER" ] && [ -z "$PKG_VER" -o "$PKG_VER" = "$LOCAL_PKG_VER" ]; then - PKG_VER="$LOCAL_PKG_VER" - if [ -z "$PKG_VER" ]; then - PKG_NAME="${PKG_BASE}" - else - PKG_NAME="${PKG_BASE}-${PKG_VER}" - fi - USE_LOCAL_SCRIPTS=yes - PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'` - PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini" | sed "s/VERSION/$PKG_BASE_VER/"` - echo "Found local metadata for $PKG_NAME" - - # Warning for experimental packages - if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" -a $INFO = 0 ]; then - if [ $YES != 1 ]; then - # We use /dev/tty here because our output may be redirected - # to a logfile, or line-buffered. - write_to_tty </dev/null` +PKG_VER="$LOCAL_PKG_VER" +if [ -z "$PKG_VER" ]; then + PKG_NAME="${PKG_BASE}" +else + PKG_NAME="${PKG_BASE}-${PKG_VER}" +fi +USE_LOCAL_SCRIPTS=yes +PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'` +PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini" | sed "s/VERSION/$PKG_BASE_VER/"` +echo "Found local metadata for $PKG_NAME" + +# Warning for experimental packages +if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" -a $INFO = 0 ]; then + if [ $YES != 1 ]; then + # We use /dev/tty here because our output may be redirected + # to a logfile, or line-buffered. + write_to_tty < /dev/tty 2>&1 - else - answer=n - fi - case "$answer" in - n*|N*) exit 1;; - esac - # Confirm the user's input. (This gives important - # feedback to the user when output is redirected to a logfile.) - echo > /dev/tty "OK, installing $PKG_NAME now..." - fi + if [ $? -ne 0 ]; then + echo "Terminal not available for prompting. Use 'sage -i -y $PKG_BASE'" + echo "to install experimental packages in non-interactive mode." + YES=-1 fi - - else - cd "$SAGE_DISTFILES" - for spkg in `ls -1t ${PKG_NAME}.spkg ${PKG_NAME}-*.spkg 2>/dev/null`; do - if [ -f "$spkg" ]; then - # Found a good package - echo "Found package $PKG_NAME in $SAGE_DISTFILES/$spkg" - PKG_SRC="`pwd`/$spkg" - PKG_NAME=`basename "$spkg" | sed 's/\.spkg$//'` - break - fi - done + if [ $YES != -1 ]; then + read -p "Are you sure you want to continue [Y/n]? " answer < /dev/tty > /dev/tty 2>&1 + else + answer=n + fi + case "$answer" in + n*|N*) exit 1;; + esac + # Confirm the user's input. (This gives important + # feedback to the user when output is redirected to a logfile.) + echo > /dev/tty "OK, installing $PKG_NAME now..." fi fi @@ -376,154 +331,8 @@ if [ ! -f "$PKG_SRC" ]; then fi PKG_SRC="$SAGE_DISTFILES/$PKG_NAME_UPSTREAM" else - # Handle all the legacy cruft. This branch can be deleted once - # we get rid of old-style spkgs - if [ $YES = -1 ]; then - # User provided -n option, so don't even try to download the package" - echo "Old-style packages disabled by use of '-n' option" - exit 1 - fi - if [ $INFO -eq 0 ]; then - echo "Attempting to download package $PKG_NAME" - else - echo "Attempting to get on-line info for package $PKG_NAME" - fi - - # Reduce everything to case 4: full URL. - if [ -n "$PKG_HAS_PATH" ]; then - PKG_URL="$PKG_SRC" - else - # Handle cases 2a and 3, where the package name is something - # like "foo" or "foo-1.2.3". - MIRROR=$(sage-download-file --print-fastest-mirror)/spkg - if [ $? -ne 0 ]; then - error_msg "Error downloading list of packages" - exit 1 - fi - for repo in optional experimental huge; do - # Download the list of packages. - echo ">>> Checking online list of $repo packages." - # File inside DOT_SAGE should be writable - repolist="${DOT_SAGE}/${repo}.list" - sage-download-file --quiet "$MIRROR/$repo/list" $repolist - if [ $? -ne 0 ]; then - rm -f $repolist - error_msg "Error downloading $MIRROR/$repo/list" - exit 1 - fi - - # The contrived sed commands print out either ${PKG_NAME} if - # it appears as a complete line or some string starting with - # ${PKG_NAME}- whichever occurs first. - # Tested with GNU sed, BSD sed (on OS X) and Solaris sed. - pkg=`sed -n -f <( echo "/^${PKG_NAME}\$/{p;q;}" && echo "/^${PKG_NAME}-/{p;q;}" ) $repolist` - rm -f $repolist - if [ -n "$pkg" ]; then - echo ">>> Found $pkg" - PKG_NAME=$pkg - - # If INFO is set, try downloading only the .txt file - if [ $INFO -eq 1 ]; then - PKG_URL="$MIRROR/$repo/$pkg.txt" - sage-download-file --quiet "$PKG_URL" && exit 0 - # If the download failed (for whatever reason), - # fall through and use the .spkg file. - else - if [ $YES != 1 ]; then - # Warn and ask the user if downloading an - # experimental package. - # Add a deprecation note for other packages, - # since old-style packages are deprecated. - if [ $repo = experimental ]; then - write_to_tty < /dev/tty 2>&1 - else - answer=n - fi - case "$answer" in - n*|N*) exit 1;; - esac - else - # Deprecated since Sage 6.9, Trac #19158 - write_to_tty < /dev/tty 2>&1 - elif [ $YES = -1 ]; then - answer=n - else - answer=y - fi - case "$answer" in - n*|N*) exit 1;; - esac - fi - # Confirm the user's input. (This gives important - # feedback to the user when output is redirected to a logfile.) - echo > /dev/tty "OK, installing $PKG_NAME now..." - fi - fi - PKG_URL="$MIRROR/$repo/$pkg.spkg" - break - fi - done - - if [ -z "$PKG_URL" ]; then - echo >&2 "Error: could not find a package matching $PKG_NAME" - echo >&2 " Try 'sage --package list' to see the available packages" - echo >&2 " $(sage-package apropos $PKG_NAME)" - exit 1 - fi - fi - - # Trac #5852: check write permissions - mkdir -p "$SAGE_DISTFILES" - if [ ! -w "$SAGE_DISTFILES" ]; then - error_msg "Error: no write access to packages directory $SAGE_PACKAGES" - exit 1 - fi - cd "$SAGE_DISTFILES" || exit $? - - # Download to a temporary file (such that we don't end up with a - # corrupted .spkg file). - PKG_TMP="${PKG_URL##*/}.tmp" - echo ">>> Trying to download $PKG_URL" - sage-download-file "$PKG_URL" "$PKG_TMP" - if [ $? -ne 0 ]; then - # Delete failed download - rm -f "$PKG_TMP" - error_msg "Error downloading $PKG_URL" - exit 1 - fi - - PKG_SRC="`pwd`/${PKG_URL##*/}" - mv -f "$PKG_TMP" "$PKG_SRC" + echo >&2 "Error: Installing old-style SPKGs is no longer supported" + exit 1 fi fi @@ -636,21 +445,8 @@ if [ "$USE_LOCAL_SCRIPTS" = yes ]; then exit 1 fi else - # Old-style package (deprecated) - echo "Extracting package $PKG_SRC" - ls -l "$PKG_SRC" - - sage-uncompress-spkg "$PKG_SRC" - if [ $? -ne 0 ]; then - error_msg "Error: failed to extract $PKG_SRC" - exit 1 - fi - - cd "$PKG_NAME" - if [ $? -ne 0 ]; then - error_msg "Error: after extracting, the directory '$PKG_NAME' does not exist" - exit 1 - fi + echo >&2 "Error: Installing old-style SPKGs is no longer supported." + exit 1 fi echo "Finished extraction" @@ -1049,4 +845,4 @@ fi touch "$SAGE_LOCAL/lib/sage-force-relocate.txt" -echo "Finished installing $PKG_NAME.spkg" +echo "Finished installing $PKG_NAME" diff --git a/build/bin/sage-system-python b/build/bin/sage-system-python index 7ba5ed30257..9e18639da1d 100755 --- a/build/bin/sage-system-python +++ b/build/bin/sage-system-python @@ -20,7 +20,9 @@ fi # # See https://trac.sagemath.org/ticket/29090 -PYTHONS="python3 python3.8 python3.7 python2.7 python python3.6 python2" +# Trac #29890: Our first choice is "python", not "python3". This is to avoid +# a defect of sage_bootstrap on macOS regarding SSL URLs. +PYTHONS="python python3 python3.8 python3.7 python2.7 python3.6 python2" for PY in $PYTHONS; do PYTHON="$(PATH="$SAGE_ORIG_PATH" command -v $PY)" if [[ -n "$PYTHON" ]]; then diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index e298620f2ea..95826412b5c 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -56,6 +56,15 @@ EOF EXISTS="2>/dev/null >/dev/null yum install -y --downloadonly" INSTALL="yum install -y" ;; + gentoo*) + cat <&2 "SAGE_LOCAL undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -cd src - -sdh_pip_install . - -if [ $? -ne 0 ]; then - echo "Error installing backports_abc ... exiting" - exit 1 -fi diff --git a/build/pkgs/backports_functools_lru_cache/SPKG.rst b/build/pkgs/backports_functools_lru_cache/SPKG.rst deleted file mode 100644 index b8bcbc948e7..00000000000 --- a/build/pkgs/backports_functools_lru_cache/SPKG.rst +++ /dev/null @@ -1,8 +0,0 @@ -backports.functools_lru_cache -============================= - -Description ------------ - -A backport of functools.lru_cache from Python 3.3 as published at -ActiveState. diff --git a/build/pkgs/backports_functools_lru_cache/checksums.ini b/build/pkgs/backports_functools_lru_cache/checksums.ini deleted file mode 100644 index 19e72765bcd..00000000000 --- a/build/pkgs/backports_functools_lru_cache/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=backports.functools_lru_cache-VERSION.tar.gz -sha1=35a5895d22875cd024694d3c7393a793e9fd653d -md5=20f53f54cd3f04b3346ce75a54959754 -cksum=4241725171 diff --git a/build/pkgs/backports_functools_lru_cache/package-version.txt b/build/pkgs/backports_functools_lru_cache/package-version.txt deleted file mode 100644 index c239c60cba2..00000000000 --- a/build/pkgs/backports_functools_lru_cache/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.5 diff --git a/build/pkgs/backports_functools_lru_cache/spkg-install.in b/build/pkgs/backports_functools_lru_cache/spkg-install.in deleted file mode 100644 index 058b1344dc2..00000000000 --- a/build/pkgs/backports_functools_lru_cache/spkg-install.in +++ /dev/null @@ -1,3 +0,0 @@ -cd src - -sdh_pip_install . diff --git a/build/pkgs/backports_functools_lru_cache/type b/build/pkgs/backports_functools_lru_cache/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/backports_functools_lru_cache/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/backports_shutil_get_terminal_size/SPKG.rst b/build/pkgs/backports_shutil_get_terminal_size/SPKG.rst deleted file mode 100644 index 87dd9ddeeb8..00000000000 --- a/build/pkgs/backports_shutil_get_terminal_size/SPKG.rst +++ /dev/null @@ -1,7 +0,0 @@ -backports.shutil_get_terminal_size -================================== - -Description ------------ - -A backport of the get_terminal_size function from Python 3.3's shutil. diff --git a/build/pkgs/backports_shutil_get_terminal_size/checksums.ini b/build/pkgs/backports_shutil_get_terminal_size/checksums.ini deleted file mode 100644 index 4b76671e1aa..00000000000 --- a/build/pkgs/backports_shutil_get_terminal_size/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=backports.shutil_get_terminal_size-VERSION.tar.gz -sha1=a9774b04db0abc2df1b4b603699469358967346c -md5=03267762480bd86b50580dc19dff3c66 -cksum=2627812760 diff --git a/build/pkgs/backports_shutil_get_terminal_size/dependencies b/build/pkgs/backports_shutil_get_terminal_size/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/backports_shutil_get_terminal_size/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/backports_shutil_get_terminal_size/package-version.txt b/build/pkgs/backports_shutil_get_terminal_size/package-version.txt deleted file mode 100644 index b423d8166b0..00000000000 --- a/build/pkgs/backports_shutil_get_terminal_size/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.0.p1 diff --git a/build/pkgs/backports_shutil_get_terminal_size/patches/master.patch b/build/pkgs/backports_shutil_get_terminal_size/patches/master.patch deleted file mode 100644 index 70f55cc8066..00000000000 --- a/build/pkgs/backports_shutil_get_terminal_size/patches/master.patch +++ /dev/null @@ -1,69 +0,0 @@ -Diff between the latest release and the github master - -diff -ru backports.shutil_get_terminal_size-1.0.0/backports/shutil_get_terminal_size/get_terminal_size.py backports.shutil_get_terminal_size/backports/shutil_get_terminal_size/get_terminal_size.py ---- backports.shutil_get_terminal_size-1.0.0/backports/shutil_get_terminal_size/get_terminal_size.py 2014-08-19 01:52:24.000000000 +0200 -+++ backports.shutil_get_terminal_size/backports/shutil_get_terminal_size/get_terminal_size.py 2016-05-12 17:59:57.208494332 +0200 -@@ -16,30 +16,30 @@ - terminal_size = namedtuple("terminal_size", "columns lines") - - try: -- from ctypes import windll, create_string_buffer -+ from ctypes import windll, create_string_buffer, WinError - -- _handles = { -- 0: windll.kernel32.GetStdHandle(-10), -- 1: windll.kernel32.GetStdHandle(-11), -- 2: windll.kernel32.GetStdHandle(-12), -+ _handle_ids = { -+ 0: -10, -+ 1: -11, -+ 2: -12, - } - - def _get_terminal_size(fd): -- columns = lines = 0 -- -- try: -- handle = _handles[fd] -- csbi = create_string_buffer(22) -- res = windll.kernel32.GetConsoleScreenBufferInfo(handle, csbi) -- if res: -- res = struct.unpack("hhhhHhhhhhh", csbi.raw) -- left, top, right, bottom = res[5:9] -- columns = right - left + 1 -- lines = bottom - top + 1 -- except Exception: -- pass -- -- return terminal_size(columns, lines) -+ handle = windll.kernel32.GetStdHandle(_handle_ids[fd]) -+ if handle == 0: -+ raise OSError('handle cannot be retrieved') -+ if handle == -1: -+ raise WinError() -+ csbi = create_string_buffer(22) -+ res = windll.kernel32.GetConsoleScreenBufferInfo(handle, csbi) -+ if res: -+ res = struct.unpack("hhhhHhhhhhh", csbi.raw) -+ left, top, right, bottom = res[5:9] -+ columns = right - left + 1 -+ lines = bottom - top + 1 -+ return terminal_size(columns, lines) -+ else: -+ raise WinError() - - except ImportError: - import fcntl -@@ -48,9 +48,9 @@ - def _get_terminal_size(fd): - try: - res = fcntl.ioctl(fd, termios.TIOCGWINSZ, b"\x00" * 4) -- lines, columns = struct.unpack("hh", res) -- except Exception: -- columns = lines = 0 -+ except IOError as e: -+ raise OSError(e) -+ lines, columns = struct.unpack("hh", res) - - return terminal_size(columns, lines) - diff --git a/build/pkgs/backports_shutil_get_terminal_size/spkg-install.in b/build/pkgs/backports_shutil_get_terminal_size/spkg-install.in deleted file mode 100644 index 058b1344dc2..00000000000 --- a/build/pkgs/backports_shutil_get_terminal_size/spkg-install.in +++ /dev/null @@ -1,3 +0,0 @@ -cd src - -sdh_pip_install . diff --git a/build/pkgs/backports_shutil_get_terminal_size/type b/build/pkgs/backports_shutil_get_terminal_size/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/backports_shutil_get_terminal_size/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/backports_ssl_match_hostname/SPKG.rst b/build/pkgs/backports_ssl_match_hostname/SPKG.rst deleted file mode 100644 index 6e298bae7a6..00000000000 --- a/build/pkgs/backports_ssl_match_hostname/SPKG.rst +++ /dev/null @@ -1,31 +0,0 @@ -backports.ssl_match_hostname -============================ - -Description ------------ - -This backport brings match_hostname() to users of Python 2.x - -License -------- - -Python Software Foundation License - - -Upstream Contact ----------------- - -Home page: https://pypi.python.org/pypi/backports.ssl_match_hostname - -Dependencies ------------- - -Python, Setuptools - - -Special Update/Build Instructions ---------------------------------- - -- Unpack the tarball -- rename backports.ssl_match_hostname -> backports_ssl_match_hostname -- Tar as backports_ssl_match_hostname.VERSION.tar.gz diff --git a/build/pkgs/backports_ssl_match_hostname/checksums.ini b/build/pkgs/backports_ssl_match_hostname/checksums.ini deleted file mode 100644 index 25b368b83c4..00000000000 --- a/build/pkgs/backports_ssl_match_hostname/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=backports_ssl_match_hostname-VERSION.tar.gz -sha1=1d7500574eef84c826dfaf507722cd9249bf0672 -md5=c21f63bb4729eeab399932410a012934 -cksum=541176683 diff --git a/build/pkgs/backports_ssl_match_hostname/dependencies b/build/pkgs/backports_ssl_match_hostname/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/backports_ssl_match_hostname/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/backports_ssl_match_hostname/package-version.txt b/build/pkgs/backports_ssl_match_hostname/package-version.txt deleted file mode 100644 index fda4604388d..00000000000 --- a/build/pkgs/backports_ssl_match_hostname/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.5.0.1.p0 diff --git a/build/pkgs/backports_ssl_match_hostname/spkg-install.in b/build/pkgs/backports_ssl_match_hostname/spkg-install.in deleted file mode 100644 index 9cbe3bc3242..00000000000 --- a/build/pkgs/backports_ssl_match_hostname/spkg-install.in +++ /dev/null @@ -1,14 +0,0 @@ -if [ -z "$SAGE_LOCAL" ]; then - echo >&2 "SAGE_LOCAL undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -cd src - -sdh_pip_install . - -if [ $? -ne 0 ]; then - echo "Error installing backports.ssl_match_hostname ... exiting" - exit 1 -fi diff --git a/build/pkgs/backports_ssl_match_hostname/type b/build/pkgs/backports_ssl_match_hostname/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/backports_ssl_match_hostname/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/brial/spkg-configure.m4 b/build/pkgs/brial/spkg-configure.m4 new file mode 100644 index 00000000000..3d69c88f82d --- /dev/null +++ b/build/pkgs/brial/spkg-configure.m4 @@ -0,0 +1,63 @@ +SAGE_SPKG_CONFIGURE([brial], [ + SAGE_SPKG_DEPCHECK([boost m4ri], [ + # If we're using the system m4ri and boost, ensure that we can + # compile and run an executable linked against both libbrial and + # libbrial_groebner (both are used by SageMath). + AC_LANG_PUSH(C++) + SAVED_LIBS=$LIBS + LIBS="$LIBS -lbrial -lbrial_groebner" + AC_MSG_CHECKING([if we can link against brial libraries]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([ + #include + #include + USING_NAMESPACE_PBORI + USING_NAMESPACE_PBORIGB + + class MyConstant : public BooleConstant{ + public: void negate() { this->m_value = !this->m_value; } + }; + ],[ + BoolePolyRing r = BoolePolyRing(2, COrderEnums::dlex); + ReductionStrategy rs = ReductionStrategy(r); + rs.llReduceAll(); // uses groebner lib + if (2 != r.nVariables()) { return 1; } + if (r.constant(true) == r.constant(false)) { return 2; } + MyConstant f = MyConstant(); + f.negate(); // ensures v1.1.0+ if m_value isn't const + if (!f.isOne()) { return 3; } + return 0; + ]) + ], + [ + dnl check we're not on Fedora 30 - more precisely, we reject version 1.2.5 + dnl for which the version is verifiable by the following code. + AC_MSG_CHECKING([version not equal to 1.2.5]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM( + [[#include + #include + ]], [[ + if (VERSION=="1.2.5") return 0; + else return 1; + ]]) + ], [ + AC_MSG_RESULT([found a possibly buggy 1.2.5. Rejecting]) + sage_spkg_install_brial=yes + ], [ + AC_MSG_RESULT([yes]) + sage_spkg_install_brial=no + ]) + ], + [ + AC_MSG_RESULT([no]) + sage_spkg_install_brial=yes + ]) + LIBS=$SAVED_LIBS + AC_LANG_POP + ], + [ # If we're installing sage's boost or m4ri, then we have to + # install its BRiAl, too. + sage_spkg_install_brial=yes + ]) +]) diff --git a/build/pkgs/configparser/SPKG.rst b/build/pkgs/configparser/SPKG.rst deleted file mode 100644 index a059c92aa0e..00000000000 --- a/build/pkgs/configparser/SPKG.rst +++ /dev/null @@ -1,25 +0,0 @@ -configparser -============ - -Description ------------ - -This library brings the updated configparser from Python 3.5 to Python -2.6-3.5. - -The ancient ConfigParser module available in the standard library 2.x -has seen a major update in Python 3.2. This is a backport of those -changes so that they can be used directly in Python 2.6 - 3.5. - -To use the configparser backport instead of the built-in version on both -Python 2 and Python 3, simply import it explicitly as a backport: - - from backports import configparser - -If you'd like to use the backport on Python 2 and the built-in version -on Python 3, use that invocation instead: - - import configparser - -For detailed documentation consult the vanilla version at -http://docs.python.org/3/library/configparser.html. diff --git a/build/pkgs/configparser/checksums.ini b/build/pkgs/configparser/checksums.ini deleted file mode 100644 index a34386e96b0..00000000000 --- a/build/pkgs/configparser/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=configparser-VERSION.tar.gz -sha1=81351574c345e2a8600b7f2b2afb2b8f1c6aded2 -md5=aaa80b58b6b0810e54f66486860b3ed1 -cksum=4208301028 diff --git a/build/pkgs/configparser/dependencies b/build/pkgs/configparser/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/configparser/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/configparser/package-version.txt b/build/pkgs/configparser/package-version.txt deleted file mode 100644 index 0833a98f140..00000000000 --- a/build/pkgs/configparser/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.7.4 diff --git a/build/pkgs/configparser/spkg-install.in b/build/pkgs/configparser/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/configparser/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/configparser/type b/build/pkgs/configparser/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/configparser/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 4375c3aee32..640603dde3e 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=7c6e5982f299aeb5eaa1cc311bfed75c2387f6df -md5=1968f79d16a2f5cd1e3ae5add5e047e9 -cksum=2150519936 +sha1=f4040175ebc1ebcae8eb41eaab02f84e5840692a +md5=8b89552d880b19af9d7830e068084ae9 +cksum=582947775 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 04a79b8a531..31870dda81e 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -d5756d46d6a6cdd8d481c0381dcfa9e7719ba711 +73f0829779110ea1262fafbceecdd56e108f1b7b diff --git a/build/pkgs/conway_polynomials/dependencies b/build/pkgs/conway_polynomials/dependencies index b28747a2248..304d0c987a2 100644 --- a/build/pkgs/conway_polynomials/dependencies +++ b/build/pkgs/conway_polynomials/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | six +$(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/conway_polynomials/spkg-install.py b/build/pkgs/conway_polynomials/spkg-install.py index 8ed45676a35..cb192719d63 100644 --- a/build/pkgs/conway_polynomials/spkg-install.py +++ b/build/pkgs/conway_polynomials/spkg-install.py @@ -1,5 +1,5 @@ import os -from six.moves import cPickle as pickle +import pickle SAGE_SHARE = os.getenv('SAGE_SHARE') install_root = os.path.join(SAGE_SHARE, 'conway_polynomials') diff --git a/build/pkgs/cunningham_tables/SPKG.txt b/build/pkgs/cunningham_tables/SPKG.txt new file mode 100644 index 00000000000..920aef8a904 --- /dev/null +++ b/build/pkgs/cunningham_tables/SPKG.txt @@ -0,0 +1,11 @@ +cunningham_tables + +The script read_cunningham_prime_factors.py was used to generate the data set +from the file http://cage.ugent.be/~jdemeyer/cunningham/main.gz +We include a local copy, main.gz +(see comments in the file for details) + +== Changelog == + +2009/10/18 - version 1.0 - Initial version +* add cunningham_prime_factors diff --git a/build/pkgs/cunningham_tables/checksums.ini b/build/pkgs/cunningham_tables/checksums.ini new file mode 100644 index 00000000000..d6de22c0850 --- /dev/null +++ b/build/pkgs/cunningham_tables/checksums.ini @@ -0,0 +1,5 @@ +tarball=cunningham_tables-VERSION.tar.gz +sha1=8bea1a113d85bb9c37d8f213dd19525d9d026f22 +md5=e71b32f12e9a46c1c86e275e8441a06b +cksum=1990403877 +upstream_url=http://users.ox.ac.uk/~coml0531/sage/cunningham_tables-1.0.tar.gz diff --git a/build/pkgs/cunningham_tables/main.gz b/build/pkgs/cunningham_tables/main.gz new file mode 100644 index 00000000000..2265df843d6 Binary files /dev/null and b/build/pkgs/cunningham_tables/main.gz differ diff --git a/build/pkgs/cunningham_tables/package-version.txt b/build/pkgs/cunningham_tables/package-version.txt new file mode 100644 index 00000000000..d3827e75a5c --- /dev/null +++ b/build/pkgs/cunningham_tables/package-version.txt @@ -0,0 +1 @@ +1.0 diff --git a/build/pkgs/cunningham_tables/read_cunningham_prime_factors.py b/build/pkgs/cunningham_tables/read_cunningham_prime_factors.py new file mode 100644 index 00000000000..adc28b35336 --- /dev/null +++ b/build/pkgs/cunningham_tables/read_cunningham_prime_factors.py @@ -0,0 +1,56 @@ +# python2/Sage script used to create the package +# (needs porting to python3 Sage) +import urllib +import gzip +import StringIO +from re import match,findall + +# the following URL is gone, but may be found on archive.org +# webfile=urllib.urlopen("http://cage.ugent.be/~jdemeyer/cunningham/main.gz") +webfile=urllib.request.urlopen("https://web.archive.org/web/20190315214633/http://cage.ugent.be/~jdemeyer/cunningham/main.gz") +localfile=StringIO.StringIO(webfile.read()) +data = gzip.GzipFile(fileobj=localfile) + +L = [] + +for line in data: + l=match("\(.*\)( .*)",line).groups() + if len(l[0])>0: + L += map(Integer,findall("[ \.]([1234567890]+)",l[0])) + +# I add the factorisation of (2^4096-1) because I use it + +L += [ + 3, + 5, + 17, + 257, + 641, + 65537, + 274177, + 319489, + 974849, + 2424833, + 6700417, + 45592577, + 6487031809, + 67280421310721, + 1238926361552897, + 59649589127497217, + 167988556341760475137, + 5704689200685129054721, + 3560841906445833920513, + 4659775785220018543264560743076778192897, + 7455602825647884208337395736200454918783366342657, + 93461639715357977769163558199606896584051237541638188580280321, + 741640062627530801524787141901937474059940781097519023905821316144415759504705008092818711693940737, + 130439874405488189727484768796509903946608530841611892186895295776832416251471863574140227977573104895898783928842923844831149032913798729088601617946094119449010595906710130531906171018354491609619193912488538116080712299672322806217820753127014424577, + 173462447179147555430258970864309778377421844723664084649347019061363579192879108857591038330408837177983810868451546421940712978306134189864280826014542758708589243873685563973118948869399158545506611147420216132557017260564139394366945793220968665108959685482705388072645828554151936401912464931182546092879815733057795573358504982279280090942872567591518912118622751714319229788100979251036035496917279912663527358783236647193154777091427745377038294584918917590325110939381322486044298573971650711059244462177542540706913047034664643603491382441723306598834177 +] + +#sort and unique +cunningham_prime_factors = sorted(list(set(L))) + +F = file("cunningham_prime_factors.sobj","w") +F.write(dumps(cunningham_prime_factors)) +F.close() diff --git a/build/pkgs/cunningham_tables/spkg-install.in b/build/pkgs/cunningham_tables/spkg-install.in new file mode 100755 index 00000000000..e613f07744d --- /dev/null +++ b/build/pkgs/cunningham_tables/spkg-install.in @@ -0,0 +1 @@ +cp -r src/src/cunningham_tables $SAGE_SHARE/cunningham_tables diff --git a/build/pkgs/cunningham_tables/spkg-legacy-uninstall.in b/build/pkgs/cunningham_tables/spkg-legacy-uninstall.in new file mode 100644 index 00000000000..d80dcc284c0 --- /dev/null +++ b/build/pkgs/cunningham_tables/spkg-legacy-uninstall.in @@ -0,0 +1 @@ +rm -rf $SAGE_SHARE/cunningham_tables diff --git a/build/pkgs/flask/type b/build/pkgs/cunningham_tables/type similarity index 100% rename from build/pkgs/flask/type rename to build/pkgs/cunningham_tables/type diff --git a/build/pkgs/e_antic/checksums.ini b/build/pkgs/e_antic/checksums.ini index 3276a46e55a..4ef18e1d257 100644 --- a/build/pkgs/e_antic/checksums.ini +++ b/build/pkgs/e_antic/checksums.ini @@ -1,5 +1,5 @@ tarball=e-antic-VERSION.tar.gz -sha1=582c0c3118410f6d8efe23f8fd679e2c602f09a3 -md5=25e1df644ba85db544209cc1d2056464 -cksum=1577490486 +sha1=e3f54ab708e34c65d5704a560caba3f89a065785 +md5=7af45afdb754bb87b11abf08cc876c26 +cksum=1677181853 upstream_url=https://www.labri.fr/perso/vdelecro/e-antic/e-antic-VERSION.tar.gz diff --git a/build/pkgs/e_antic/package-version.txt b/build/pkgs/e_antic/package-version.txt index 9faa1b7a733..11808190d4b 100644 --- a/build/pkgs/e_antic/package-version.txt +++ b/build/pkgs/e_antic/package-version.txt @@ -1 +1 @@ -0.1.5 +0.1.7 diff --git a/build/pkgs/entrypoints/dependencies b/build/pkgs/entrypoints/dependencies index e82a12b05bb..15df0c4d6d8 100644 --- a/build/pkgs/entrypoints/dependencies +++ b/build/pkgs/entrypoints/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) configparser +$(PYTHON) | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/entrypoints/setup.py b/build/pkgs/entrypoints/setup.py deleted file mode 100755 index 76bb5e925a2..00000000000 --- a/build/pkgs/entrypoints/setup.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env sage-python -# -# Upstream does not have a setup.py file, so we use this instead -# - -from entrypoints import __version__ as v - -from setuptools import setup -setup(name="entrypoints", version=v, py_modules=["entrypoints"]) diff --git a/build/pkgs/entrypoints/spkg-install.in b/build/pkgs/entrypoints/spkg-install.in index 1ef8c69d080..cb4ba894442 100644 --- a/build/pkgs/entrypoints/spkg-install.in +++ b/build/pkgs/entrypoints/spkg-install.in @@ -1,6 +1,8 @@ -# -# Upstream does not have a setup.py file, so we supply one with Sage -# +cd src -mv setup.py src -cd src && sdh_pip_install . +# Make sure that modern pip uses the generated setup.py +# that is distributed with the PyPI tarball, +# so we do not have to have flit. Trac #29803. +rm -f pyproject.toml + +sdh_pip_install . diff --git a/build/pkgs/enum34/SPKG.rst b/build/pkgs/enum34/SPKG.rst deleted file mode 100644 index 98df0d9b429..00000000000 --- a/build/pkgs/enum34/SPKG.rst +++ /dev/null @@ -1,11 +0,0 @@ -enum34 -====== - -Description ------------ - -Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4 - -An enumeration is a set of symbolic names (members) bound to unique, -constant values. Within an enumeration, the members can be compared by -identity, and the enumeration itself can be iterated over. diff --git a/build/pkgs/enum34/checksums.ini b/build/pkgs/enum34/checksums.ini deleted file mode 100644 index e43c2a8c833..00000000000 --- a/build/pkgs/enum34/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=enum34-VERSION.tar.gz -sha1=014ef5878333ff91099893d615192c8cd0b1525a -md5=5f13a0841a61f7fc295c514490d120d0 -cksum=3196958404 diff --git a/build/pkgs/enum34/dependencies b/build/pkgs/enum34/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/enum34/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/enum34/package-version.txt b/build/pkgs/enum34/package-version.txt deleted file mode 100644 index 0664a8fd291..00000000000 --- a/build/pkgs/enum34/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.1.6 diff --git a/build/pkgs/enum34/spkg-install.in b/build/pkgs/enum34/spkg-install.in deleted file mode 100644 index 934d72d76be..00000000000 --- a/build/pkgs/enum34/spkg-install.in +++ /dev/null @@ -1,6 +0,0 @@ -if [ "$SAGE_PYTHON3" = "yes" ]; then - echo "Not installing enum34: it is only needed for Python version 3.3 or older." - exit 0 -fi - -cd src && sdh_pip_install . diff --git a/build/pkgs/enum34/type b/build/pkgs/enum34/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/enum34/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/flask/SPKG.rst b/build/pkgs/flask/SPKG.rst deleted file mode 100644 index 2b80d810b4b..00000000000 --- a/build/pkgs/flask/SPKG.rst +++ /dev/null @@ -1,10 +0,0 @@ -Flask -===== - -Description ------------ - -A microframework based on Werkzeug, Jinja2 and good intentions - -Flask is a microframework for Python based on Werkzeug, Jinja 2 and good -intentions. And before you ask: It’s BSD licensed! diff --git a/build/pkgs/flask/checksums.ini b/build/pkgs/flask/checksums.ini deleted file mode 100644 index f9167d09e4a..00000000000 --- a/build/pkgs/flask/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Flask-VERSION.tar.gz -sha1=d3d078262b053f4438e2ed3fd6f9b923c2c92172 -md5=378670fe456957eb3c27ddaef60b2b24 -cksum=2901487846 diff --git a/build/pkgs/flask/dependencies b/build/pkgs/flask/dependencies deleted file mode 100644 index 386a7b1542b..00000000000 --- a/build/pkgs/flask/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) werkzeug jinja2 itsdangerous - ----------- -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/flask/package-version.txt b/build/pkgs/flask/package-version.txt deleted file mode 100644 index 1bb0c37e72a..00000000000 --- a/build/pkgs/flask/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.10.1.p0 diff --git a/build/pkgs/flask/spkg-install.in b/build/pkgs/flask/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/flask/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/flask_autoindex/SPKG.rst b/build/pkgs/flask_autoindex/SPKG.rst deleted file mode 100644 index 43f8f79e3da..00000000000 --- a/build/pkgs/flask_autoindex/SPKG.rst +++ /dev/null @@ -1,12 +0,0 @@ - -Flask-AutoIndex -=============== - -Description ------------ - -The mod_autoindex for Flask - -Flask-AutoIndex generates an index page for your Flask application -automatically. The result just like mod_autoindex, but the look is more -awesome! diff --git a/build/pkgs/flask_autoindex/checksums.ini b/build/pkgs/flask_autoindex/checksums.ini deleted file mode 100644 index c9e98fd8be0..00000000000 --- a/build/pkgs/flask_autoindex/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Flask_AutoIndex-VERSION.tar.gz -sha1=7727fe9afd4132ca638281624b089b2d7a1a90b4 -md5=7e3aa3e9ffdd4be1bc3ec95d0400e46e -cksum=1126596374 diff --git a/build/pkgs/flask_autoindex/dependencies b/build/pkgs/flask_autoindex/dependencies deleted file mode 100644 index 5b4d510f6b6..00000000000 --- a/build/pkgs/flask_autoindex/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flask_silk - ----------- -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/flask_autoindex/package-version.txt b/build/pkgs/flask_autoindex/package-version.txt deleted file mode 100644 index ddf260918b2..00000000000 --- a/build/pkgs/flask_autoindex/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.6.p0 diff --git a/build/pkgs/flask_autoindex/spkg-install.in b/build/pkgs/flask_autoindex/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/flask_autoindex/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/flask_babel/SPKG.rst b/build/pkgs/flask_babel/SPKG.rst deleted file mode 100644 index 6974facfcf8..00000000000 --- a/build/pkgs/flask_babel/SPKG.rst +++ /dev/null @@ -1,9 +0,0 @@ - -Flask-Babel -=========== - -Description ------------ - -Adds i18n/l10n support to Flask applications with the help of the Babel -library. diff --git a/build/pkgs/flask_babel/checksums.ini b/build/pkgs/flask_babel/checksums.ini deleted file mode 100644 index 49652906818..00000000000 --- a/build/pkgs/flask_babel/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Flask_Babel-VERSION.tar.gz -sha1=977d3b152f876e06c215f6bb72616b4ce138fa49 -md5=4762e0392303f464d53cbebedfb87ded -cksum=2286190911 diff --git a/build/pkgs/flask_babel/dependencies b/build/pkgs/flask_babel/dependencies deleted file mode 100644 index 2b11ca831ea..00000000000 --- a/build/pkgs/flask_babel/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flask speaklater babel - ----------- -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/flask_babel/package-version.txt b/build/pkgs/flask_babel/package-version.txt deleted file mode 100644 index cdcd38abab9..00000000000 --- a/build/pkgs/flask_babel/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.9.p0 diff --git a/build/pkgs/flask_babel/spkg-install.in b/build/pkgs/flask_babel/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/flask_babel/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/flask_babel/type b/build/pkgs/flask_babel/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/flask_babel/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/flask_oldsessions/SPKG.rst b/build/pkgs/flask_oldsessions/SPKG.rst deleted file mode 100644 index 9ce3d39c12d..00000000000 --- a/build/pkgs/flask_oldsessions/SPKG.rst +++ /dev/null @@ -1,8 +0,0 @@ - -Flask-OldSessions -================= - -Description ------------ - -Provides a session class that works like the one in Flask before 0.10. diff --git a/build/pkgs/flask_oldsessions/checksums.ini b/build/pkgs/flask_oldsessions/checksums.ini deleted file mode 100644 index c5fc0993ff0..00000000000 --- a/build/pkgs/flask_oldsessions/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Flask_OldSessions-VERSION.tar.gz -sha1=1c0bbcd79b4fc626da2fd34ce9b59b2d43f6d81e -md5=3d731d343d5380bb9f502742ad62df50 -cksum=709943870 diff --git a/build/pkgs/flask_oldsessions/dependencies b/build/pkgs/flask_oldsessions/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/flask_oldsessions/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/flask_oldsessions/package-version.txt b/build/pkgs/flask_oldsessions/package-version.txt deleted file mode 100644 index 400afd7090f..00000000000 --- a/build/pkgs/flask_oldsessions/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.10.p0 diff --git a/build/pkgs/flask_oldsessions/spkg-install.in b/build/pkgs/flask_oldsessions/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/flask_oldsessions/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/flask_oldsessions/type b/build/pkgs/flask_oldsessions/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/flask_oldsessions/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/flask_openid/SPKG.rst b/build/pkgs/flask_openid/SPKG.rst deleted file mode 100644 index 5ac2ac228e0..00000000000 --- a/build/pkgs/flask_openid/SPKG.rst +++ /dev/null @@ -1,8 +0,0 @@ - -Flask-OpenID -============ - -Description ------------ - -OpenID support for Flask diff --git a/build/pkgs/flask_openid/checksums.ini b/build/pkgs/flask_openid/checksums.ini deleted file mode 100644 index a17be5fa13a..00000000000 --- a/build/pkgs/flask_openid/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Flask_OpenID-VERSION.tar.gz -sha1=18d39e03417cd2b577cd5c1f5c2ac117493f3fef -md5=a40c63df701ec634450d03490ddfb6c1 -cksum=995771756 diff --git a/build/pkgs/flask_openid/dependencies b/build/pkgs/flask_openid/dependencies deleted file mode 100644 index 08f3a274b80..00000000000 --- a/build/pkgs/flask_openid/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flask python_openid - ----------- -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/flask_openid/package-version.txt b/build/pkgs/flask_openid/package-version.txt deleted file mode 100644 index 81c03d9313a..00000000000 --- a/build/pkgs/flask_openid/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.2.5.p0 diff --git a/build/pkgs/flask_openid/spkg-install.in b/build/pkgs/flask_openid/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/flask_openid/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/flask_openid/type b/build/pkgs/flask_openid/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/flask_openid/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/flask_silk/SPKG.rst b/build/pkgs/flask_silk/SPKG.rst deleted file mode 100644 index 6d5b14492c4..00000000000 --- a/build/pkgs/flask_silk/SPKG.rst +++ /dev/null @@ -1,8 +0,0 @@ - -Flask-Silk -========== - -Description ------------ - -Adds silk icons to your Flask application or blueprint, or extension. diff --git a/build/pkgs/flask_silk/checksums.ini b/build/pkgs/flask_silk/checksums.ini deleted file mode 100644 index a54c85cdfd6..00000000000 --- a/build/pkgs/flask_silk/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Flask_Silk-VERSION.tar.gz -sha1=cef42b469c9ebb69a766d0cd33ad27480800d518 -md5=aca545a94063dc4acd21779ea5dde330 -cksum=1557295080 diff --git a/build/pkgs/flask_silk/dependencies b/build/pkgs/flask_silk/dependencies deleted file mode 100644 index 5df54be1a5d..00000000000 --- a/build/pkgs/flask_silk/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flask - ----------- -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/flask_silk/package-version.txt b/build/pkgs/flask_silk/package-version.txt deleted file mode 100644 index cebc1db828b..00000000000 --- a/build/pkgs/flask_silk/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.2.p0 diff --git a/build/pkgs/flask_silk/spkg-install.in b/build/pkgs/flask_silk/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/flask_silk/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/flask_silk/type b/build/pkgs/flask_silk/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/flask_silk/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/functools32/SPKG.rst b/build/pkgs/functools32/SPKG.rst deleted file mode 100644 index 0a9c6f1370f..00000000000 --- a/build/pkgs/functools32/SPKG.rst +++ /dev/null @@ -1,24 +0,0 @@ -functools32 -=========== - -Description ------------ - -Backport of the functools module from Python 3.2.3 for use on 2.7 and -PyPy. - -License -------- - -Python Software Foundation License - - -Upstream Contact ----------------- - -Home page: https://pypi.python.org/pypi/functools32 - -Dependencies ------------- - -Python, Setuptools diff --git a/build/pkgs/functools32/checksums.ini b/build/pkgs/functools32/checksums.ini deleted file mode 100644 index 7357e795b7d..00000000000 --- a/build/pkgs/functools32/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=functools32-VERSION.tar.gz -sha1=a520082a56af52c7af8d2d1390856bf1a0d755df -md5=09f24ffd9af9f6cd0f63cb9f4e23d4b2 -cksum=3970476845 diff --git a/build/pkgs/functools32/dependencies b/build/pkgs/functools32/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/functools32/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/functools32/package-version.txt b/build/pkgs/functools32/package-version.txt deleted file mode 100644 index bab4980050f..00000000000 --- a/build/pkgs/functools32/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.2.3-2.p0 diff --git a/build/pkgs/functools32/spkg-install.in b/build/pkgs/functools32/spkg-install.in deleted file mode 100644 index 1a768c61ce2..00000000000 --- a/build/pkgs/functools32/spkg-install.in +++ /dev/null @@ -1,19 +0,0 @@ -if [ -z "$SAGE_LOCAL" ]; then - echo >&2 "SAGE_LOCAL undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -if [ "$SAGE_PYTHON3" = yes ]; then - echo "Skipping functools32 since it is not necessary on Python 3" - exit 0 -fi - -cd src - -sdh_pip_install . - -if [ $? -ne 0 ]; then - echo "Error installing functools32 ... exiting" - exit 1 -fi diff --git a/build/pkgs/functools32/type b/build/pkgs/functools32/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/functools32/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/future/SPKG.rst b/build/pkgs/future/SPKG.rst deleted file mode 100644 index 9bab6bba252..00000000000 --- a/build/pkgs/future/SPKG.rst +++ /dev/null @@ -1,31 +0,0 @@ -future -====== - -Description ------------ - -Clean single-source support for Python 3 and 2 - -future is the missing compatibility layer between Python 2 and Python 3. -It allows you to use a single, clean Python 3.x-compatible codebase to -support both Python 2 and Python 3 with minimal overhead. - -It is designed to be used as follows: - -.. CODE-BLOCK:: python - - from __future__ import (absolute_import, division, - print_function, unicode_literals) - - from builtins import ( - bytes, dict, int, list, object, range, str, - ascii, chr, hex, input, next, oct, open, - pow, round, super, - filter, map, zip) - -followed by predominantly standard, idiomatic Python 3 code that then -runs similarly on Python 2.6/2.7 and Python 3.3+. - -The imports have no effect on Python 3. On Python 2, they shadow the -corresponding builtins, which normally have different semantics on -Python 3 versus 2, to provide their Python 3 semantics. diff --git a/build/pkgs/future/checksums.ini b/build/pkgs/future/checksums.ini deleted file mode 100644 index 2e6dd115e6c..00000000000 --- a/build/pkgs/future/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=future-VERSION.tar.gz -sha1=7abd068d09c637f4fa5fb2df3d90cc9607523aee -md5=e42113b4b72fabb5273ff88417104913 -cksum=2947769885 diff --git a/build/pkgs/future/dependencies b/build/pkgs/future/dependencies deleted file mode 100644 index e8cd251f60b..00000000000 --- a/build/pkgs/future/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | setuptools pip setuptools_scm - ----------- -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/future/package-version.txt b/build/pkgs/future/package-version.txt deleted file mode 100644 index 7cca7711a0d..00000000000 --- a/build/pkgs/future/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.17.1 diff --git a/build/pkgs/future/spkg-install.in b/build/pkgs/future/spkg-install.in deleted file mode 100644 index edc39fa5930..00000000000 --- a/build/pkgs/future/spkg-install.in +++ /dev/null @@ -1,7 +0,0 @@ -cd src - -sdh_pip_install . -if [ $? -ne 0 ]; then - echo "Error installing future ... exiting" - exit 1 -fi diff --git a/build/pkgs/future/type b/build/pkgs/future/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/future/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/gentoo-bootstrap.txt b/build/pkgs/gentoo-bootstrap.txt new file mode 100644 index 00000000000..6f590cfce06 --- /dev/null +++ b/build/pkgs/gentoo-bootstrap.txt @@ -0,0 +1,3 @@ +sys-devel/autoconf +sys-devel/automake +sys-devel/libtool diff --git a/build/pkgs/gentoo.txt b/build/pkgs/gentoo.txt new file mode 100644 index 00000000000..51316a87c0b --- /dev/null +++ b/build/pkgs/gentoo.txt @@ -0,0 +1,22 @@ +sys-devel/binutils +sys-libs/binutils-libs +sys-devel/make +dev-scheme/guile +dev-libs/libffi +app-arch/tar +sys-devel/gcc +dev-libs/mpc +sys-libs/glibc +sys-kernel/linux-headers +dev-lang/perl +sys-devel/m4 +sys-devel/bc +dev-lang/python +sys-devel/flex +app-misc/ca-certificates +sys-devel/gettext +dev-libs/libcroco +dev-libs/libxml2 +sys-apps/findutils +sys-apps/which +sys-apps/diffutils diff --git a/build/pkgs/ipaddress/SPKG.rst b/build/pkgs/ipaddress/SPKG.rst deleted file mode 100644 index ee9b69be864..00000000000 --- a/build/pkgs/ipaddress/SPKG.rst +++ /dev/null @@ -1,7 +0,0 @@ -ipaddress -========= - -Description ------------ - -Python 3.3+'s ipaddress for Python 2.6, 2.7, 3.2. diff --git a/build/pkgs/ipaddress/checksums.ini b/build/pkgs/ipaddress/checksums.ini deleted file mode 100644 index c77b736147a..00000000000 --- a/build/pkgs/ipaddress/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=ipaddress-VERSION.tar.gz -sha1=7b60cef3c7fdb7fa9c991ddff5968754cec6adb0 -md5=74c1ce3109f30eaa1ab3dd342e7b76d4 -cksum=275990046 diff --git a/build/pkgs/ipaddress/dependencies b/build/pkgs/ipaddress/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/ipaddress/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/ipaddress/package-version.txt b/build/pkgs/ipaddress/package-version.txt deleted file mode 100644 index c787b213b07..00000000000 --- a/build/pkgs/ipaddress/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.22 diff --git a/build/pkgs/ipaddress/spkg-install.in b/build/pkgs/ipaddress/spkg-install.in deleted file mode 100644 index 796815681b0..00000000000 --- a/build/pkgs/ipaddress/spkg-install.in +++ /dev/null @@ -1,6 +0,0 @@ -if [ "$SAGE_PYTHON3" = yes ]; then - echo "Skipping ipaddress: it is not necessary for on Python 3.3+." - exit 0 -fi - -cd src && sdh_pip_install . diff --git a/build/pkgs/ipaddress/type b/build/pkgs/ipaddress/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/ipaddress/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/ipython/dependencies b/build/pkgs/ipython/dependencies index 253b728ab93..427c31bf760 100644 --- a/build/pkgs/ipython/dependencies +++ b/build/pkgs/ipython/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) jinja2 tornado pyzmq pickleshare simplegeneric traitlets | $(PYTHON_TOOLCHAIN) backports_shutil_get_terminal_size wcwidth prompt_toolkit pygments pexpect appnope +$(PYTHON) jinja2 tornado pyzmq pickleshare simplegeneric traitlets | $(PYTHON_TOOLCHAIN) wcwidth prompt_toolkit pygments pexpect appnope ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jsonschema/dependencies b/build/pkgs/jsonschema/dependencies index c4b55842a4a..8b3637a0a0e 100644 --- a/build/pkgs/jsonschema/dependencies +++ b/build/pkgs/jsonschema/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) vcversioner functools32 | $(PYTHON_TOOLCHAIN) +$(PYTHON) vcversioner | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/matplotlib/dependencies b/build/pkgs/matplotlib/dependencies index 7be26fab2bf..85320c40ab2 100644 --- a/build/pkgs/matplotlib/dependencies +++ b/build/pkgs/matplotlib/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy freetype libpng dateutil pyparsing tornado six cycler | $(PYTHON_TOOLCHAIN) pytz functools32 backports_functools_lru_cache subprocess32 kiwisolver +$(PYTHON) numpy freetype libpng dateutil pyparsing tornado six cycler | $(PYTHON_TOOLCHAIN) pytz kiwisolver ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/matplotlib/make-setup-config.py b/build/pkgs/matplotlib/make-setup-config.py index caca02b71cd..9d8e998c805 100644 --- a/build/pkgs/matplotlib/make-setup-config.py +++ b/build/pkgs/matplotlib/make-setup-config.py @@ -1,7 +1,4 @@ -try: - from configparser import SafeConfigParser # Python 3 -except ImportError: - from ConfigParser import SafeConfigParser # Python 2 +from configparser import SafeConfigParser import os config = SafeConfigParser() diff --git a/build/pkgs/notebook/dependencies b/build/pkgs/notebook/dependencies index afa83258b14..76a05899142 100644 --- a/build/pkgs/notebook/dependencies +++ b/build/pkgs/notebook/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) ipython jupyter_client ipykernel nbconvert nbformat jinja2 tornado terminado send2trash ipaddress prometheus_client +$(PYTHON) | $(PYTHON_TOOLCHAIN) ipython jupyter_client ipykernel nbconvert nbformat jinja2 tornado terminado send2trash prometheus_client ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pathlib2/SPKG.rst b/build/pkgs/pathlib2/SPKG.rst deleted file mode 100644 index 6936a68aee3..00000000000 --- a/build/pkgs/pathlib2/SPKG.rst +++ /dev/null @@ -1,12 +0,0 @@ -pathlib -======= - -Description ------------ - -Object-oriented filesystem paths - -The old pathlib module on bitbucket is in bugfix-only mode. The goal of -pathlib2 is to provide a backport of standard pathlib module which -tracks the standard library module, so all the newest features of the -standard pathlib can be used also on older Python versions. diff --git a/build/pkgs/pathlib2/checksums.ini b/build/pkgs/pathlib2/checksums.ini deleted file mode 100644 index 01d841eedb8..00000000000 --- a/build/pkgs/pathlib2/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=pathlib2-VERSION.tar.gz -sha1=3a902176bb4b5b7f1f112e501409b84c21c7f50c -md5=f9ede5c162ea6fc6a3b1d26db53bb6a2 -cksum=1296606336 diff --git a/build/pkgs/pathlib2/dependencies b/build/pkgs/pathlib2/dependencies deleted file mode 100644 index d8a9f85cc31..00000000000 --- a/build/pkgs/pathlib2/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) six scandir - ----------- -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/pathlib2/package-version.txt b/build/pkgs/pathlib2/package-version.txt deleted file mode 100644 index 0bee604df76..00000000000 --- a/build/pkgs/pathlib2/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -2.3.3 diff --git a/build/pkgs/pathlib2/spkg-install.in b/build/pkgs/pathlib2/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/pathlib2/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/pathlib2/type b/build/pkgs/pathlib2/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/pathlib2/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/pickleshare/dependencies b/build/pkgs/pickleshare/dependencies index c7c548a71ae..7b6f95c9d9b 100644 --- a/build/pkgs/pickleshare/dependencies +++ b/build/pkgs/pickleshare/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) pathpy pathlib2 | $(PYTHON_TOOLCHAIN) +$(PYTHON) pathpy | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pip/checksums.ini b/build/pkgs/pip/checksums.ini index a11ba827600..a3a9f987369 100644 --- a/build/pkgs/pip/checksums.ini +++ b/build/pkgs/pip/checksums.ini @@ -1,4 +1,5 @@ tarball=pip-VERSION.tar.gz -sha1=1226368a8d39bd8b945517b6f7cb9802b279564e -md5=75cad449ad62c88b22de317a26781714 -cksum=886798891 +sha1=68e2ac7462489518db27eba9ade8be39e40798c9 +md5=62fa8775c44b070c5e1a3f44b0b6ccc5 +cksum=2731990114 +upstream_url=https://pypi.io/packages/source/p/pip/pip-VERSION.tar.gz diff --git a/build/pkgs/pip/dependencies b/build/pkgs/pip/dependencies index 6fb99bfe3f2..6f2aa240c02 100644 --- a/build/pkgs/pip/dependencies +++ b/build/pkgs/pip/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) python3 setuptools +$(PYTHON) setuptools wheel ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pip/package-version.txt b/build/pkgs/pip/package-version.txt index 33718932a44..2a0e5e0a153 100644 --- a/build/pkgs/pip/package-version.txt +++ b/build/pkgs/pip/package-version.txt @@ -1 +1 @@ -18.1 +20.1.1 diff --git a/build/pkgs/pip/spkg-install.in b/build/pkgs/pip/spkg-install.in index f7243906fb7..df71edf7d2e 100644 --- a/build/pkgs/pip/spkg-install.in +++ b/build/pkgs/pip/spkg-install.in @@ -8,12 +8,7 @@ export PYTHONPATH="$(pwd)/src" # need to use --upgrade or --ignore-installed; Otherwise pip, which is # importing itself, will think itself is already installed # -if [ "$SAGE_PYTHON3" = "yes" ]; then - versions="3" -else - # Install pip3 first so pip2 overwrites local/bin/pip - versions="3 2" -fi +versions=3 for vers in $versions; do python${vers} -m pip install --verbose --no-index --ignore-installed \ diff --git a/build/pkgs/pkgconfig/spkg-install.in b/build/pkgs/pkgconfig/spkg-install.in index d14edc90bcd..761190e309c 100644 --- a/build/pkgs/pkgconfig/spkg-install.in +++ b/build/pkgs/pkgconfig/spkg-install.in @@ -1,5 +1,10 @@ cd src +# Make sure that modern pip uses the generated setup.py +# that is distributed with the PyPI tarball, +# so we do not have to have poetry. Trac #29803. +rm -f pyproject.toml + sdh_pip_install . if [ $? -ne 0 ]; then diff --git a/build/pkgs/pytest/requirements.txt b/build/pkgs/pytest/requirements.txt new file mode 100644 index 00000000000..e079f8a6038 --- /dev/null +++ b/build/pkgs/pytest/requirements.txt @@ -0,0 +1 @@ +pytest diff --git a/build/pkgs/flask_autoindex/type b/build/pkgs/pytest/type similarity index 100% rename from build/pkgs/flask_autoindex/type rename to build/pkgs/pytest/type diff --git a/build/pkgs/rpy2/dependencies b/build/pkgs/rpy2/dependencies index c939931f297..7cb68462c25 100644 --- a/build/pkgs/rpy2/dependencies +++ b/build/pkgs/rpy2/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) r six singledispatch | $(PYTHON_TOOLCHAIN) +$(PYTHON) r six | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sagelib/package-version.txt b/build/pkgs/sagelib/package-version.txt index c46dc66e699..f083251bf12 100644 --- a/build/pkgs/sagelib/package-version.txt +++ b/build/pkgs/sagelib/package-version.txt @@ -1 +1 @@ -9.1.rc5 +9.2.beta3 diff --git a/build/pkgs/sagenb/SPKG.rst b/build/pkgs/sagenb/SPKG.rst deleted file mode 100644 index 7d031d20a9d..00000000000 --- a/build/pkgs/sagenb/SPKG.rst +++ /dev/null @@ -1,47 +0,0 @@ - -Sage Notebook -============= - -Description ------------ - -The Sage Notebook is a web-based graphical user interface for -mathematical software. - -License -------- - -GPLv3+ - - -Upstream Contact ----------------- - -- Keshav Kini -- Homepage: https://github.com/sagemath/sagenb - -Dependencies ------------- - -Build-time dependencies: - -- Python -- setuptools -- twisted -- flask -- flask-autoindex -- flask-babel -- flask-openid -- flask-oldsessions - -Run-time dependencies: - -- Sage -- jinja2 -- pexpect -- docutils -- sphinx - -Optional dependency: - -- OpenSSL (including headers) diff --git a/build/pkgs/sagenb/checksums.ini b/build/pkgs/sagenb/checksums.ini deleted file mode 100644 index 5b0930947d3..00000000000 --- a/build/pkgs/sagenb/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=sagenb-VERSION.tar.bz2 -sha1=722b7a15f2e1f911224ab6f397457f69d65027d7 -md5=0bdc2b44f3ce961c6b74bfc736ac2e09 -cksum=2540078270 diff --git a/build/pkgs/sagenb/dependencies b/build/pkgs/sagenb/dependencies deleted file mode 100644 index 9a8426a809b..00000000000 --- a/build/pkgs/sagenb/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(STARTED) | $(PYTHON_TOOLCHAIN) babel flask flask_autoindex flask_babel flask_oldsessions flask_openid mathjax twisted sphinx - ----------- -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/sagenb/package-version.txt b/build/pkgs/sagenb/package-version.txt deleted file mode 100644 index 781dcb07cd8..00000000000 --- a/build/pkgs/sagenb/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.1.3 diff --git a/build/pkgs/sagenb/spkg-install.in b/build/pkgs/sagenb/spkg-install.in deleted file mode 100644 index 414edd66f01..00000000000 --- a/build/pkgs/sagenb/spkg-install.in +++ /dev/null @@ -1,23 +0,0 @@ -cd src - -sdh_pip_install . - -cd doc -$MAKE html || sdh_die "Error building the documentation" -docdir="$SAGE_LOCAL/share/doc/sagenb" -rm -rf "$docdir" -mv build/html "$docdir" - -cd "${SAGE_DESTDIR}" - -# SageNB installation path, relative either to / (for real install) -# or to SAGE_DESTDIR. -SAGENB_INSTALL=$(echo ."$SAGE_LOCAL"/lib/python*/site-packages/sagenb) - -# Completely remove the old sagenb installation, including bad mathjax -# installations. -( cd / && rm -rf "$SAGENB_INSTALL" ) - -# Let sagenb use mathjax -ln -s -n "$SAGE_SHARE/mathjax/" "$SAGENB_INSTALL/data/mathjax" || \ - sdh_die "Error: Cannot symlink mathjax into the SageNB data directory." diff --git a/build/pkgs/sagenb/type b/build/pkgs/sagenb/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/sagenb/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/scandir/dependencies b/build/pkgs/scandir/dependencies index 974a474cf0e..15df0c4d6d8 100644 --- a/build/pkgs/scandir/dependencies +++ b/build/pkgs/scandir/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) six +$(PYTHON) | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools/checksums.ini b/build/pkgs/setuptools/checksums.ini index 845ef67e3c0..da1c43e62d5 100644 --- a/build/pkgs/setuptools/checksums.ini +++ b/build/pkgs/setuptools/checksums.ini @@ -1,4 +1,5 @@ tarball=setuptools-VERSION.zip -sha1=74b0dc738f72a21fe11f16af613166fd5694e436 -md5=1fbcbe45c7fb1d21041e676ba68d2dec -cksum=3373762786 +sha1=f76f68af6d2072882329870e8c022f1b958895cf +md5=6e9de90b242fdd60ef59f497424ce13a +cksum=1518553956 +upstream_url=https://pypi.io/packages/source/s/setuptools/setuptools-VERSION.zip diff --git a/build/pkgs/setuptools/dependencies b/build/pkgs/setuptools/dependencies index 63046883544..304d0c987a2 100644 --- a/build/pkgs/setuptools/dependencies +++ b/build/pkgs/setuptools/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) python3 +$(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/setuptools/package-version.txt b/build/pkgs/setuptools/package-version.txt index 9dd3e2460e8..d9694843ef5 100644 --- a/build/pkgs/setuptools/package-version.txt +++ b/build/pkgs/setuptools/package-version.txt @@ -1 +1 @@ -40.6.3 +47.1.1 diff --git a/build/pkgs/setuptools/spkg-install.in b/build/pkgs/setuptools/spkg-install.in index 800170674b0..efc63964f5c 100644 --- a/build/pkgs/setuptools/spkg-install.in +++ b/build/pkgs/setuptools/spkg-install.in @@ -9,11 +9,7 @@ export PYTHON_EGG_CACHE="$DOT_SAGE/.python-eggs" cd src -if [ "$SAGE_PYTHON3" = "yes" ]; then - versions="3" -else - versions="2 3" -fi +versions=3 # Prevent setuptools from installing itself with easy_install for vers in $versions; do diff --git a/build/pkgs/setuptools_scm/checksums.ini b/build/pkgs/setuptools_scm/checksums.ini index 319eec9fa78..4a07c989b19 100644 --- a/build/pkgs/setuptools_scm/checksums.ini +++ b/build/pkgs/setuptools_scm/checksums.ini @@ -1,4 +1,5 @@ tarball=setuptools_scm-VERSION.tar.gz -sha1=cffffd63429761edece3957321a50fbdb364f043 -md5=52a8dee23c9e5f7d7d18094563db516c -cksum=3085521574 +sha1=464fcfa8c35f0f1e6dcfe79c0d66cfe6f8e4b5ec +md5=e6c9fad17c90516d640868eb833d5150 +cksum=723592301 +upstream_url=https://pypi.io/packages/source/s/setuptools_scm/setuptools_scm-VERSION.tar.gz diff --git a/build/pkgs/setuptools_scm/package-version.txt b/build/pkgs/setuptools_scm/package-version.txt index fd2a01863fd..4d0dcda01c4 100644 --- a/build/pkgs/setuptools_scm/package-version.txt +++ b/build/pkgs/setuptools_scm/package-version.txt @@ -1 +1 @@ -3.1.0 +4.1.2 diff --git a/build/pkgs/singledispatch/SPKG.rst b/build/pkgs/singledispatch/SPKG.rst deleted file mode 100644 index de7f7337ccb..00000000000 --- a/build/pkgs/singledispatch/SPKG.rst +++ /dev/null @@ -1,25 +0,0 @@ -singledispatch -============== - -Description ------------ - -This library brings functools.singledispatch from Python 3.4 to Python -2.6-3.3. - -License -------- - -MIT License - - -Upstream Contact ----------------- - -Author: Łukasz Langa Home page: -http://docs.python.org/3/library/functools.html#functools.singledispatch - -Dependencies ------------- - -Python diff --git a/build/pkgs/singledispatch/checksums.ini b/build/pkgs/singledispatch/checksums.ini deleted file mode 100644 index 73faccd72b0..00000000000 --- a/build/pkgs/singledispatch/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=singledispatch-VERSION.tar.gz -sha1=f93241b06754a612af8bb7aa208c4d1805637022 -md5=af2fc6a3d6cc5a02d0bf54d909785fcb -cksum=2060266165 diff --git a/build/pkgs/singledispatch/dependencies b/build/pkgs/singledispatch/dependencies deleted file mode 100644 index 70f40469c70..00000000000 --- a/build/pkgs/singledispatch/dependencies +++ /dev/null @@ -1,4 +0,0 @@ -$(PYTHON) six | $(PYTHON_TOOLCHAIN) ----------- -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/singledispatch/package-version.txt b/build/pkgs/singledispatch/package-version.txt deleted file mode 100644 index d47ed3edce1..00000000000 --- a/build/pkgs/singledispatch/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.4.0.3.p0 diff --git a/build/pkgs/singledispatch/spkg-install.in b/build/pkgs/singledispatch/spkg-install.in deleted file mode 100644 index 058b1344dc2..00000000000 --- a/build/pkgs/singledispatch/spkg-install.in +++ /dev/null @@ -1,3 +0,0 @@ -cd src - -sdh_pip_install . diff --git a/build/pkgs/singledispatch/type b/build/pkgs/singledispatch/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/singledispatch/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/sphinx/dependencies b/build/pkgs/sphinx/dependencies index 16f478530e9..af979e75c97 100644 --- a/build/pkgs/sphinx/dependencies +++ b/build/pkgs/sphinx/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) docutils jinja2 pygments six snowballstemmer imagesize babel alabaster requests typing sphinxcontrib_websupport sphinxcontrib_applehelp sphinxcontrib_devhelp sphinxcontrib_htmlhelp sphinxcontrib_jsmath sphinxcontrib_qthelp sphinxcontrib_serializinghtml packaging +$(PYTHON) | $(PYTHON_TOOLCHAIN) docutils jinja2 pygments six snowballstemmer imagesize babel alabaster requests sphinxcontrib_websupport sphinxcontrib_applehelp sphinxcontrib_devhelp sphinxcontrib_htmlhelp sphinxcontrib_jsmath sphinxcontrib_qthelp sphinxcontrib_serializinghtml packaging ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/subprocess32/SPKG.rst b/build/pkgs/subprocess32/SPKG.rst deleted file mode 100644 index 79ec8a9aac1..00000000000 --- a/build/pkgs/subprocess32/SPKG.rst +++ /dev/null @@ -1,7 +0,0 @@ -subprocess32 -============ - -Description ------------ - -A backport of the subprocess module from Python 3 for use on 2.x diff --git a/build/pkgs/subprocess32/checksums.ini b/build/pkgs/subprocess32/checksums.ini deleted file mode 100644 index 1833f20506d..00000000000 --- a/build/pkgs/subprocess32/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=subprocess32-VERSION.tar.gz -sha1=bfc293afad55733195927a236fd57c099db231b3 -md5=afa0510115f483d668e25aa30502d9bc -cksum=3131639977 diff --git a/build/pkgs/subprocess32/dependencies b/build/pkgs/subprocess32/dependencies deleted file mode 100644 index 86e5d272f2c..00000000000 --- a/build/pkgs/subprocess32/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) python3 - ----------- -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/subprocess32/fix_config.py b/build/pkgs/subprocess32/fix_config.py deleted file mode 100644 index 0ed5933e23a..00000000000 --- a/build/pkgs/subprocess32/fix_config.py +++ /dev/null @@ -1,47 +0,0 @@ -# Fix build of subprocess32 -# -# subprocess32 is a backport from Python 3 to Python 2. But only the C -# sources were backported, not the configure script. This way, macros -# like HAVE_DIRFD which come from the Python 3 configure script are -# always undefined. This causes breakage on certain platforms. -# See upstream bug -# https://github.com/google/python-subprocess32/issues/40 -# -# In Sage, we fix this by using the actual pyconfig.h file from our -# Python 3 installation. -# -# This Python script should be run with the Python version where -# subprocess32 will eventually be installed. - - -from sysconfig import get_path -from subprocess import check_output - - -# Path to the Python 3 includes -cmd = "from sysconfig import get_path; print(get_path('include'), end='')" -py3incdir = check_output(["python3", "-c", cmd]) - -# Path to the includes of the Python installation where subprocess32 -# will be installed -incdir = get_path("include") - - -# Create a fake "Python.h" file which includes "pyconfig.h" from -# Python 3 and then includes the real Python.h header -header = ''' -/* Include pyconfig.h from Python 3 */ -#include "{}/pyconfig.h" - -/* Make sure that the Python 2 version of pyconfig.h can also be included */ -#undef Py_PYCONFIG_H - -/* Include the real Python.h file */ -#include "{}/Python.h" -'''.format(py3incdir, incdir) - - -print("NOTE: Using Python 3 configuration to build subprocess32 for Python 2") - -with open("Python.h", "w") as f: - f.write(header) diff --git a/build/pkgs/subprocess32/package-version.txt b/build/pkgs/subprocess32/package-version.txt deleted file mode 100644 index 444877d48fb..00000000000 --- a/build/pkgs/subprocess32/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.5.3 diff --git a/build/pkgs/subprocess32/spkg-install.in b/build/pkgs/subprocess32/spkg-install.in deleted file mode 100644 index d1734178f3a..00000000000 --- a/build/pkgs/subprocess32/spkg-install.in +++ /dev/null @@ -1,11 +0,0 @@ -if [ "$SAGE_PYTHON3" = yes ]; then - echo "Skipping subprocess32 since it is not necessary on Python 3" - exit 0 -fi - -cd src - -# See fix_config.py for an explanation -python2 ../fix_config.py || exit $? - -sdh_pip_install . diff --git a/build/pkgs/subprocess32/type b/build/pkgs/subprocess32/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/subprocess32/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/terminado/spkg-install.in b/build/pkgs/terminado/spkg-install.in index deba1bb42bb..cb4ba894442 100644 --- a/build/pkgs/terminado/spkg-install.in +++ b/build/pkgs/terminado/spkg-install.in @@ -1 +1,8 @@ -cd src && sdh_pip_install . +cd src + +# Make sure that modern pip uses the generated setup.py +# that is distributed with the PyPI tarball, +# so we do not have to have flit. Trac #29803. +rm -f pyproject.toml + +sdh_pip_install . diff --git a/build/pkgs/testpath/spkg-install.in b/build/pkgs/testpath/spkg-install.in index deba1bb42bb..cb4ba894442 100644 --- a/build/pkgs/testpath/spkg-install.in +++ b/build/pkgs/testpath/spkg-install.in @@ -1 +1,8 @@ -cd src && sdh_pip_install . +cd src + +# Make sure that modern pip uses the generated setup.py +# that is distributed with the PyPI tarball, +# so we do not have to have flit. Trac #29803. +rm -f pyproject.toml + +sdh_pip_install . diff --git a/build/pkgs/threejs/checksums.ini b/build/pkgs/threejs/checksums.ini index 162dff75979..924f689a6ac 100644 --- a/build/pkgs/threejs/checksums.ini +++ b/build/pkgs/threejs/checksums.ini @@ -1,4 +1,4 @@ tarball=threejs-VERSION.tar.gz -sha1=fe1ebb981e0347c8562acf356eab4c6fe5b86896 -md5=73eac3ca4f95eb42165328798df4a026 -cksum=3268794484 +sha1=55e28aff39d60e54069504eb84146961e1ca1cfd +md5=6082b27846f5b63a342e9cc91928785e +cksum=1458447267 diff --git a/build/pkgs/threejs/package-version.txt b/build/pkgs/threejs/package-version.txt index 3174e2cb4d7..cc32ce05abb 100644 --- a/build/pkgs/threejs/package-version.txt +++ b/build/pkgs/threejs/package-version.txt @@ -1 +1 @@ -r110 +r117 diff --git a/build/pkgs/threejs/spkg-src b/build/pkgs/threejs/spkg-src index 1194cdafe10..ae0d79dc6c0 100755 --- a/build/pkgs/threejs/spkg-src +++ b/build/pkgs/threejs/spkg-src @@ -3,7 +3,7 @@ set -e # https://github.com/mrdoob/three.js/releases -GIT_VERSION=r110 +GIT_VERSION=r117 [ -n "${SAGE_ROOT}" ] || SAGE_ROOT="$(pwd)/../../../" diff --git a/build/pkgs/tornado/dependencies b/build/pkgs/tornado/dependencies index 83826523451..7a3a585116d 100644 --- a/build/pkgs/tornado/dependencies +++ b/build/pkgs/tornado/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) backports_abc backports_ssl_match_hostname certifi singledispatch | $(PYTHON_TOOLCHAIN) +$(PYTHON) certifi | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/traitlets/dependencies b/build/pkgs/traitlets/dependencies index 859b5be322b..242140707df 100644 --- a/build/pkgs/traitlets/dependencies +++ b/build/pkgs/traitlets/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) ipython_genutils decorator six enum34 +$(PYTHON) | $(PYTHON_TOOLCHAIN) ipython_genutils decorator six ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/twisted/SPKG.rst b/build/pkgs/twisted/SPKG.rst deleted file mode 100644 index 5b6e9293e55..00000000000 --- a/build/pkgs/twisted/SPKG.rst +++ /dev/null @@ -1,10 +0,0 @@ -twisted -======= - -Description ------------ - -An asynchronous networking framework written in Python - -An extensible framework for Python programming, with special focus on -event-based network programming and multiprotocol integration. diff --git a/build/pkgs/twisted/checksums.ini b/build/pkgs/twisted/checksums.ini deleted file mode 100644 index a720c8839e7..00000000000 --- a/build/pkgs/twisted/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Twisted-VERSION.tar.bz2 -sha1=b9f183ae63a49c99619f7d37d1ae3a368d6cf886 -md5=e044af844623e9fbcbe29f578db6053a -cksum=3273908979 diff --git a/build/pkgs/twisted/dependencies b/build/pkgs/twisted/dependencies deleted file mode 100644 index c19839157ec..00000000000 --- a/build/pkgs/twisted/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) zope_interface - ----------- -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/twisted/package-version.txt b/build/pkgs/twisted/package-version.txt deleted file mode 100644 index ff595906737..00000000000 --- a/build/pkgs/twisted/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -16.3.0.p0 diff --git a/build/pkgs/twisted/spkg-install.in b/build/pkgs/twisted/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/twisted/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/twisted/type b/build/pkgs/twisted/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/twisted/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/typing/SPKG.rst b/build/pkgs/typing/SPKG.rst deleted file mode 100644 index 5bdd9ff8ebc..00000000000 --- a/build/pkgs/typing/SPKG.rst +++ /dev/null @@ -1,20 +0,0 @@ -typing -====== - -Description ------------ - -Typing – Type Hints for Python - -This is a backport of the standard library typing module to Python -versions older than 3.6. - -Typing defines a standard notation for Python function and variable type -annotations. The notation can be used for documenting code in a concise, -standard format, and it has been designed to also be used by static and -runtime type checkers, static analyzers, IDEs and other tools. - -License -------- - -Python Software Foundation License diff --git a/build/pkgs/typing/checksums.ini b/build/pkgs/typing/checksums.ini deleted file mode 100644 index a421db5e1c5..00000000000 --- a/build/pkgs/typing/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=typing-VERSION.tar.gz -sha1=8414f7e523f1f286f72392e9f8929d346df6f6a2 -md5=64614206b4bdc0864fc0e0bccd69efc9 -cksum=2256549185 diff --git a/build/pkgs/typing/dependencies b/build/pkgs/typing/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/typing/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/typing/package-version.txt b/build/pkgs/typing/package-version.txt deleted file mode 100644 index 4f2c1d15f6d..00000000000 --- a/build/pkgs/typing/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.6.6 diff --git a/build/pkgs/typing/spkg-install.in b/build/pkgs/typing/spkg-install.in deleted file mode 100644 index ee68cc6792e..00000000000 --- a/build/pkgs/typing/spkg-install.in +++ /dev/null @@ -1,6 +0,0 @@ -# The Python module typing is only useful for Python 2 and early -# Python 3 versions. See https://trac.sagemath.org/ticket/28499 -if [ $SAGE_PYTHON_VERSION -eq 2 ] -then - cd src && sdh_pip_install . -fi diff --git a/build/pkgs/typing/type b/build/pkgs/typing/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/typing/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/werkzeug/SPKG.rst b/build/pkgs/werkzeug/SPKG.rst deleted file mode 100644 index 860d3762b49..00000000000 --- a/build/pkgs/werkzeug/SPKG.rst +++ /dev/null @@ -1,21 +0,0 @@ -Werkzeug -======== - -Description ------------ - -The Swiss Army knife of Python web development - -Werkzeug started as simple collection of various utilities for WSGI -applications and has become one of the most advanced WSGI utility -modules. It includes a powerful debugger, full featured request and -response objects, HTTP utilities to handle entity tags, cache control -headers, HTTP dates, cookie handling, file uploads, a powerful URL -routing system and a bunch of community contributed addon modules. - -Werkzeug is unicode aware and doesn't enforce a specific template -engine, database adapter or anything else. It doesn’t even enforce a -specific way of handling requests and leaves all that up to the -developer. It's most useful for end user applications which should work -on as many server environments as possible (such as blogs, wikis, -bulletin boards, etc.). diff --git a/build/pkgs/werkzeug/checksums.ini b/build/pkgs/werkzeug/checksums.ini deleted file mode 100644 index 409b4650988..00000000000 --- a/build/pkgs/werkzeug/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Werkzeug-VERSION.tar.gz -sha1=4b979fb960c5b5507ccb8a705931fa217013483d -md5=6d20b5be2d245be4ac7706cc390d130c -cksum=1712124090 diff --git a/build/pkgs/werkzeug/dependencies b/build/pkgs/werkzeug/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/werkzeug/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -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/werkzeug/package-version.txt b/build/pkgs/werkzeug/package-version.txt deleted file mode 100644 index 930e3000bdc..00000000000 --- a/build/pkgs/werkzeug/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.14.1 diff --git a/build/pkgs/werkzeug/spkg-install.in b/build/pkgs/werkzeug/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/werkzeug/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/werkzeug/type b/build/pkgs/werkzeug/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/werkzeug/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/wheel/checksums.ini b/build/pkgs/wheel/checksums.ini new file mode 100644 index 00000000000..4365ece9d85 --- /dev/null +++ b/build/pkgs/wheel/checksums.ini @@ -0,0 +1,5 @@ +tarball=wheel-VERSION.tar.gz +sha1=6c3ef86120c454fefb3154460c466a82a985982a +md5=ce2a27f99c130a927237b5da1ff5ceaf +cksum=3327534776 +upstream_url=https://pypi.io/packages/source/w/wheel/wheel-VERSION.tar.gz diff --git a/build/pkgs/backports_functools_lru_cache/dependencies b/build/pkgs/wheel/dependencies similarity index 82% rename from build/pkgs/backports_functools_lru_cache/dependencies rename to build/pkgs/wheel/dependencies index 15df0c4d6d8..dbe5d796c45 100644 --- a/build/pkgs/backports_functools_lru_cache/dependencies +++ b/build/pkgs/wheel/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) +$(PYTHON) setuptools ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/wheel/package-version.txt b/build/pkgs/wheel/package-version.txt new file mode 100644 index 00000000000..3f8003cd4c4 --- /dev/null +++ b/build/pkgs/wheel/package-version.txt @@ -0,0 +1 @@ +0.34.2 diff --git a/build/pkgs/wheel/spkg-install.in b/build/pkgs/wheel/spkg-install.in new file mode 100644 index 00000000000..9c0353a87ef --- /dev/null +++ b/build/pkgs/wheel/spkg-install.in @@ -0,0 +1,9 @@ +cd src + +versions=3 + +for vers in $versions; do + python${vers} setup.py --no-user-cfg install \ + --single-version-externally-managed --root="$SAGE_DESTDIR" || \ + sdh_die "Error building / installing wheel for Python ${vers}" +done diff --git a/build/pkgs/backports_abc/type b/build/pkgs/wheel/type similarity index 100% rename from build/pkgs/backports_abc/type rename to build/pkgs/wheel/type diff --git a/build/pkgs/zope_interface/checksums.ini b/build/pkgs/zope_interface/checksums.ini deleted file mode 100644 index 2c713d14909..00000000000 --- a/build/pkgs/zope_interface/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=zope.interface-VERSION.tar.gz -sha1=e4dd98256b168e7888abbf6798789c775f5eae35 -md5=a3b24f9d079bae5e13dd7a88aa512112 -cksum=1864918591 diff --git a/build/pkgs/zope_interface/package-version.txt b/build/pkgs/zope_interface/package-version.txt deleted file mode 100644 index 6016e8addc4..00000000000 --- a/build/pkgs/zope_interface/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -4.6.0 diff --git a/build/pkgs/zope_interface/spkg-install b/build/pkgs/zope_interface/spkg-install new file mode 100755 index 00000000000..d37ec11bc29 --- /dev/null +++ b/build/pkgs/zope_interface/spkg-install @@ -0,0 +1,2 @@ +#! /bin/sh +echo Installation of zope_interface is disabled, as a preparation for removal diff --git a/build/pkgs/zope_interface/spkg-install.in b/build/pkgs/zope_interface/spkg-install.in index deba1bb42bb..9e34dd1f6d2 100644 --- a/build/pkgs/zope_interface/spkg-install.in +++ b/build/pkgs/zope_interface/spkg-install.in @@ -1 +1,2 @@ -cd src && sdh_pip_install . +#! /usr/bin/env bash +echo Installation of zope_interface is disabled, as a preparation for removal diff --git a/src/bin/sage b/src/bin/sage index d7c009fb402..9b3710ba223 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -167,9 +167,7 @@ usage_advanced() { echo " -n -- reply no to prompts about experimental" echo " and old-style packages" echo " -p [opts] [packages]-- install the given Sage packages, without dependency" - echo " checking and with support for old-style spkgs." - echo " Options are -c, -d and -s with the same meaning as" - echo " for the -i command" + echo " checking. Options are the same as for the -i command." echo " -info [packages] -- print the SPKG.txt or SPKG.rst of the given packages," echo " and some additional information." echo " --location -- if needed, fix paths to make Sage relocatable" @@ -360,6 +358,11 @@ if [ "$1" = '-i' ]; then echo >&2 "Error: 'sage -i $OPT ' is no longer supported, use 'sage --info ' instead." exit 2;; -f) FORCE_INSTALL=yes;; + # Setting SAGE_CHECK here duplicates what we do in sage-spkg + # but we need it in "make" already when there are (order-only) + # dependencies on packages providing test infrastructure + -c) INSTALL_OPTIONS="$INSTALL_OPTIONS $OPT"; export SAGE_CHECK=yes;; + -w) INSTALL_OPTIONS="$INSTALL_OPTIONS $OPT"; export SAGE_CHECK=warn;; -*) INSTALL_OPTIONS="$INSTALL_OPTIONS $OPT";; *) PACKAGES="$PACKAGES $OPT";; esac @@ -385,7 +388,7 @@ if [ "$1" = '-i' ]; then # See https://trac.sagemath.org/ticket/25078 if ! echo "$ALL_TARGETS" | grep "^${PKG}$" >/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" + echo >&2 "Note: if it is an old-style package, installing these is no longer supported" exit 1 fi $MAKE SAGE_SPKG="sage-spkg $INSTALL_OPTIONS" "$PKG" @@ -1110,7 +1113,8 @@ fi if [ $# -ge 1 ]; then T=`echo "$1" | sed -e "s/.*\.//"` if [ "$T" = "spkg" ]; then - install "$@" + echo "Error: Installing old-style SPKGs is no longer supported." + exit 1 fi sage_setup unset TERM # See Trac #12263 diff --git a/src/bin/sage-env b/src/bin/sage-env index f3a005f573a..32860d3663c 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -109,6 +109,24 @@ resolvelinks() { echo "$out" } +# See if we can obtain SAGE_SCRIPTS_DIR before determining SAGE_ROOT +if [ -z "$SAGE_SCRIPTS_DIR" ]; then + ## Find the directory of this script (sage-env). + ## Note that it is *sourced* by various other scripts, + ## which is why `dirname $0` would not work ($0 is /bin/bash). + ## Instead we use a solution from + ## http://stackoverflow.com/questions/59895/can-a-bash-script-tell-which-directory-it-is-stored-in + ## It uses a bash feature: BASH_SOURCE[0] gives the source of + ## the "currently running function". See + ## https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html + ## (entries for FUNCNAME and BASH_SOURCE). + SAGE_SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +fi + +if [ -n "$SAGE_SCRIPTS_DIR" -a -r "$SAGE_SCRIPTS_DIR/sage-env-config" ]; then + # Set environment variables (like SAGE_LOCAL and SAGE_ROOT) depending on ./configure + . "$SAGE_SCRIPTS_DIR/sage-env-config" +fi # New value for SAGE_ROOT: either SAGE_ROOT (if given) # or a guessed value based on pwd. @@ -120,7 +138,7 @@ elif [ -f ../../sage -a -d ../../build ]; then NEW_SAGE_ROOT="../.." else # No idea what SAGE_ROOT should be... - echo >&2 "Error: You must set the SAGE_ROOT environment variable or run this" + echo >&2 "Error: You must set the SAGE_ROOT or SAGE_SCRIPTS_DIR environment variables or run this" echo >&2 "script from the SAGE_ROOT or SAGE_ROOT/local/bin/ directory." return 1 fi @@ -185,11 +203,13 @@ elif [ ! -f "$SAGE_SCRIPTS_DIR/sage-env-config" ]; then return 1 fi -# Set environment variables (like SAGE_LOCAL) depending on ./configure -. "$SAGE_SCRIPTS_DIR/sage-env-config" -if [ $? -ne 0 ]; then - echo >&2 "Error: failed to source $SAGE_SCRIPTS_DIR/sage-env-config" - return 1 +if [ -n $SAGE_ENV_CONFIG_SOURCED ]; then + # Set environment variables (like SAGE_LOCAL) depending on ./configure + . "$SAGE_SCRIPTS_DIR/sage-env-config" + if [ $? -ne 0 ]; then + echo >&2 "Error: failed to source $SAGE_SCRIPTS_DIR/sage-env-config" + return 1 + fi fi # The compilers are set in order of priority by diff --git a/src/bin/sage-env-config.in b/src/bin/sage-env-config.in index 12ab66031de..7fee406fb41 100644 --- a/src/bin/sage-env-config.in +++ b/src/bin/sage-env-config.in @@ -24,10 +24,15 @@ # ########################################################################## +export SAGE_ENV_CONFIG_SOURCED=1 + # SAGE_LOCAL is the installation prefix and can be customized by using # ./configure --prefix export SAGE_LOCAL="@prefix@" +# SAGE_ROOT is the location of the Sage source/build tree. +export SAGE_ROOT="@abs_top_srcdir@" + ####################################### # Compilers set at configuration time ####################################### diff --git a/src/bin/sage-notebook b/src/bin/sage-notebook index d54a6ba91a2..889341d8b00 100755 --- a/src/bin/sage-notebook +++ b/src/bin/sage-notebook @@ -13,66 +13,6 @@ logger = logging.getLogger() from sage.misc.banner import banner -class NotebookSageNB(object): - - def print_banner(self): - banner() - print('Please wait while the old SageNB Notebook server starts...') - - @classmethod - def print_help(cls): - cls([], help=True) - - def cmdline2argspec(self, cmdline_args): - """ - Convert command line arguments to Python argspec - - AKA the crappy copy of argparse. Only here for the legacy - notebook, do not use. - - INPUT: - - - ``cmdline_args`` -- list of string. - - OUTPUT: - - A python argspec: A pair consisting of a tuple and a dict. - """ - args = [] - kwds = dict() - for x in cmdline_args: - logger.info('Parsing %s', x) - if '=' in x: - key, value = x.split('=', 2) - logger.debug('keyword argument %s = %s', key, value) - try: - value = ast.literal_eval(value) - except Exception: - logger.debug('cannot evaluate, treat as string') - kwds[key] = value - else: - logger.debug('positional argument %s', x) - try: - value = ast.literal_eval(x) - except Exception: - value = x - logger.debug('cannot evaluate, treat as string') - args.append(value) - return tuple(args), kwds - - def __init__(self, argv, help=False): - self.print_banner() - self.args, self.kwds = self.cmdline2argspec(argv) - logger.info('notebook positional arguments = %s', self.args) - logger.info('notebook keyword arguments = %s', self.kwds) - from sagenb.notebook.notebook_object import notebook - if help: - from sage.misc.sageinspect import sage_getdoc - print(sage_getdoc(notebook)) - else: - notebook(*self.args, **self.kwds) - - class NotebookJupyter(object): PREREQUISITE_ERROR = textwrap.dedent(""" @@ -182,8 +122,7 @@ EXAMPLES: notebook_launcher = { - 'default': SageNBExport, # change this to change the default - 'sagenb': NotebookSageNB, + 'default': NotebookJupyter, # change this to change the default 'ipython': NotebookJupyter, 'jupyter': NotebookJupyter, 'jupyterlab': NotebookJupyterlab, @@ -249,10 +188,13 @@ if __name__ == '__main__': logger.info('Main parser got arguments %s', args) logger.info('Passing on to notebook implementation: %s', unknown) - if sys.version_info.major == 3 and args.notebook == "sagenb": - logger.critical('trying to use old notebook under Python 3') - print('old notebook not working under Python 3, use Jupyter notebook') - print('see https://wiki.sagemath.org/Python3-Switch') + if args.notebook == "sagenb": + logger.critical('cannot use the legacy notebook SageNB with Python 3') + print('The legacy notebook does not work under Python 3; ' + 'use the Jupyter notebook.') + print('See https://wiki.sagemath.org/Python3-Switch') + print('Use \"sage --notebook=export\" to export SageNB notebooks ' + 'to Jupyter') sys.exit(1) try: diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index a8b3f5583a4..8158c10f174 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,5 +1,5 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='9.2.beta2' -SAGE_RELEASE_DATE='2020-06-26' -SAGE_VERSION_BANNER='SageMath version 9.2.beta2, Release Date: 2020-06-26' +SAGE_VERSION='9.2.beta3' +SAGE_RELEASE_DATE='2020-07-04' +SAGE_VERSION_BANNER='SageMath version 9.2.beta3, Release Date: 2020-07-04' diff --git a/src/doc/.gitignore b/src/doc/.gitignore index 5039f33ca6a..a52195617d8 100644 --- a/src/doc/.gitignore +++ b/src/doc/.gitignore @@ -5,3 +5,4 @@ /en/reference/spkg/*.rst /output /en/installation/*.txt +/en/reference/repl/*.txt diff --git a/src/doc/bootstrap b/src/doc/bootstrap index f25a7a8d5f6..fbeb0b90a99 100755 --- a/src/doc/bootstrap +++ b/src/doc/bootstrap @@ -77,3 +77,8 @@ done cat >> "$OUTPUT_INDEX" <&2 $0:$LINENO: installing "$OUTPUT" +./sage -advanced > "$OUTPUT" diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index ae918205b20..e4852e843e8 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -307,8 +307,9 @@ A script package has a single install script named ``spkg-install``. It needs to be an executable shell script; it is not subject to the templating described in the previous section. -Sage runs ``spkg-install`` from the ``$SAGE_ROOT`` directory in the environment -obtained by sourcing the files ``src/bin/sage-env`` and ``build/bin/sage-build-env-config``. +Sage runs ``spkg-install`` from the directory ``$SAGE_ROOT/build/pkgs/`` +in the environment obtained by sourcing the files ``src/bin/sage-env`` and +``build/bin/sage-build-env-config``. .. _section-sdh-helpers: diff --git a/src/doc/en/reference/discrete_geometry/index.rst b/src/doc/en/reference/discrete_geometry/index.rst index d6cdf92e8ef..3d027326933 100644 --- a/src/doc/en/reference/discrete_geometry/index.rst +++ b/src/doc/en/reference/discrete_geometry/index.rst @@ -33,6 +33,7 @@ Polyhedra sage/geometry/polyhedron/plot sage/geometry/polyhedron/face sage/geometry/polyhedron/cdd_file_format + sage/geometry/polyhedron/modules/formal_polyhedra_module Lattice polyhedra ~~~~~~~~~~~~~~~~~ diff --git a/src/doc/en/reference/misc/index.rst b/src/doc/en/reference/misc/index.rst index 9e5b3f1f337..4e8eb49bc15 100644 --- a/src/doc/en/reference/misc/index.rst +++ b/src/doc/en/reference/misc/index.rst @@ -31,6 +31,7 @@ Special Base Classes, Decorators, etc. sage/misc/method_decorator sage/misc/object_multiplexer sage/misc/fast_methods + sage/misc/call Lists and Iteration, etc. ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index f76b818008f..b7383e7e113 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3324,6 +3324,9 @@ REFERENCES: Journal of Combinatorial Theory, Series A, **88** (1999), 66-92, http://www.sciencedirect.com/science/article/pii/0012365X9290368P +.. [Kra1999det] \C. Krattenthaler, *Advanced determinant calculus*, + Sém. Lothar. Combin. **42** (1999), Art. B42q, 67pp. + .. [Kra2006] Christian Krattenthaler. *Growth diagrams, and increasing and decreasing chains in fillings of Ferrers shapes*. Advances in Applied Mathematics Volume 37, diff --git a/src/doc/en/reference/repl/options.rst b/src/doc/en/reference/repl/options.rst index 3bc37ca1961..89214741c55 100644 --- a/src/doc/en/reference/repl/options.rst +++ b/src/doc/en/reference/repl/options.rst @@ -211,9 +211,6 @@ Command-line options for Sage .. rubric:: Making Sage packages or distributions -- ``--pkg dir`` -- create the Sage package ``dir.spkg`` from the - directory ``dir`` -- ``--pkg_nc dir`` -- as ``--pkg``, but do not compress the package - ``--merge`` -- run Sage's automatic merge and test script - ``--sdist`` -- build a source distribution of Sage diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst index 868b8a96e12..9b48b106888 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst @@ -133,6 +133,7 @@ List of Polyhedron methods :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.vertex_facet_graph` | bipartite digraph given vertex-facet adjacency :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.adjacency_matrix` | adjacency matrix :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.incidence_matrix` | incidence matrix + :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.slack_matrix` | slack matrix :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.facet_adjacency_matrix` | adjacency matrix of the facets :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.vertex_adjacency_matrix` | adjacency matrix of the vertices diff --git a/src/doc/en/thematic_tutorials/geometry/polytope_tikz.rst b/src/doc/en/thematic_tutorials/geometry/polytope_tikz.rst index 6f0a36c980c..f5d45485680 100644 --- a/src/doc/en/thematic_tutorials/geometry/polytope_tikz.rst +++ b/src/doc/en/thematic_tutorials/geometry/polytope_tikz.rst @@ -21,18 +21,16 @@ tutorial shows how it all works. Instructions """""""""""" -To put an image of a 3d-polytope in LaTeX using TikZ and Sage, simply follow the instructions: +To put an image of a 3D-polytope in LaTeX using TikZ and Sage, simply follow the instructions: - Install `SageTex `_ (optional but recommended!) - Put ``\usepackage{tikz}`` in the preamble of your article - Open Sage and change the directory to your article's by the command ``cd /path/to/article`` - Input your polytope, called P for example, to Sage - Visualize the polytope P using the command ``P.show(aspect_ratio=1)`` -- This will open an interactive viewer named Jmol, in which you can rotate the polytope. Once the wished view angle is found, right click on the image and select *Console* -- In the dialog box click the button *State* -- Scroll up to the line starting with *moveto* -- It reads something like ``moveto 0.0 {x y z angle} scale`` -- Go back to Sage and type ``Img = P.projection().tikz([x,y,z],angle)`` +- This will open an interactive view in your default browser, where you can rotate the polytope. +- Once the desired view angle is found, click on the information icon in the lower right-hand corner and select *Get Viewpoint*. This will copy a string of the form '[x,y,z],angle' to your local clipboard. +- Go back to Sage and type ``Img = P.projection().tikz([x,y,z],angle)``. You can paste the string here to save some typing. - *Img* now contains a Sage object of type ``LatexExpr`` containing the raw TikZ picture of your polytope Then, you can either copy-paste it to your article by typing ``Img`` in Sage or save it to a file, by doing diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index 088924240be..ab3ea32e922 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -1332,8 +1332,8 @@ def coprod_list(t): all_q = Set(t[0]) tens_q = {} for a in all_q.subsets(): - left_q = sorted(list(a)) - right_q = sorted(list(all_q - a)) + left_q = sorted(a) + right_q = sorted(all_q - a) sign = Permutation(convert_perm(left_q + right_q)).signature() tens_q[(tuple(left_q), tuple(right_q))] = sign tens = {} diff --git a/src/sage/categories/bimodules.py b/src/sage/categories/bimodules.py index 5d78363039e..c05db937d72 100644 --- a/src/sage/categories/bimodules.py +++ b/src/sage/categories/bimodules.py @@ -107,7 +107,8 @@ def an_instance(cls): sage: Bimodules.an_instance() Category of bimodules over Rational Field on the left and Real Field with 53 bits of precision on the right """ - from sage.rings.all import QQ, RR + from sage.rings.rational_field import QQ + from sage.rings.real_mpfr import RR return cls(QQ, RR) def _repr_object_names(self): diff --git a/src/sage/categories/category_with_axiom.py b/src/sage/categories/category_with_axiom.py index 524fb42c386..03bb998a7aa 100644 --- a/src/sage/categories/category_with_axiom.py +++ b/src/sage/categories/category_with_axiom.py @@ -1660,7 +1660,7 @@ class ``Sets.Finite``), or in a separate file (typically in a class from sage.misc.cachefunc import cached_method, cached_function from sage.misc.lazy_attribute import lazy_class_attribute from sage.misc.lazy_import import LazyImport -from sage.misc.misc import call_method +from sage.misc.call import call_method from sage.categories.category import Category from sage.categories.category_singleton import Category_singleton from sage.categories.category_types import Category_over_base_ring diff --git a/src/sage/categories/coalgebras_with_basis.py b/src/sage/categories/coalgebras_with_basis.py index 8ac39c20d38..24505dcf067 100644 --- a/src/sage/categories/coalgebras_with_basis.py +++ b/src/sage/categories/coalgebras_with_basis.py @@ -197,7 +197,7 @@ def coproduct_iterated(self, n=1): if n == 1: return self.coproduct() from sage.functions.all import floor, ceil - from sage.rings.all import Integer + from sage.rings.integer import Integer # Use coassociativity of `\Delta` to perform many coproducts simultaneously. fn = floor(Integer(n-1)/2); cn = ceil(Integer(n-1)/2) diff --git a/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py b/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py index edb8a5ffbc6..720d0097632 100644 --- a/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py +++ b/src/sage/categories/complex_reflection_or_generalized_coxeter_groups.py @@ -339,7 +339,7 @@ def simple_reflection_orders(self): """ one = self.one() s = self.simple_reflections() - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ def mult_order(x): ct = ZZ.one() diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 91875a4a0f6..e01e5b66277 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -15,7 +15,7 @@ from sage.misc.cachefunc import cached_method, cached_in_parent_method from sage.misc.lazy_import import LazyImport from sage.misc.constant_function import ConstantFunction -from sage.misc.misc import attrcall +from sage.misc.call import attrcall from sage.categories.category_singleton import Category_singleton from sage.categories.enumerated_sets import EnumeratedSets from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets @@ -24,8 +24,6 @@ from sage.misc.flatten import flatten from copy import copy -from sage.rings.integer_ring import ZZ - class CoxeterGroups(Category_singleton): r""" @@ -319,6 +317,7 @@ def braid_orbit(self, word): braid_rels = self.braid_relations() I = self.index_set() + from sage.rings.integer_ring import ZZ be_careful = any(i not in ZZ for i in I) if be_careful: @@ -736,7 +735,7 @@ def sign_representation(self, base_ring=None, side="twosided"): """ if base_ring is None: - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ base_ring = ZZ from sage.modules.with_basis.representation import SignRepresentationCoxeterGroup return SignRepresentationCoxeterGroup(self, base_ring) @@ -1513,21 +1512,21 @@ def reduced_word_graph(self): y = tuple(y) # Check that the reduced expressions differ by only # a single braid move - i = 0 - while i < len(x) and x[i] == y[i]: - i += 1 - if i == len(x): + j = 0 + while j < len(x) and x[j] == y[j]: + j += 1 + if j == len(x): continue - a, b = x[i], y[i] + a, b = x[j], y[j] m = P.coxeter_matrix()[a, b] subword = [a, b] * (m // 2) subword2 = [b, a] * (m // 2) if m % 2: subword.append(a) subword2.append(b) - if (x[i:i+m] != tuple(subword) - or y[i:i+m] != tuple(subword2) - or x[i+m:] != y[i+m:]): + if (x[j:j+m] != tuple(subword) + or y[j:j+m] != tuple(subword2) + or x[j+m:] != y[j+m:]): continue edges.append([x, y, m]) G = Graph(edges, immutable=True, format="list_of_edges") diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index 7af4ec76dab..4b12ce0d8f7 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -29,12 +29,6 @@ from sage.categories.tensor import TensorProductsCategory from sage.categories.morphism import Morphism from sage.categories.homset import Hom, Homset -from sage.misc.latex import latex -from sage.combinat import ranker -from sage.graphs.dot2tex_utils import have_dot2tex -from sage.rings.integer import Integer -from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet -from sage.sets.family import Family class Crystals(Category_singleton): r""" @@ -144,6 +138,7 @@ def example(self, choice="highwt", **kwds): if choice == "naive": return examples.NaiveCrystal(**kwds) else: + from sage.rings.integer import Integer if isinstance(choice, Integer): return examples.HighestWeightCrystalOfTypeA(n=choice, **kwds) else: @@ -388,6 +383,7 @@ def __iter__(self, index_set=None, max_depth=float('inf')): if index_set is None: index_set = self.index_set() succ = lambda x: [x.f(i) for i in index_set] + [x.e(i) for i in index_set] + from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet R = RecursivelyEnumeratedSet(self.module_generators, succ, structure=None) return R.breadth_first_search_iterator(max_depth) @@ -540,6 +536,7 @@ def subcrystal(self, index_set=None, generators=None, max_depth=float("inf"), else: raise ValueError("direction must be either 'both', 'upper', or 'lower'") + from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet subset = RecursivelyEnumeratedSet(generators, succ, structure=None, enumeration='breadth', max_depth=max_depth) @@ -912,6 +909,7 @@ def digraph(self, subset=None, index_set=None): continue d[x][child]=i G = DiGraph(d) + from sage.graphs.dot2tex_utils import have_dot2tex if have_dot2tex(): G.set_latex_options(format="dot2tex", edge_labels=True, @@ -1127,12 +1125,15 @@ def dot_tex(self): 'digraph G { \n node [ shape=plaintext ];\n N_0 [ label = " ", texlbl = "$1$" ];\n N_1 [ label = " ", texlbl = "$2$" ];\n N_2 [ label = " ", texlbl = "$3$" ];\n N_0 -> N_1 [ label = " ", texlbl = "1" ];\n N_1 -> N_2 [ label = " ", texlbl = "2" ];\n}' """ import re + from sage.combinat import ranker + rank = ranker.from_list(self.list())[0] vertex_key = lambda x: "N_"+str(rank(x)) # To do: check the regular expression # Removing %-style comments, newlines, quotes # This should probably be moved to sage.misc.latex + from sage.misc.latex import latex quoted_latex = lambda x: re.sub("\"|\r|(%[^\n]*)?\n","", latex(x)) result = "digraph G { \n node [ shape=plaintext ];\n" @@ -1848,6 +1849,7 @@ def __init__(self, parent, cartan_type=None, virtualization = dict(virtualization) except (TypeError, ValueError): virtualization = {i: (virtualization(i),) for i in index_set} + from sage.sets.family import Family self._virtualization = Family(virtualization) self._scaling_factors = Family(scaling_factors) diff --git a/src/sage/categories/euclidean_domains.py b/src/sage/categories/euclidean_domains.py index bc3a5a1f321..fa4feb161ad 100644 --- a/src/sage/categories/euclidean_domains.py +++ b/src/sage/categories/euclidean_domains.py @@ -148,7 +148,7 @@ def _test_euclidean_degree(self, **options): min_degree = self.one().euclidean_degree() - from sage.rings.all import NN + from sage.rings.semirings.non_negative_integer_semiring import NN for a in S: tester.assertIn(a.euclidean_degree(), NN) tester.assertGreaterEqual(a.euclidean_degree(), min_degree) diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 686c5eb369a..d88743cc17f 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -20,7 +20,6 @@ from sage.categories.euclidean_domains import EuclideanDomains from sage.categories.division_rings import DivisionRings -import sage.rings.ring from sage.structure.element import coerce_binop class Fields(CategoryWithAxiom): @@ -119,6 +118,7 @@ def __contains__(self, x): 0 """ + import sage.rings.ring try: return self._contains_helper(x) or sage.rings.ring._is_Field(x) except Exception: @@ -559,7 +559,7 @@ def euclidean_degree(self): """ if self.is_zero(): raise ValueError("euclidean degree not defined for the zero element") - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ return ZZ.zero() def quo_rem(self, other): diff --git a/src/sage/categories/finite_complex_reflection_groups.py b/src/sage/categories/finite_complex_reflection_groups.py index 82f3800aa62..817b762c2ac 100644 --- a/src/sage/categories/finite_complex_reflection_groups.py +++ b/src/sage/categories/finite_complex_reflection_groups.py @@ -324,7 +324,7 @@ def number_of_reflection_hyperplanes(self): sage: W.number_of_reflection_hyperplanes() # optional - gap3 15 """ - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ return ZZ.sum(codeg + 1 for codeg in self.codegrees()) @cached_method @@ -358,7 +358,7 @@ def number_of_reflections(self): sage: W.number_of_reflections() # optional - gap3 15 """ - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ return ZZ.sum(deg - 1 for deg in self.degrees()) @cached_method @@ -413,7 +413,7 @@ def cardinality(self): sage: W.cardinality() # optional - gap3 192 """ - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ return ZZ.prod(self.degrees()) def is_well_generated(self): diff --git a/src/sage/categories/finite_coxeter_groups.py b/src/sage/categories/finite_coxeter_groups.py index 90e301bedef..8e7df277404 100644 --- a/src/sage/categories/finite_coxeter_groups.py +++ b/src/sage/categories/finite_coxeter_groups.py @@ -13,9 +13,6 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.coxeter_groups import CoxeterGroups -from sage.rings.all import AA, UniversalCyclotomicField, QQbar -from sage.rings.integer_ring import ZZ - class FiniteCoxeterGroups(CategoryWithAxiom): r""" @@ -742,9 +739,12 @@ def permutahedron(self, point=None, base_ring=None): n = self.one().canonical_matrix().rank() weights = self.fundamental_weights() if point is None: + from sage.rings.integer_ring import ZZ point = [ZZ.one()] * n v = sum(point[i-1] * weights[i] for i in weights.keys()) from sage.geometry.polyhedron.constructor import Polyhedron + from sage.rings.qqbar import AA, QQbar + from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField vertices = [v*w for w in self] if base_ring is None and v.base_ring() in [UniversalCyclotomicField(), QQbar]: vertices = [v.change_ring(AA) for v in vertices] diff --git a/src/sage/categories/finite_dimensional_algebras_with_basis.py b/src/sage/categories/finite_dimensional_algebras_with_basis.py index 754d26276e6..1d5ef56fce3 100644 --- a/src/sage/categories/finite_dimensional_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_algebras_with_basis.py @@ -32,7 +32,6 @@ from sage.categories.algebras import Algebras from sage.categories.associative_algebras import AssociativeAlgebras from sage.categories.tensor import TensorProductsCategory -from sage.matrix.constructor import Matrix class FiniteDimensionalAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): r""" @@ -701,6 +700,7 @@ def cartan_invariants_matrix(self): [0 0 0 1 0 1 1 0] [0 0 0 0 0 0 0 1] """ + from sage.matrix.constructor import Matrix from sage.rings.integer_ring import ZZ A_quo = self.semisimple_quotient() idempotents_quo = A_quo.central_orthogonal_idempotents() diff --git a/src/sage/categories/finite_posets.py b/src/sage/categories/finite_posets.py index b01ea7f4818..e262db24fbe 100644 --- a/src/sage/categories/finite_posets.py +++ b/src/sage/categories/finite_posets.py @@ -18,7 +18,6 @@ from sage.misc.abstract_method import abstract_method from sage.categories.category_with_axiom import CategoryWithAxiom -from sage.plot.plot import graphics_array class FinitePosets(CategoryWithAxiom): r""" @@ -1435,6 +1434,7 @@ def rowmotion_orbits_plots(self): Graphics Array of size 1 x 1 """ + from sage.plot.plot import graphics_array plot_of_orb_plots=[] max_orbit_size = 0 for orb in self.rowmotion_orbits(): @@ -1520,6 +1520,7 @@ def toggling_orbits_plots(self, vs): Graphics Array of size 1 x 1 """ + from sage.plot.plot import graphics_array plot_of_orb_plots=[] max_orbit_size = 0 for orb in self.toggling_orbits(vs): @@ -1889,7 +1890,7 @@ def order_ideals_lattice(self, as_ideals=True, facade=None): if facade is None: facade = self._is_facade if as_ideals: - from sage.misc.misc import attrcall + from sage.misc.call import attrcall from sage.sets.set import Set ideals = [Set(self.order_ideal(antichain)) for antichain in self.antichains()] diff --git a/src/sage/categories/finite_semigroups.py b/src/sage/categories/finite_semigroups.py index 1dc8a494619..76c082af096 100644 --- a/src/sage/categories/finite_semigroups.py +++ b/src/sage/categories/finite_semigroups.py @@ -11,7 +11,7 @@ # ***************************************************************************** from sage.misc.cachefunc import cached_method -from sage.misc.misc import attrcall +from sage.misc.call import attrcall from sage.categories.category_with_axiom import CategoryWithAxiom diff --git a/src/sage/categories/groups.py b/src/sage/categories/groups.py index 920ea94126a..712edff66bf 100644 --- a/src/sage/categories/groups.py +++ b/src/sage/categories/groups.py @@ -78,7 +78,7 @@ def free(index_set=None, names=None, **kwds): sage: F. = Groups().free(); F Free Group on generators {x, y, z} """ - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ if index_set in ZZ or (index_set is None and names is not None): from sage.groups.free_group import FreeGroup if names is None: diff --git a/src/sage/categories/highest_weight_crystals.py b/src/sage/categories/highest_weight_crystals.py index 0c7b99e2e8e..dc4441abe46 100644 --- a/src/sage/categories/highest_weight_crystals.py +++ b/src/sage/categories/highest_weight_crystals.py @@ -13,7 +13,6 @@ from sage.categories.crystals import (Crystals, CrystalHomset, CrystalMorphismByGenerators) from sage.categories.tensor import TensorProductsCategory -from sage.graphs.dot2tex_utils import have_dot2tex class HighestWeightCrystals(Category_singleton): """ @@ -331,7 +330,7 @@ def q_dimension(self, q=None, prec=None, use_product=False): + 36*q^12 + 44*q^13 + 57*q^14 + 70*q^15 + O(x^16) """ - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ WLR = self.weight_lattice_realization() I = self.index_set() mg = self.highest_weight_vectors() @@ -520,6 +519,7 @@ def digraph(self, subset=None, index_set=None, depth=None): visited = recently_visited G = DiGraph(d) + from sage.graphs.dot2tex_utils import have_dot2tex if have_dot2tex(): G.set_latex_options(format="dot2tex", edge_labels=True, diff --git a/src/sage/categories/lie_algebras.py b/src/sage/categories/lie_algebras.py index 51408b3bd10..b088a9cb39d 100644 --- a/src/sage/categories/lie_algebras.py +++ b/src/sage/categories/lie_algebras.py @@ -166,7 +166,7 @@ def example(self, gens=None): """ if gens is None: from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra - from sage.rings.all import QQ + from sage.rings.rational_field import QQ gens = SymmetricGroupAlgebra(QQ, 3).algebra_generators() from sage.categories.examples.lie_algebras import Example return Example(gens) diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index 00ba408cc77..8d6aa2821c2 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -22,8 +22,6 @@ from sage.categories.map import Map from sage.graphs.dot2tex_utils import have_dot2tex from sage.functions.other import ceil -from sage.rings.all import ZZ - class LoopCrystals(Category_singleton): r""" @@ -534,6 +532,7 @@ def is_perfect(self, ell=None): Implement a version for tensor products of KR crystals. """ + from sage.rings.integer_ring import ZZ if ell is None: if (self.cartan_type().dual().type() == 'BC' and self.cartan_type().rank() - 1 == self.r()): @@ -978,6 +977,7 @@ def energy_function(self, algorithm=None): if algorithm == 'definition': # Setup + from sage.rings.integer_ring import ZZ energy = ZZ.zero() R_mats = [[K.R_matrix(Kp) for Kp in self.parent().crystals[i+1:]] for i,K in enumerate(self.parent().crystals)] @@ -1179,6 +1179,7 @@ def __init__(self, B, Bp, normalization=0): sage: [H(x) for x in hw] [0, 1, 2, 1] """ + from sage.rings.integer_ring import ZZ self._B = B self._Bp = Bp self._R_matrix = self._B.R_matrix(self._Bp) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index ba8a1be9e0d..f77b2d0cbf3 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -29,7 +29,6 @@ from sage.categories.fields import Fields from sage.categories.modules import Modules from sage.categories.poor_man_map import PoorManMap -from sage.rings.infinity import Infinity from sage.structure.element import Element, parent @@ -967,6 +966,7 @@ def cardinality(self): sage: s.cardinality() +Infinity """ + from sage.rings.infinity import Infinity if self.dimension() == Infinity: return Infinity return self.base_ring().cardinality() ** self.dimension() diff --git a/src/sage/categories/monoids.py b/src/sage/categories/monoids.py index 87ce88a693d..42b55b8dda4 100644 --- a/src/sage/categories/monoids.py +++ b/src/sage/categories/monoids.py @@ -13,7 +13,6 @@ #****************************************************************************** from sage.misc.cachefunc import cached_method -from sage.misc.misc_c import prod from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.semigroups import Semigroups from sage.misc.lazy_import import LazyImport @@ -103,7 +102,7 @@ def free(index_set=None, names=None, **kwds): """ if names is not None: if isinstance(names, str): - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ if ',' not in names and index_set in ZZ: names = [names + repr(i) for i in range(index_set)] else: @@ -154,6 +153,7 @@ def prod(self, args): sage: S.prod([S('a'), S('b')]) 'ab' """ + from sage.misc.misc_c import prod return prod(args, self.one()) def _test_prod(self, **options): @@ -349,7 +349,7 @@ def free(index_set=None, names=None, **kwds): """ if names is not None: if isinstance(names, str): - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ if ',' not in names and index_set in ZZ: names = [names + repr(i) for i in range(index_set)] else: diff --git a/src/sage/categories/polyhedra.py b/src/sage/categories/polyhedra.py index a20538948f2..14006e85866 100644 --- a/src/sage/categories/polyhedra.py +++ b/src/sage/categories/polyhedra.py @@ -28,19 +28,23 @@ class PolyhedralSets(Category_over_base_ring): sage: P = Polyhedron() sage: P.parent().category().element_class - + sage: P.parent().category().element_class.mro() - [, + [, + , , , , , , , + , + , + , , , , - <... 'object'>] + ] sage: isinstance(P, P.parent().category().element_class) True """ diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index a410fdd1c76..0f2753185b4 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -4352,12 +4352,8 @@ def type_to_parent(P): ... TypeError: Not a scalar type. """ - import sage.rings.all - if P is int: - return sage.rings.all.ZZ - elif P is float: - return sage.rings.all.RDF - elif P is complex: - return sage.rings.all.CDF - else: + from sage.structure.coerce import py_scalar_parent + parent = py_scalar_parent(P) + if parent is None: raise TypeError("Not a scalar type.") + return parent diff --git a/src/sage/categories/regular_crystals.py b/src/sage/categories/regular_crystals.py index 7233ee70825..f9466c2fa23 100644 --- a/src/sage/categories/regular_crystals.py +++ b/src/sage/categories/regular_crystals.py @@ -22,8 +22,6 @@ from sage.categories.category_singleton import Category_singleton from sage.categories.crystals import Crystals from sage.categories.tensor import TensorProductsCategory -from sage.combinat.subset import Subsets -from sage.graphs.dot2tex_utils import have_dot2tex class RegularCrystals(Category_singleton): r""" @@ -261,7 +259,7 @@ def demazure_subcrystal(self, element, reduced_word, only_support=True): ([[2, 2]], [[1, 2]], 0)] """ from sage.combinat.free_module import CombinatorialFreeModule - from sage.rings.all import QQ + from sage.rings.rational_field import QQ C = CombinatorialFreeModule(QQ, self) D = self.demazure_operator(C(element), reduced_word) if only_support: @@ -450,6 +448,7 @@ def wt_zero(x): edges.append([x, y, i]) from sage.graphs.all import DiGraph G = DiGraph([X, edges], format="vertices_and_edges", immutable=True) + from sage.graphs.dot2tex_utils import have_dot2tex if have_dot2tex(): G.set_latex_options(format="dot2tex", edge_labels=True, color_by_label=self.cartan_type()._index_set_coloring) @@ -747,6 +746,8 @@ def _test_stembridge_local_axioms(self, index_set=None, verbose=False, **options goodness=True if index_set is None: index_set=self.index_set() + from sage.combinat.subset import Subsets + for (i,j) in Subsets(index_set, 2): if self.e(i) is not None and self.e(j) is not None: triple=self.stembridgeTriple(i,j) @@ -867,6 +868,7 @@ def dual_equivalence_class(self, index_set=None): from sage.graphs.graph import Graph G = Graph([visited, edges], format="vertices_and_edges", immutable=True, multiedges=True) + from sage.graphs.dot2tex_utils import have_dot2tex if have_dot2tex(): G.set_latex_options(format="dot2tex", edge_labels=True, color_by_label=self.cartan_type()._index_set_coloring) diff --git a/src/sage/categories/semigroups.py b/src/sage/categories/semigroups.py index a24d8c8a4b5..a358149dd13 100644 --- a/src/sage/categories/semigroups.py +++ b/src/sage/categories/semigroups.py @@ -16,7 +16,6 @@ from sage.misc.abstract_method import abstract_method from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import LazyImport -from sage.misc.misc_c import prod from sage.categories.category_with_axiom import CategoryWithAxiom, all_axioms from sage.categories.algebra_functor import AlgebrasCategory from sage.categories.subquotients import SubquotientsCategory @@ -169,6 +168,7 @@ def prod(self, args): ... AssertionError: Cannot compute an empty product in a semigroup """ + from sage.misc.misc_c import prod assert len(args) > 0, "Cannot compute an empty product in a semigroup" return prod(args[1:], args[0]) diff --git a/src/sage/categories/sets_with_grading.py b/src/sage/categories/sets_with_grading.py index 9585d861390..36a3a9aa89f 100644 --- a/src/sage/categories/sets_with_grading.py +++ b/src/sage/categories/sets_with_grading.py @@ -14,7 +14,6 @@ from .category_types import Category from sage.categories.sets_cat import Sets from sage.categories.enumerated_sets import EnumeratedSets -from sage.sets.non_negative_integers import NonNegativeIntegers class SetsWithGrading(Category): @@ -145,6 +144,7 @@ def grading_set(self): sage: SetsWithGrading().example().grading_set() Non negative integers """ + from sage.sets.non_negative_integers import NonNegativeIntegers return NonNegativeIntegers() # TODO: diff --git a/src/sage/categories/supercrystals.py b/src/sage/categories/supercrystals.py index abd528c1d86..51560ae262d 100644 --- a/src/sage/categories/supercrystals.py +++ b/src/sage/categories/supercrystals.py @@ -257,7 +257,7 @@ def character(self): B[(1, 0, 0, 0, 0)] + B[(0, 1, 0, 0, 0)] + B[(0, 0, 1, 0, 0)] + B[(0, 0, 0, 1, 0)] + B[(0, 0, 0, 0, 1)] """ - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ A = self.weight_lattice_realization().algebra(ZZ) return A.sum(A(x.weight()) for x in self) diff --git a/src/sage/categories/weyl_groups.py b/src/sage/categories/weyl_groups.py index 6ea5cf878ea..2f84ca64bb7 100644 --- a/src/sage/categories/weyl_groups.py +++ b/src/sage/categories/weyl_groups.py @@ -12,8 +12,6 @@ from sage.misc.lazy_import import LazyImport from sage.categories.category_singleton import Category_singleton from sage.categories.coxeter_groups import CoxeterGroups -from sage.rings.infinity import infinity -from sage.rings.rational_field import QQ class WeylGroups(Category_singleton): @@ -279,7 +277,7 @@ def is_pieri_factor(self): return self in self.parent().pieri_factors() - def left_pieri_factorizations(self, max_length = infinity): + def left_pieri_factorizations(self, max_length=None): r""" Returns all factorizations of ``self`` as `uv`, where `u` is a Pieri factor and `v` is an element of the Weyl group. @@ -335,6 +333,9 @@ def left_pieri_factorizations(self, max_length = infinity): sage: W.from_reduced_word([0,2,1,0]).left_pieri_factorizations().cardinality() 6 """ + if max_length is None: + from sage.rings.infinity import infinity + max_length = infinity pieri_factors = self.parent().pieri_factors() def predicate(u): return u in pieri_factors and u.length() <= max_length @@ -342,7 +343,7 @@ def predicate(u): return self.binary_factorizations(predicate) @cached_in_parent_method - def stanley_symmetric_function_as_polynomial(self, max_length = infinity): + def stanley_symmetric_function_as_polynomial(self, max_length=None): r""" Returns a multivariate generating function for the number of factorizations of a Weyl group element into Pieri @@ -404,8 +405,12 @@ def stanley_symmetric_function_as_polynomial(self, max_length = infinity): by taking right factors, and in particular Grassmanian elements. """ + if max_length is None: + from sage.rings.infinity import infinity + max_length = infinity W = self.parent() pieri_factors = W.pieri_factors() + from sage.rings.rational_field import QQ R = QQ[','.join('x%s'%l for l in range(1,pieri_factors.max_length()+1))] x = R.gens() if self.is_one(): @@ -483,6 +488,7 @@ def stanley_symmetric_function(self): - [Pon2010]_ """ import sage.combinat.sf + from sage.rings.rational_field import QQ m = sage.combinat.sf.sf.SymmetricFunctions(QQ).monomial() return m.from_polynomial_exp(self.stanley_symmetric_function_as_polynomial()) @@ -633,6 +639,7 @@ def inversion_arrangement(self, side='right'): inv = self.inversions(side=side, inversion_type='roots') from sage.geometry.hyperplane_arrangement.arrangement import HyperplaneArrangements I = self.parent().cartan_type().index_set() + from sage.rings.rational_field import QQ H = HyperplaneArrangements(QQ, tuple(['a{}'.format(i) for i in I])) gens = H.gens() if not inv: diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index 4b8f04dc4ed..ae990791368 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -211,12 +211,10 @@ class should inherit from this class. Also ``AbstractLinearCode`` should never from sage.cpython.string import bytes_to_str from sage.interfaces.all import gap -from sage.categories.modules import Modules from sage.categories.cartesian_product import cartesian_product from sage.categories.fields import Fields from sage.matrix.matrix_space import MatrixSpace from sage.modules.free_module import VectorSpace -from sage.modules.module import Module from sage.modules.free_module_element import vector from sage.arith.all import GCD, binomial from sage.groups.all import SymmetricGroup @@ -226,7 +224,6 @@ class should inherit from this class. Also ``AbstractLinearCode`` should never from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.structure.parent import Parent from sage.misc.all import prod from sage.misc.functional import is_even from sage.misc.cachefunc import cached_method @@ -234,7 +231,6 @@ class should inherit from this class. Also ``AbstractLinearCode`` should never from sage.combinat.subset import Subsets from sage.features.gap import GapPackage from sage.coding.linear_code_no_metric import AbstractLinearCodeNoMetric -from sage.coding.abstract_code import AbstractCode from .encoder import Encoder from .decoder import Decoder diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index 1932f4f057b..ae911dfc154 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -16,7 +16,7 @@ [0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1] sage: R.period(4) #the period of the fibonacci sequence modulo 4 6 - sage: R.pthpowers(2, 10**30) # long time (7 seconds) -- in fact these are all squares, c.f. [BMS06] + sage: R.pthpowers(2, 10**10) # long time (7 seconds) -- in fact these are all squares, c.f. [BMS06] [0, 1, 2, 12] sage: S = BinaryRecurrenceSequence(8,1) #a Lucas sequence @@ -24,7 +24,7 @@ 148 sage: S(5) % 73 == S(5 +148) %73 True - sage: S.pthpowers(3,10**30) # long time (3 seconds) -- provably finds the indices of all 3rd powers less than 10^30 + sage: S.pthpowers(3,10**10) # long time (3 seconds) -- provably finds the indices of all 3rd powers less than 10^10 [0, 1, 2] sage: T = BinaryRecurrenceSequence(2,0,1,2) @@ -61,11 +61,12 @@ from sage.structure.sage_object import SageObject from sage.matrix.constructor import matrix +from sage.modules.free_module_element import vector from sage.rings.number_field.number_field import QuadraticField from sage.rings.finite_rings.integer_mod_ring import Integers from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.integer import Integer -from sage.arith.all import gcd, lcm, next_prime, is_prime, next_prime_power, legendre_symbol +from sage.arith.all import lcm, next_prime, is_prime, next_prime_power, legendre_symbol from sage.functions.log import log from sage.functions.other import sqrt @@ -129,7 +130,6 @@ def __init__(self, b, c, u0=0, u1=1): self._PGoodness = {} #dictionary to cache primes that are "good" by some prime power self._ell = 1 #variable that keeps track of the last prime power to be used as a goodness - def __repr__(self): """ Give string representation of the class. @@ -158,13 +158,10 @@ def __eq__(self, other): sage: T = BinaryRecurrenceSequence(3,3,2,2) sage: R == T False - """ - return (self.u0 == other.u0) and (self.u1 == other.u1) and (self.b == other.b) and (self.c == other.c) def __call__(self, n, modulus=0): - """ Give the nth term of a binary recurrence sequence, possibly mod some modulus. @@ -189,12 +186,12 @@ def __call__(self, n, modulus=0): 9 sage: R(101)%12 9 - """ R = Integers(modulus) - F = matrix(R, [[0,1],[self.c,self.b]]) # F*[u_{n}, u_{n+1}]^T = [u_{n+1}, u_{n+2}]^T (T indicates transpose). - v = matrix(R, [[self.u0],[self.u1]]) - return list(F**n*v)[0][0] + F = matrix(R, [[0, 1], [self.c, self.b]]) + # F*[u_{n}, u_{n+1}]^T = [u_{n+1}, u_{n+2}]^T (T indicates transpose). + v = vector(R, [self.u0, self.u1]) + return list(F**n * v)[0] def is_degenerate(self): """ @@ -237,16 +234,13 @@ def is_degenerate(self): True sage: T.is_arithmetic() True - """ - - if (self.b**2+4*self.c) != 0: - - if (self.b**2+4*self.c).is_square(): - A = sqrt((self.b**2+4*self.c)) - + D = self.b**2 + 4 * self.c + if D != 0: + if D.is_square(): + A = sqrt(D) else: - K = QuadraticField((self.b**2+4*self.c), 'x') + K = QuadraticField(D, 'x') A = K.gen() aa = (self.u1 - self.u0*(self.b + A)/2)/(A) #called `a` in Docstring @@ -254,17 +248,15 @@ def is_degenerate(self): #(b+A)/2 is called alpha in Docstring, (b-A)/2 is called beta in Docstring - if (self.b - A) != 0: - if ((self.b+A)/(self.b-A))**(6) == 1: + if self.b != A: + if ((self.b+A)/(self.b-A))**6 == 1: return True else: return True - if aa*bb*(self.b + A)*(self.b - A) == 0: - return True - return False - return True + return aa*bb*(self.b + A)*(self.b - A) == 0 + return True def is_geometric(self): """ @@ -281,15 +273,13 @@ def is_geometric(self): [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] sage: S.is_geometric() True - """ - #If [u_0, u_1]^T is an eigenvector for the incrementation matrix F = [[0,1],[c,b]], then the sequence #is geometric, ie we can write u_n = a*r^n for some a and r. #We decide if u0, u1, u2 = b*u1+c*u0 are in geometric progression by whether u1^2 = (b*u1+c*u0)*u0 - return bool((self.u1)**2 == (self.b*self.u1 + self.c*self.u0)*self.u0) + return (self.u1)**2 == (self.b*self.u1 + self.c*self.u0)*self.u0 def is_quasigeometric(self): """ @@ -318,24 +308,20 @@ def is_quasigeometric(self): sage: R.is_quasigeometric() True """ - - #First test if F is singular... i.e. beta = 0 + # First test if F is singular... i.e. beta = 0 if self.c == 0: return True - #Otherwise test if alpha/beta is a root of unity that is not 1 - else: - if (self.b**2+4*self.c) != 0: #thus alpha/beta != 1 - - if (self.b**2+4*self.c).is_square(): - A = sqrt((self.b**2+4*self.c)) - - else: - K = QuadraticField((self.b**2+4*self.c), 'x') - A = K.gen() - - if ((self.b+A)/(self.b-A))**(6) == 1: - return True + # Otherwise test if alpha/beta is a root of unity that is not 1 + D = self.b**2 + 4 * self.c + if D != 0: # thus alpha/beta != 1 + if D.is_square(): + A = sqrt(D) + else: + K = QuadraticField(D, 'x') + A = K.gen() + if ((self.b+A)/(self.b-A))**6 == 1: + return True return False @@ -356,11 +342,7 @@ def is_arithmetic(self): sage: S.is_arithmetic() True """ - - #Test if u_1-u_0 = u_2-u_1 = u_3-u_2 - - return bool(self(1) - self(0) == self(2) - self(1) == self(3) - self(2)) - + return (self(1) - self(0) == self(2) - self(1) == self(3) - self(2)) def period(self, m): """ @@ -408,7 +390,7 @@ def period(self, m): sage: S.period(17) 8 - Note: the answer is cached. + .. NOTE:: The answer is cached. """ #If we have already computed the period mod m, then we return the stored value. @@ -418,8 +400,8 @@ def period(self, m): else: R = Integers(m) - A = matrix(R, [[0,1],[self.c,self.b]]) - w = matrix(R, [[self.u0],[self.u1]]) + A = matrix(R, [[0, 1], [self.c, self.b]]) + w = vector(R, [self.u0, self.u1]) Fac = list(m.factor()) Periods = {} @@ -433,7 +415,8 @@ def period(self, m): #multiplying the period mod p by powers of p. for i in Fac: - p = i[0]; e = i[1] + p = i[0] + e = i[1] #first compute the period mod p if p in self._period_dict: perp = self._period_dict[p] @@ -457,7 +440,7 @@ def period(self, m): Mfac = p1fac #check if the trace is 2, then the order is a multiple of p dividing p*(p-1) - elif (FF).trace() == 2: + elif FF.trace() == 2: M = p-1 Mfac = p1fac F = F**p #replace F by F^p as now we only need to determine the factor dividing (p-1) @@ -467,12 +450,12 @@ def period(self, m): M = (p+1)*(p-1) p2fac = list((p+1).factor()) #factor the (p+1) and (p-1) terms separately and then combine for speed Mfac_dic = {} - for i in list(p1fac + p2fac): - if i[0] not in Mfac_dic: - Mfac_dic[i[0]] = i[1] + for i0, i1 in list(p1fac + p2fac): + if i0 not in Mfac_dic: + Mfac_dic[i0] = i1 else: - Mfac_dic[i[0]] = Mfac_dic[i[0]] + i[1] - Mfac = [(i,Mfac_dic[i]) for i in Mfac_dic] + Mfac_dic[i0] += i1 + Mfac = list(Mfac_dic.items()) #Now use a fast order algorithm to compute the period. We know that the period divides #M = i_1*i_2*...*i_l where the i_j denote not necessarily distinct prime factors. As @@ -480,19 +463,19 @@ def period(self, m): #all factors have been iterated over, the result is the period mod p. Mfac = list(Mfac) - C=[] + C = [] #expand the list of prime factors so every factor is with multiplicity 1 - for i in range(len(Mfac)): - for j in range(Mfac[i][1]): - C.append(Mfac[i][0]) + for i0, i1 in Mfac: + for j in range(i1): + C.append(i0) Mfac = C n = M - for i in Mfac: - b = Integer(n/i) - if F**b*v == v: + for ii in Mfac: + b = n // ii + if F**b * v == v: n = b perp = n @@ -515,12 +498,11 @@ def period(self, m): #take the lcm of the periods mod all distinct primes dividing m period = 1 for p in Periods: - period = lcm(Periods[p],period) + period = lcm(Periods[p], period) self._period_dict[m] = period #cache the period mod m return period - def pthpowers(self, p, Bound): """ Find the indices of proveably all pth powers in the recurrence sequence bounded by Bound. @@ -542,15 +524,15 @@ def pthpowers(self, p, Bound): EXAMPLES:: sage: R = BinaryRecurrenceSequence(1,1) #the Fibonacci sequence - sage: R.pthpowers(2, 10**30) # long time (7 seconds) -- in fact these are all squares, c.f. [BMS2006]_ + sage: R.pthpowers(2, 10**10) # long time (7 seconds) -- in fact these are all squares, c.f. [BMS2006]_ [0, 1, 2, 12] sage: S = BinaryRecurrenceSequence(8,1) #a Lucas sequence - sage: S.pthpowers(3,10**30) # long time (3 seconds) -- provably finds the indices of all 3rd powers less than 10^30 + sage: S.pthpowers(3,10**10) # long time (3 seconds) -- provably finds the indices of all 3rd powers less than 10^10 [0, 1, 2] sage: Q = BinaryRecurrenceSequence(3,3,2,1) - sage: Q.pthpowers(11,10**30) # long time (7.5 seconds) + sage: Q.pthpowers(11,10**10) # long time (7.5 seconds) [1] If the sequence is degenerate, and there are no ``p`` th powers, returns `[]`. Otherwise, if @@ -576,10 +558,11 @@ def pthpowers(self, p, Bound): sage: L.pthpowers(2,10**30) [] - NOTE: This function is primarily optimized in the range where ``Bound`` is much larger than ``p``. + .. NOTE:: + This function is primarily optimized in the range where + ``Bound`` is much larger than ``p``. """ - #Thanks to Jesse Silliman for helpful conversations! #Reset the dictionary of good primes, as this depends on p @@ -599,7 +582,7 @@ def pthpowers(self, p, Bound): no_powers = False break if no_powers: - if _is_p_power(self.u0,p): + if _is_p_power(self.u0, p): return [0] return [] else: @@ -619,7 +602,7 @@ def pthpowers(self, p, Bound): #Look at classes n = k mod p, for k = 1,...,p. - for k in range(1,p+1): + for k in range(1, p + 1): #The linear equation alpha^(k-1)*u_0 + (k+pm)*(alpha^(k-1)*u1 - u0*alpha^k) #must thus be a pth power. This is a linear equation in m, namely, A + B*m, where @@ -658,10 +641,11 @@ def pthpowers(self, p, Bound): ell = p + 1 while not is_prime(ell): - ell = ell + p + ell += p F = GF(ell) - a0 = F(self.u0); a1 = F(self.u1) #a0 and a1 are variables for terms in sequence + a0 = F(self.u0) + a1 = F(self.u1) #a0 and a1 are variables for terms in sequence bf, cf = F(self.b), F(self.c) for n in range(Bound): # n is the index of the a0 @@ -692,7 +676,7 @@ def pthpowers(self, p, Bound): #Try to get good data mod M2 #patience of how long we should search for a "good prime" - patience = 0.01 * _estimated_time(lcm(M2,p*next_prime_power(qq)), M1, len(cong), p) + patience = 0.01 * _estimated_time(lcm(M2, p*next_prime_power(qq)), M1, len(cong), p) tries = 0 #This loop uses primes to get a small set of congruences mod M2. @@ -729,19 +713,19 @@ def pthpowers(self, p, Bound): cong = list(cong) qqold = qq qq = next_prime_power(qq) - M2 = lcm(M2,p*qq) + M2 = lcm(M2, p * qq) break else: qq = next_prime_power(qq) - M2 = lcm(M2,p*qq) + M2 = lcm(M2, p * qq) cong = list(cong) break #Document how long each element of cong has been there for i in cong: if i in Possible_count: - Possible_count[i] = Possible_count[i] + 1 + Possible_count[i] += 1 else: Possible_count[i] = 1 @@ -751,7 +735,7 @@ def pthpowers(self, p, Bound): if Possible_count[i] == 7: n = Integer(i) if n < Bound: - if _is_p_power(self(n),p): + if _is_p_power(self(n), p): powers.append(n) #check for a contradiction @@ -765,7 +749,6 @@ def pthpowers(self, p, Bound): def _prime_powers(N): - """ Find the prime powers dividing ``N``. @@ -787,25 +770,21 @@ def _prime_powers(N): sage: sage.combinat.binary_recurrence_sequences._prime_powers(65537) [65537] - """ - output = sorted([i ** j for i, j in N.factor()]) - return output + return sorted(i**j for i, j in N.factor()) -#This function finds the largest prime power divisor of an integer N def _largest_ppower_divisor(N): - """ Find the largest prime power divisor of N. INPUT: - - ``N`` -- an integer (of which the largest prime power divisor will be found) + - ``N`` -- an integer OUTPUT: - - The largest prime power dividing ``N``. + The largest prime power dividing ``N``. EXAMPLES:: @@ -813,16 +792,11 @@ def _largest_ppower_divisor(N): 53 sage: sage.combinat.binary_recurrence_sequences._largest_ppower_divisor(65537) 65537 - """ - - output = _prime_powers(N)[-1] - - return output + return _prime_powers(N)[-1] def _goodness(n, R, p): - """ Return the goodness of ``n`` for the sequence ``R`` and the prime ``p`` -- that is the largest non-``p`` prime power dividing ``period(n)``. @@ -850,13 +824,10 @@ def _goodness(n, R, p): 4 sage: R.period(13) #the period of R mod 13 is divisible by 7 28 - """ - - #The period of R mod ell + # The period of R mod ell K = R.period(n) - - return _largest_ppower_divisor(K/gcd(K,p)) + return _largest_ppower_divisor(K // K.gcd(p)) def _next_good_prime(p, R, qq, patience, qqold): @@ -912,14 +883,13 @@ def _next_good_prime(p, R, qq, patience, qqold): #Possible_Primes keeps track of possible primes satisfying our goodness requirements we might return Possible_Primes = [] - #check to see if anything in R._PGoodness fits our goodness requirements for j in R._PGoodness: if (qqold < j <= qq) and len(R._PGoodness[j]): Possible_Primes.append(R._PGoodness[j][0]) #If we found good primes, we take the smallest - if Possible_Primes != []: + if Possible_Primes: q = min(Possible_Primes) n = _goodness(q, R, p) del R._PGoodness[n][0] #if we are going to use it, then we delete it from R._PGoodness @@ -1000,9 +970,8 @@ def _is_p_power_mod(a, p, N): if v >= e: continue - #otherwise, it can only be a pth power if v is a multiple of p. - - if v % p != 0: + # otherwise, it can only be a pth power if v is a multiple of p. + if v % p: return False #in this cse it is a pth power if x is a pth power mod q^(e-v), so let x = aa, @@ -1037,7 +1006,7 @@ def _is_p_power_mod(a, p, N): #We use the strong statement of Hensel's lemma, which implies that if p is odd #and aa is a pth power mod p^2, then aa is a pth power mod any higher power of p - if p % 2 == 1: + if p % 2: #ZZ/(p^2)ZZ^\times is abstractly isomorphic to ZZ/(p)ZZ cross ZZ/(p-1)ZZ. then #aa is a pth power mod p^2 if (aa)^(p*(p-1)/p) == 1, ie if aa^(p-1) == 1. @@ -1099,12 +1068,12 @@ def _estimated_time(M2, M1, length, p): return (length * (Q/p)**NPrimes).n() + #Find the list of necessary congruences for the index n of binary recurrence #sequence R using the fact that the reduction mod ell must be a pth power def _find_cong1(p, R, ell): - """ - Find the list of permissible indices `n` for which `u_n = y^p` mod ``ell``. + Find the list of permissible indices `n` for which `u_n = y^p` mod ``ell``. INPUT: @@ -1123,18 +1092,16 @@ def _find_cong1(p, R, ell): sage: R = BinaryRecurrenceSequence(1,1) sage: sage.combinat.binary_recurrence_sequences._find_cong1(7, R, 29) ([0, 1, 2, 12, 13], 14) - """ - F = GF(ell) - u0 = F(R.u0); u1 = F(R.u1) + u0 = F(R.u0) + u1 = F(R.u1) bf, cf = F(R.b), F(R.c) - a0 = u0; a1 = u1 #a0 and a1 are variables for terms in sequence + a0 = u0 + a1 = u1 #a0 and a1 are variables for terms in sequence #The set of pth powers mod ell - PPowers = set([]) - for i in F: - PPowers.add(i**p) + PPowers = set(i**p for i in F) #The period of R mod ell modu = R.period(ell) @@ -1157,11 +1124,9 @@ def _find_cong1(p, R, ell): return cong1, modu -#check for when a is a perfect pth power def _is_p_power(a, p): - """ - Determine whether ``a`` is a ``p`` th power. + Determine whether ``a`` is a perfect ``p`` th power. INPUT: @@ -1173,17 +1138,14 @@ def _is_p_power(a, p): - True if ``a`` is a ``p`` th power; else False. - EXAMPLES:: sage: sage.combinat.binary_recurrence_sequences._is_p_power(2**7,7) True sage: sage.combinat.binary_recurrence_sequences._is_p_power(2**7*3**2,7) False - """ - - return (int(a**(1/p))**p == a) - - - + return int(a**(1/p))**p == a + # slower tentative ? + # _, test = Integer(a).nth_root(p, truncate_mode=True) + # return test diff --git a/src/sage/combinat/binary_tree.py b/src/sage/combinat/binary_tree.py index cb2b1376c77..b2b3f0b6fe8 100644 --- a/src/sage/combinat/binary_tree.py +++ b/src/sage/combinat/binary_tree.py @@ -23,9 +23,6 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** -# python3 -from __future__ import division, absolute_import - from sage.structure.list_clone import ClonableArray from sage.combinat.abstract_tree import (AbstractClonableTree, AbstractLabelledClonableTree) @@ -2016,15 +2013,9 @@ def in_order_traversal_iter(self): if self.is_empty(): yield self return - # TODO:: PYTHON 3 - # yield from self[0].in_order_traversal_iter() - for left_subtree in self[0].in_order_traversal_iter(): - yield left_subtree + yield from self[0].in_order_traversal_iter() yield self - # TODO:: PYTHON 3 - # yield from self[1].in_order_traversal_iter() - for right_subtree in self[1].in_order_traversal_iter(): - yield right_subtree + yield from self[1].in_order_traversal_iter() def in_order_traversal(self, node_action=None, leaf_action=None): r""" diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index 77b4a6f7113..f112e45491f 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -512,7 +512,7 @@ def is_admissible(self): sage: C = crystals.AlcovePaths(['A',2],[1,1]); C Highest weight crystal of alcove paths of type ['A', 2] and weight Lambda[1] + Lambda[2] - sage: roots = sorted(list(C._R._root_lattice.positive_roots())); roots + sage: roots = sorted(C._R._root_lattice.positive_roots()); roots [alpha[1], alpha[1] + alpha[2], alpha[2]] sage: r1 = C._R(roots[0],0); r1 (alpha[1], 0) diff --git a/src/sage/combinat/crystals/fast_crystals.py b/src/sage/combinat/crystals/fast_crystals.py index e98989df6ba..2f964bb60de 100644 --- a/src/sage/combinat/crystals/fast_crystals.py +++ b/src/sage/combinat/crystals/fast_crystals.py @@ -1,7 +1,7 @@ r""" Fast Rank Two Crystals """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007 Anne Schilling # Nicolas Thiery # Ben Brubaker @@ -17,8 +17,8 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#**************************************************************************** +# https://www.gnu.org/licenses/ +# *************************************************************************** from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent @@ -91,7 +91,7 @@ class FastCrystal(UniqueRepresentation, Parent): @staticmethod def __classcall__(cls, cartan_type, shape, format = "string"): """ - Normalizes the input arguments to ensure unique representation + Normalize the input arguments to ensure unique representation EXAMPLES:: @@ -245,12 +245,13 @@ def __call__(self, value): sage: C(x) is x True """ - if parent(value) is self: return value + if parent(value) is self: + return value return self.element_class(self, value, self.format) def list(self): """ - Returns a list of the elements of self. + Return a list of the elements of self. EXAMPLES:: @@ -269,7 +270,7 @@ def list(self): def digraph(self): """ - Returns the digraph associated to self. + Return the digraph associated to self. EXAMPLES:: @@ -281,7 +282,7 @@ def digraph(self): def cmp_elements(self, x,y): r""" - Returns True if and only if there is a path from x to y in the + Return True if and only if there is a path from x to y in the crystal graph. Because the crystal graph is classical, it is a directed acyclic @@ -326,7 +327,7 @@ def __init__(self, parent, value, format): def weight(self): """ - Returns the weight of self. + Return the weight of self. EXAMPLES:: @@ -411,7 +412,7 @@ def _richcmp_(self, other, op): def e(self, i): """ - Returns the action of `e_i` on self. + Return the action of `e_i` on self. EXAMPLES:: @@ -430,7 +431,7 @@ def e(self, i): def f(self, i): """ - Returns the action of `f_i` on self. + Return the action of `f_i` on self. EXAMPLES:: @@ -446,6 +447,3 @@ def f(self, i): else: r = self.parent()._rootoperators[self.value][3] return self.parent()(r) if r is not None else None - - -#FastCrystal.Element = FastCrystalElement diff --git a/src/sage/combinat/designs/all.py b/src/sage/combinat/designs/all.py index 7fb0763a1af..7ec907e7100 100644 --- a/src/sage/combinat/designs/all.py +++ b/src/sage/combinat/designs/all.py @@ -1,30 +1,8 @@ """ Combinatorial design features that are imported by default in the interpreter namespace - -Test for deprecations of imports into global namespace:: - - sage: designs_from_XML - doctest:warning...: - DeprecationWarning: - Importing designs_from_XML from here is deprecated. If you need to use it, please import it directly from sage.combinat.designs.ext_rep - See https://trac.sagemath.org/27066 for details. - ... - - sage: designs_from_XML_url - doctest:warning...: - DeprecationWarning: - Importing designs_from_XML_url from here is deprecated. If you need to use it, please import it directly from sage.combinat.designs.ext_rep - See https://trac.sagemath.org/27066 for details. - ... """ -from __future__ import absolute_import - from sage.misc.lazy_import import lazy_import -lazy_import("sage.combinat.designs.ext_rep", ['designs_from_XML', - 'designs_from_XML_url'], - deprecation=27066) - lazy_import('sage.combinat.designs.block_design', 'BlockDesign') lazy_import('sage.combinat.designs.incidence_structures', 'IncidenceStructure') @@ -36,5 +14,3 @@ ['CoveringDesign', 'schonheim', 'trivial_covering_design']) from . import design_catalog as designs - -del absolute_import diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index 1866fdc6b3c..22b453120e3 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -4571,7 +4571,7 @@ def BIBD_201_6_1(): # (n,k,lambda)-BIBD family. # # This dictionary is used by designs.BalancedIncompleteBlockDesign - +# Note that the values are a list of blocks and not a design object BIBD_constructions = { ( 45,9,8): BIBD_45_9_8, ( 66,6,1): BIBD_66_6_1, @@ -4584,7 +4584,7 @@ def BIBD_201_6_1(): (136,6,1): BIBD_136_6_1, (141,6,1): BIBD_141_6_1, (171,6,1): BIBD_171_6_1, - (176,50,14): HigmanSimsDesign, + (176,50,14): lambda : HigmanSimsDesign().blocks(), (196,6,1): BIBD_196_6_1, (201,6,1): BIBD_201_6_1, } diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index 0bc319e6399..04fbe15d7b3 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -180,7 +180,7 @@ sage: E E_1^*(1->12, 10->1,11, 11->1,12, 12->1, 2->13, 3->14, 4->15, 5->16, 6->17, 7->18, 8->19, 9->1,10) sage: P = Patch([Face((0,0,0,0,0,0,0,0,0,0,0,0),t) for t in [1,2,3]]) - sage: for x in sorted(list(E(P)), key=lambda x : (x.vector(),x.type())): print(x) + sage: for x in sorted(E(P), key=lambda x : (x.vector(),x.type())): print(x) [(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1]* [(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 2]* [(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 12]* diff --git a/src/sage/combinat/finite_state_machine_generators.py b/src/sage/combinat/finite_state_machine_generators.py index e840ea303c5..ba7d86b0d49 100644 --- a/src/sage/combinat/finite_state_machine_generators.py +++ b/src/sage/combinat/finite_state_machine_generators.py @@ -1990,7 +1990,7 @@ def f(n): if missing_initial_values: raise ValueError( "Missing initial values for %s." % - sorted(list(missing_initial_values))) + sorted(missing_initial_values)) for cycle in recursion_digraph.all_simple_cycles(): assert cycle[0] is cycle[-1] @@ -2020,7 +2020,7 @@ def f(n): if superfluous_initial_values: raise ValueError( "Superfluous initial values for %s." % - sorted(list(superfluous_initial_values))) + sorted(superfluous_initial_values)) for state in T.iter_states(): state.is_final = True diff --git a/src/sage/combinat/fully_packed_loop.py b/src/sage/combinat/fully_packed_loop.py index 3323a1de19b..2afdc0b6887 100644 --- a/src/sage/combinat/fully_packed_loop.py +++ b/src/sage/combinat/fully_packed_loop.py @@ -1154,10 +1154,14 @@ def link_pattern(self): i,j = unrank(k) # initial direction - if i == -1: d = R - elif i == n: d = L - elif j == -1: d = U - elif j == n: d = D + if i == -1: + d = R + elif i == n: + d = L + elif j == -1: + d = U + elif j == n: + d = D # go through the link while True: diff --git a/src/sage/combinat/knutson_tao_puzzles.py b/src/sage/combinat/knutson_tao_puzzles.py index 9d18df326f1..efa2f6d6800 100644 --- a/src/sage/combinat/knutson_tao_puzzles.py +++ b/src/sage/combinat/knutson_tao_puzzles.py @@ -1315,7 +1315,8 @@ def tikztriangle_fill(color, k, d, i, *args): def tikztriangle_edges(color, k, d, i, label1, label2, label3): s = "" - if i == 1: return s + if i == 1: + return s tikzcmd = r"""\draw[color=%s, fill=none] (%s, %s) -- (%s, %s);""" + "\n" if edge_colors[label1]: s += tikzcmd % (edge_colors[label1], k-1, d-1, k+1, d-1) diff --git a/src/sage/combinat/matrices/dlxcpp.py b/src/sage/combinat/matrices/dlxcpp.py index d85380081e8..7dffdb0792e 100644 --- a/src/sage/combinat/matrices/dlxcpp.py +++ b/src/sage/combinat/matrices/dlxcpp.py @@ -79,8 +79,8 @@ def DLXCPP(rows): sage: [x for x in DLXCPP(rows)] [[3, 0], [3, 1, 2]] """ - - if len(rows) == 0: return + if not rows: + return x = dlx_solver(rows) diff --git a/src/sage/combinat/multiset_partition_into_sets_ordered.py b/src/sage/combinat/multiset_partition_into_sets_ordered.py index 2b15f9cb899..46b317565d3 100755 --- a/src/sage/combinat/multiset_partition_into_sets_ordered.py +++ b/src/sage/combinat/multiset_partition_into_sets_ordered.py @@ -191,7 +191,7 @@ def __init__(self, parent, data): if not _has_nonempty_sets(co): raise ValueError("cannot view %s as an ordered partition of %s"%(co, parent._Xtup)) - ClonableArray.__init__(self, parent, [frozenset(list(k)) for k in co]) + ClonableArray.__init__(self, parent, [frozenset(k) for k in co]) self._multiset = _get_multiset(co) self._weight = _get_weight(self._multiset) self._order = sum(len(block) for block in self) @@ -2873,12 +2873,13 @@ def _iterator_size(size, length=None, alphabet=None): max_part=min(a, max_p)) for a in alpha]): if frozenset(_concatenate(p)).issubset(frozenset(alphabet)): - yield tuple(frozenset(list(k)) for k in p) + yield tuple(frozenset(k) for k in p) else: for alpha in IntegerListsLex(size, length=length, min_part=1, max_part=size): for p in cartesian_product([IntegerListsLex(a, min_slope=1, min_part=1) for a in alpha]): - yield tuple(frozenset(list(k)) for k in p) + yield tuple(frozenset(k) for k in p) + def _iterator_order(A, d, lengths=None): """ diff --git a/src/sage/combinat/parallelogram_polyomino.py b/src/sage/combinat/parallelogram_polyomino.py index 4dc32a7c066..f2f903c828b 100644 --- a/src/sage/combinat/parallelogram_polyomino.py +++ b/src/sage/combinat/parallelogram_polyomino.py @@ -3830,7 +3830,7 @@ class ParallelogramPolyominoesFactory(SetFactory): sage: PPS Parallelogram polyominoes of size 4 - sage: sorted(list(PPS)) + sage: sorted(PPS) [[[0, 0, 0, 1], [1, 0, 0, 0]], [[0, 0, 1, 1], [1, 0, 1, 0]], [[0, 0, 1, 1], [1, 1, 0, 0]], @@ -3860,7 +3860,7 @@ def __call__(self, size=None, policy=None): sage: PPS = ParallelogramPolyominoes(size=4) sage: PPS Parallelogram polyominoes of size 4 - sage: sorted(list(PPS)) + sage: sorted(PPS) [[[0, 0, 0, 1], [1, 0, 0, 0]], [[0, 0, 1, 1], [1, 0, 1, 0]], [[0, 0, 1, 1], [1, 1, 0, 0]], @@ -3935,7 +3935,7 @@ class ParallelogramPolyominoes_size( sage: PPS = ParallelogramPolyominoes(4) sage: PPS Parallelogram polyominoes of size 4 - sage: sorted(list(PPS)) + sage: sorted(PPS) [[[0, 0, 0, 1], [1, 0, 0, 0]], [[0, 0, 1, 1], [1, 0, 1, 0]], [[0, 0, 1, 1], [1, 1, 0, 0]], diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 7d17bf29a4b..184c0a1a7b3 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -15,8 +15,6 @@ # (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** -from __future__ import print_function - from sage.graphs.digraph import DiGraph from sage.matrix.constructor import matrix from sage.rings.integer_ring import ZZ @@ -162,17 +160,16 @@ def greedy_rec(H, linext): S = [] if linext: - S = [x for x in H.neighbors_out(linext[-1]) - if all(low in linext for low in H.neighbors_in(x))] + S = [x for x in H.neighbor_out_iterator(linext[-1]) + if all(low in linext for low in H.neighbor_in_iterator(x))] if not S: S_ = set(self).difference(set(linext)) S = [x for x in S_ - if not any(low in S_ for low in self.neighbors_in(x))] + if not any(low in S_ + for low in self.neighbor_in_iterator(x))] for e in S: - # Python3-todo: use yield from - for tmp in greedy_rec(H, linext + [e]): - yield tmp + yield from greedy_rec(H, linext + [e]) return greedy_rec(self, []) @@ -228,16 +225,14 @@ def supergreedy_rec(H, linext): if not k: # Start from new minimal element S = [x for x in self.sources() if x not in linext] else: - S = [x for x in self.neighbors_out(linext[k - 1]) + S = [x for x in self.neighbor_out_iterator(linext[k - 1]) if x not in linext and all(low in linext - for low in self.neighbors_in(x))] + for low in self.neighbor_in_iterator(x))] k -= 1 for e in S: - # Python3-todo: use yield from - for tmp in supergreedy_rec(H, linext + [e]): - yield tmp + yield from supergreedy_rec(H, linext + [e]) return supergreedy_rec(self, []) @@ -255,15 +250,10 @@ def is_linear_extension(self, lin_ext=None): False """ if lin_ext is None or lin_ext == list(range(len(self))): - for x, y in self.cover_relations_iterator(): - if not x < y: - return False - return True + return all(x < y for x, y in self.cover_relations_iterator()) else: - for x, y in self.cover_relations_iterator(): - if not lin_ext.index(x) < lin_ext.index(y): - return False - return True + return all(lin_ext.index(x) < lin_ext.index(y) + for x, y in self.cover_relations_iterator()) def cover_relations_iterator(self): r""" @@ -276,8 +266,7 @@ def cover_relations_iterator(self): sage: list(H.cover_relations_iterator()) [(0, 2), (0, 3), (1, 3), (1, 4), (2, 5), (3, 5), (4, 5)] """ - for u, v, l in self.edge_iterator(): - yield (u, v) + yield from self.edge_iterator(labels=False) def cover_relations(self): r""" @@ -322,7 +311,7 @@ def is_lequal(self, i, j): def is_less_than(self, x, y): r""" - Return ``True`` if ``x`` is less than or equal to ``y`` in the + Return ``True`` if ``x`` is less than but not equal to ``y`` in the poset, and ``False`` otherwise. EXAMPLES:: @@ -599,13 +588,11 @@ def _precompute_intervals(self): True """ n = self.order() - - v_up = [frozenset(self.depth_first_search(v)) for v in range(n)] + v_up = (frozenset(self.depth_first_search(v)) for v in range(n)) v_down = [frozenset(self.depth_first_search(v, neighbors=self.neighbors_in)) for v in range(n)] self._intervals = [[sorted(up.intersection(down)) for down in v_down] for up in v_up] - self.interval = self._alternate_interval def _alternate_interval(self, x, y): @@ -628,7 +615,6 @@ def _alternate_interval(self, x, y): sage: P._hasse_diagram._precompute_intervals() sage: P.interval(1, 7) # Uses this function [1, 3, 5, 7] - """ return self._intervals[x][y] @@ -678,7 +664,7 @@ def open_interval(self, x, y): [] """ ci = self.interval(x, y) - if len(ci) == 0: + if not ci: return [] else: return ci[1:-1] @@ -785,12 +771,12 @@ def _rank(self): # look at the neighbors of y and set the ranks; # then look at the neighbors of the neighbors ... y = queue.pop() - for x in self.neighbors_out(y): + for x in self.neighbor_out_iterator(y): if rank[x] is None: rank[x] = rank[y] + 1 queue.add(x) component.add(x) - for x in self.neighbors_in(y): + for x in self.neighbor_in_iterator(y): if rank[x] is None: rank[x] = rank[y] - 1 queue.add(x) @@ -1100,7 +1086,7 @@ def order_filter(self, elements): sage: H.order_filter([3,8]) [3, 7, 8, 9, 10, 11, 12, 13, 14, 15] """ - return sorted(list(self.depth_first_search(elements))) + return sorted(self.depth_first_search(elements)) def principal_order_filter(self, i): """ @@ -1127,8 +1113,8 @@ def order_ideal(self, elements): sage: H.order_ideal([7,10]) [0, 1, 2, 3, 4, 5, 6, 7, 8, 10] """ - return sorted(list( - self.depth_first_search(elements, neighbors=self.neighbors_in))) + return sorted(self.depth_first_search(elements, + neighbors=self.neighbors_in)) def principal_order_ideal(self, i): """ @@ -1159,7 +1145,7 @@ def _leq_storage(self): greater_than = [set([i]) for i in range(n)] for i in range(n - 1, -1, -1): gt = greater_than[i] - for j in self.neighbors_out(i): + for j in self.neighbor_out_iterator(i): gt = gt.union(greater_than[j]) greater_than[i] = gt @@ -1968,13 +1954,12 @@ def recursive_fit(orthocomplements, unbinded): new_unbinded = unbinded[1:] # Remove next_to_fit new_unbinded.remove(e) - for i_want_python3_yield_from in recursive_fit(new_binded, new_unbinded): - yield i_want_python3_yield_from + yield from recursive_fit(new_binded, new_unbinded) start = [None] * n # A little optimization for e in range(n): - if len(comps[e]) == 0: # Not any possible orthocomplement + if not comps[e]: # Not any possible orthocomplement return if len(comps[e]) == 1: # Do not re-fit this every time e_ = comps[e][0] @@ -1989,8 +1974,7 @@ def recursive_fit(orthocomplements, unbinded): start[e_] = e start_unbinded = [e for e in range(n) if start[e] is None] - for i_want_python3_yield_from in recursive_fit(start, start_unbinded): - yield i_want_python3_yield_from + yield from recursive_fit(start, start_unbinded) def find_nonsemimodular_pair(self, upper): """ @@ -2311,7 +2295,6 @@ def sublattices_iterator(self, elms, min_e): sage: next(it) {0} """ - # Python3-note: "yield from" would be simpler. yield elms for e in range(min_e, self.cardinality()): if e in elms: @@ -2329,8 +2312,7 @@ def sublattices_iterator(self, elms, min_e): gens.add(self._join[x, g]) current_set.add(g) else: - for x in self.sublattices_iterator(current_set, e + 1): - yield x + yield from self.sublattices_iterator(current_set, e + 1) def maximal_sublattices(self): """ @@ -2498,10 +2480,10 @@ def kappa_dual(self, a): if self.in_degree(uc) == 1: return uc lt_a = set(self.depth_first_search(a, neighbors=self.neighbors_in)) - tmp = list(self.depth_first_search(uc, neighbors=lambda v: [v_ for v_ in self.neighbors_in(v) if v_ not in lt_a])) + tmp = list(self.depth_first_search(uc, neighbors=lambda v: [v_ for v_ in self.neighbor_in_iterator(v) if v_ not in lt_a])) result = None for e in tmp: - if all(x not in tmp for x in self.neighbors_in(e)): + if all(x not in tmp for x in self.neighbor_in_iterator(e)): if result: return None result = e @@ -2738,10 +2720,10 @@ def kappa(self, a): if self.out_degree(lc) == 1: return lc gt_a = set(self.depth_first_search(a)) - tmp = list(self.depth_first_search(lc, neighbors=lambda v: [v_ for v_ in self.neighbors_out(v) if v_ not in gt_a])) + tmp = list(self.depth_first_search(lc, neighbors=lambda v: [v_ for v_ in self.neighbor_out_iterator(v) if v_ not in gt_a])) result = None for e in tmp: - if all(x not in tmp for x in self.neighbors_out(e)): + if all(x not in tmp for x in self.neighbor_out_iterator(e)): if result: return None result = e diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index f5168bcbc66..1f2e3478fe7 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -719,7 +719,7 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio vertices = sorted(set(x for item in data for x in item)) if len(vertices) != len(data): # by default, assuming vertices are the range 0..n - vertices = list(range(len(data))) + vertices = range(len(data)) D = DiGraph({v: [u for u in cov if u != v] for v, cov in zip(vertices, data)}, format="dict_of_lists") @@ -1556,7 +1556,7 @@ def linear_extension(self, linear_extension=None, check=True): @cached_method def linear_extensions(self, facade=False): """ - Return the enumerated set of all the linear extensions of this poset + Return the enumerated set of all the linear extensions of this poset. INPUT: @@ -1776,7 +1776,7 @@ def atkinson(self, a): def is_linear_extension(self, l): """ - Return whether ``l`` is a linear extension of ``self`` + Return whether ``l`` is a linear extension of ``self``. INPUT: @@ -3126,7 +3126,7 @@ def is_EL_labelling(self, f, return_raising_chains=False): if max_chains[0] != sorted(max_chains[0]) or any( max_chains[i] == sorted(max_chains[i]) for i in range(1,len(max_chains)) ): return False elif return_raising_chains: - raising_chains[(a,b)] = max_chains[0] + raising_chains[(a, b)] = max_chains[0] if return_raising_chains: return raising_chains else: @@ -5889,9 +5889,9 @@ def with_linear_extension(self, linear_extension): category=self.category(), facade=self._is_facade) - def graphviz_string(self,graph_string="graph",edge_string="--"): + def graphviz_string(self, graph_string="graph", edge_string="--"): r""" - Returns a representation in the DOT language, ready to render in + Return a representation in the DOT language, ready to render in graphviz. See http://www.graphviz.org/doc/info/lang.html for more information @@ -6188,7 +6188,7 @@ def random_linear_extension(self): new = mins[new_index] result.append(new) mins = mins[:new_index]+mins[new_index+1:] - for u in H.neighbors_out(new): + for u in H.neighbor_out_iterator(new): indegs[u] -= 1 if indegs[u] == 0: mins.append(u) @@ -6223,7 +6223,7 @@ def order_filter(self, elements): sage: C.order_filter([]) [] """ - vertices = sorted(map(self._element_to_vertex,elements)) + vertices = sorted(map(self._element_to_vertex, elements)) of = self._hasse_diagram.order_filter(vertices) return [self._vertex_to_element(_) for _ in of] @@ -6531,8 +6531,6 @@ def maximal_chains(self, partial=None): - ``partial`` -- list (optional); if present, find all maximal chains starting with the elements in partial - Returns list of the maximal chains of this poset. - This is used in constructing the order complex for the poset. EXAMPLES:: @@ -8338,13 +8336,13 @@ def __contains__(self, P): def __iter__(self): """ - Returns an iterator of representatives of the isomorphism classes + Return an iterator of representatives of the isomorphism classes of finite posets of a given size. - .. note:: + .. NOTE:: - This uses the DiGraph iterator as a backend to construct - transitively-reduced, acyclic digraphs. + This uses the DiGraph iterator as a backend to construct + transitively-reduced, acyclic digraphs. EXAMPLES:: @@ -8356,8 +8354,8 @@ def __iter__(self): for dig in DiGraphGenerators()(self._n, is_poset): # We need to relabel the digraph since range(self._n) must be a linear # extension. Too bad we need to compute this again. TODO: Fix this. - label_dict = dict(zip(dig.topological_sort(),range(dig.order()))) - yield FinitePoset(dig.relabel(label_dict,inplace=False)) + label_dict = dict(zip(dig.topological_sort(), range(dig.order()))) + yield FinitePoset(dig.relabel(label_dict, inplace=False)) def cardinality(self, from_iterator=False): r""" diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 4a1ec72bedc..7edb48e10fc 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -14,7 +14,7 @@ from __future__ import print_function, absolute_import from sage.misc.abstract_method import abstract_method, AbstractMethod -from sage.misc.misc import attrcall +from sage.misc.call import attrcall from sage.misc.cachefunc import cached_method, cached_in_parent_method from sage.misc.lazy_attribute import lazy_attribute from sage.misc.lazy_import import LazyImport diff --git a/src/sage/combinat/root_system/type_dual.py b/src/sage/combinat/root_system/type_dual.py index 885724a5eb1..cdcc1601c9c 100644 --- a/src/sage/combinat/root_system/type_dual.py +++ b/src/sage/combinat/root_system/type_dual.py @@ -10,7 +10,7 @@ # **************************************************************************** from __future__ import print_function, absolute_import -from sage.misc.misc import attrcall +from sage.misc.call import attrcall from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute from sage.combinat.root_system import cartan_type diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 82bc94ba73b..73da832155d 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -662,7 +662,7 @@ def corresponding_basis_over(self, R): put on a more robust and systematic footing. """ from sage.combinat.sf.sf import SymmetricFunctions - from sage.misc.misc import attrcall + from sage.misc.call import attrcall try: return attrcall(self._basis)(SymmetricFunctions(R)) except AttributeError: # or except (AttributeError, ValueError): diff --git a/src/sage/combinat/subsets_hereditary.py b/src/sage/combinat/subsets_hereditary.py index 27558ed630d..6c0dfe42c35 100644 --- a/src/sage/combinat/subsets_hereditary.py +++ b/src/sage/combinat/subsets_hereditary.py @@ -64,7 +64,7 @@ def subsets_with_hereditary_property(f,X,max_obstruction_size=None,ncpus=1): Same, on two threads:: - sage: sorted(list(subsets_with_hereditary_property(f,range(4),ncpus=2))) + sage: sorted(subsets_with_hereditary_property(f,range(4),ncpus=2)) [[], [0], [0, 2], [1], [1, 3], [2], [3]] One can use this function to compute the independent sets of a graph. We diff --git a/src/sage/combinat/subword_complex.py b/src/sage/combinat/subword_complex.py index 58929e6022e..0027f5229eb 100644 --- a/src/sage/combinat/subword_complex.py +++ b/src/sage/combinat/subword_complex.py @@ -713,7 +713,7 @@ def flip(self, i, return_position=False): ((2, 3), 3) """ S = self.parent() - F = set(list(self)) + F = set(self) R = list(self._extended_root_configuration_indices()) j = _flip_c(self.parent().group(), F, R, i) # F and R are changed here new_facet = S.element_class(self.parent(), F) diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index 54827a3c913..730885785ba 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -443,7 +443,8 @@ def ncube_isometry_group_cosets(n, orientation_preserving=True): G_todo = set(G) # Make sure that H is a subset of G - for h in H: h.set_immutable() + for h in H: + h.set_immutable() assert all(h in G_todo for h in H), "H must be a subset of G" # Construct the cosets diff --git a/src/sage/combinat/words/shuffle_product.py b/src/sage/combinat/words/shuffle_product.py index 41cad2aad39..2f9bf62ed2c 100644 --- a/src/sage/combinat/words/shuffle_product.py +++ b/src/sage/combinat/words/shuffle_product.py @@ -57,18 +57,18 @@ def __init__(self, w1, w2): sage: from sage.combinat.words.shuffle_product import ShuffleProduct_w1w2 sage: W = Words([1,2,3,4]) sage: s = ShuffleProduct_w1w2(W([1,2]),W([3,4])) - sage: sorted(list(s)) + sage: sorted(s) [word: 1234, word: 1324, word: 1342, word: 3124, word: 3142, word: 3412] sage: s == loads(dumps(s)) True sage: s = ShuffleProduct_w1w2(W([1,4,3]),W([2])) - sage: sorted(list(s)) + sage: sorted(s) [word: 1243, word: 1423, word: 1432, word: 2143] sage: s = ShuffleProduct_w1w2(W([1,4,3]),W([])) - sage: sorted(list(s)) + sage: sorted(s) [word: 143] """ self._w1 = w1 diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py index 473f007525b..8db29fc7673 100644 --- a/src/sage/doctest/sources.py +++ b/src/sage/doctest/sources.py @@ -808,13 +808,14 @@ def _test_enough_doctests(self, check_extras=True, verbose=True): actual = [] tests, _ = self.create_doctests({}) for dt in tests: - if len(dt.examples) > 0: + if dt.examples: for ex in dt.examples[:-1]: # the last entry is a sig_on_count() actual.append(dt.lineno + ex.lineno + 1) - shortfall = sorted(list(set(expected).difference(set(actual)))) - extras = sorted(list(set(actual).difference(set(expected)))) + shortfall = sorted(set(expected).difference(set(actual))) + extras = sorted(set(actual).difference(set(expected))) if len(actual) == len(expected): - if len(shortfall) == 0: return + if not shortfall: + return dif = extras[0] - shortfall[0] for e, s in zip(extras[1:],shortfall[1:]): if dif != e - s: @@ -834,6 +835,7 @@ def _test_enough_doctests(self, check_extras=True, verbose=True): if check_extras and extras: print(" Tests on lines %s seem extraneous" % (", ".join([str(n) for n in extras]))) + class SourceLanguage: """ An abstract class for functions that depend on the programming language of a doctest source. diff --git a/src/sage/ext/solaris_fixes.h b/src/sage/ext/solaris_fixes.h deleted file mode 100644 index 547cbd634b5..00000000000 --- a/src/sage/ext/solaris_fixes.h +++ /dev/null @@ -1,3 +0,0 @@ -#if defined(__sun) -#define _Complex_I 1.0fi -#endif diff --git a/src/sage/ext_data/graphs/graph_plot_js.html b/src/sage/ext_data/graphs/graph_plot_js.html index ad2c7e165ac..75d08f91662 100644 --- a/src/sage/ext_data/graphs/graph_plot_js.html +++ b/src/sage/ext_data/graphs/graph_plot_js.html @@ -23,6 +23,19 @@ marker { fill:#bbb; } + #menu-container { position: absolute; bottom: 30px; right: 40px; cursor: default; } + + #menu-message { position: absolute; bottom: 0px; right: 0px; white-space: nowrap; + display: none; background-color: #F5F5F5; padding: 10px; } + + #menu-content { position: absolute; bottom: 0px; right: 0px; + display: none; background-color: #F5F5F5; border-bottom: 1px solid black; + border-right: 1px solid black; border-left: 1px solid black; } + + #menu-content div { border-top: 1px solid black; padding: 10px; white-space: nowrap; } + + #menu-content div:hover { background-color: #FEFEFE;; } + // D3JS_SCRIPT_HEREEEEEEEEEEE @@ -266,6 +279,39 @@ } } + // menu functions + + function toggleMenu() { + + var m = document.getElementById( 'menu-content' ); + if ( m.style.display === 'block' ) m.style.display = 'none' + else m.style.display = 'block'; + + } + + function saveAsSVG() { + + var doctype = '' + + ''; + + var our_style=''; + + // serialize our SVG XML to a string. + var source = (new XMLSerializer()).serializeToString(d3.select('svg').node()); + + var styled_source = source.replace('"all">', '"all">' + our_style + ""); + // create a file blob of our SVG. + var blob = new Blob([doctype + styled_source], { type: 'image/svg+xml;charset=utf-8' }); + var a = document.body.appendChild( document.createElement( 'a' ) ); + a.href = window.URL.createObjectURL( blob ); + a.download = 'my_graph.svg'; + a.click() + } + @@ -274,5 +320,11 @@ // GRAPH_DATA_HEREEEEEEEEEEE + diff --git a/src/sage/ext_data/threejs/threejs_template.html b/src/sage/ext_data/threejs/threejs_template.html index a17e8db6132..68595d3b9a8 100644 --- a/src/sage/ext_data/threejs/threejs_template.html +++ b/src/sage/ext_data/threejs/threejs_template.html @@ -303,12 +303,13 @@ var side = json.singleSide ? THREE.FrontSide : THREE.DoubleSide; var transparent = json.opacity < 1 ? true : false; + var flatShading = json.useFlatShading ? json.useFlatShading : false; var material = new THREE.MeshPhongMaterial( { side: side, color: useFaceColors ? 'white' : json.color, vertexColors: useFaceColors ? THREE.FaceColors : THREE.NoColors, transparent: transparent, opacity: json.opacity, - shininess: 20, flatShading: json.useFlatShading } ); + shininess: 20, flatShading: flatShading } ); var c = new THREE.Vector3(); geometry.computeBoundingBox(); diff --git a/src/sage/game_theory/cooperative_game.py b/src/sage/game_theory/cooperative_game.py index a97ae90ae70..6d2c630cd40 100644 --- a/src/sage/game_theory/cooperative_game.py +++ b/src/sage/game_theory/cooperative_game.py @@ -669,7 +669,7 @@ def is_efficient(self, payoff_vector): sage: long_game.is_efficient({1: 20, 2: 20, 3: 5, 4: 20}) True """ - pl = tuple(sorted(list(self.player_list))) + pl = tuple(sorted(self.player_list)) return sum(payoff_vector.values()) == self.ch_f[pl] def nullplayer(self, payoff_vector): diff --git a/src/sage/games/all.py b/src/sage/games/all.py index d8066fd6190..e3e31bcf03e 100644 --- a/src/sage/games/all.py +++ b/src/sage/games/all.py @@ -1,20 +1,2 @@ -""" -Test for deprecations of imports into global namespace:: - - sage: backtrack_all - doctest:warning...: - DeprecationWarning: - Importing backtrack_all from here is deprecated. If you need to use it, please import it directly from sage.games.sudoku_backtrack - See https://trac.sagemath.org/27066 for details. - ... -""" -from __future__ import absolute_import - -from sage.misc.lazy_import import lazy_import - -lazy_import("sage.games.sudoku_backtrack", 'backtrack_all', deprecation=27066) - from .sudoku import Sudoku, sudoku from .hexad import Minimog - -del absolute_import diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index 42911093c1b..d28fa0091ec 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -2771,6 +2771,11 @@ def incidence_matrix(self): sage: halfspace.incidence_matrix().is_immutable() True + + Check that the base ring is ``ZZ``, see :trac:`29840`:: + + sage: halfspace.incidence_matrix().base_ring() + Integer Ring """ normals = self.facet_normals() incidence_matrix = matrix(ZZ, self.nrays(), diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py index 37b660fa834..66edc59bc82 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py @@ -27,7 +27,7 @@ from sage.rings.infinity import infinity from sage.functions.other import real, imag, sqrt from sage.misc.lazy_import import lazy_import -lazy_import('sage.misc.misc', 'attrcall') +lazy_import('sage.misc.call', 'attrcall') class HyperbolicModelCoercion(Morphism): """ diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 0793432652b..1b7310e4286 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -2389,6 +2389,11 @@ def incidence_matrix(self): sage: o.incidence_matrix().is_immutable() True + + Check that the base ring is ``ZZ``, see :trac:`29840`:: + + sage: o.incidence_matrix().base_ring() + Integer Ring """ incidence_matrix = matrix(ZZ, self.nvertices(), self.nfacets(), 0) diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index 32a21ca6c5f..29fdab9163e 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -26,7 +26,7 @@ from __future__ import absolute_import, print_function from sage.structure.element import Element -from sage.misc.all import prod +from sage.misc.all import cached_method, prod from sage.features import PythonModule from sage.rings.all import ZZ, QQ @@ -1112,6 +1112,7 @@ def format_number(x): return '{}'.format(QQ(x)) except (ValueError, TypeError): return '({})'.format(x.polynomial('a')) + def format_field(key, value): if isinstance(value, list) or isinstance(value, tuple): s = '{} {}\n'.format(key, len(value)) @@ -1122,6 +1123,7 @@ def format_field(key, value): return s else: return '{} {}\n'.format(key, value) + def format_number_field_data(nf_triple): min_poly, gen, emb = nf_triple return 'min_poly ({}) embedding {}'.format(min_poly, emb) @@ -1496,6 +1498,7 @@ def _triangulate_normaliz(self): return triangulation + ######################################################################### class Polyhedron_QQ_normaliz(Polyhedron_normaliz, Polyhedron_QQ): r""" @@ -1514,6 +1517,7 @@ class Polyhedron_QQ_normaliz(Polyhedron_normaliz, Polyhedron_QQ): sage: TestSuite(p).run() # optional - pynormaliz """ + @cached_method(do_pickle=True) def ehrhart_series(self, variable='t'): r""" Return the Ehrhart series of a compact rational polyhedron. @@ -1567,6 +1571,14 @@ def ehrhart_series(self, variable='t'): .. SEEALSO:: :meth:`~sage.geometry.polyhedron.backend_normaliz.hilbert_series` + + TESTS: + + Check that the Ehrhart series is pickled:: + + sage: new_poly = loads(dumps(rat_poly)) # optional - pynormaliz + sage: new_poly.ehrhart_series.is_in_cache() # optional - pynormaliz + True """ if self.is_empty(): return 0 @@ -1670,6 +1682,7 @@ def _ehrhart_quasipolynomial_normaliz(self, variable='t'): _ehrhart_polynomial_normaliz = _ehrhart_quasipolynomial_normaliz + @cached_method(do_pickle=True, key=lambda self, g, v: (tuple(g), v)) def hilbert_series(self, grading, variable='t'): r""" Return the Hilbert series of the polyhedron with respect to ``grading``. @@ -1731,6 +1744,14 @@ def hilbert_series(self, grading, variable='t'): .. SEEALSO:: :meth:`~sage.geometry.polyhedron.backend_normaliz.ehrhart_series` + + TESTS: + + Check that the Hilbert series is pickled:: + + sage: new_magic = loads(dumps(magic_square)) # optional - pynormaliz + sage: new_magic.hilbert_series.is_in_cache(grading) # optional - pynormaliz + True """ if self.is_empty(): return 0 diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 8e82e941682..d84e23ca706 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -2484,6 +2484,18 @@ def vertex_adjacency_matrix(self): (0, 0, 0, 0, 1) A ray in the direction (1, 1) (0, 0, 1, 1, 0) A vertex at (3, 0) + The vertex adjacency matrix has base ring integers. This way one can express various + counting questions:: + + sage: P = polytopes.cube() + sage: Q = P.stack(P.faces(2)[0]) + sage: M = Q.vertex_adjacency_matrix() + sage: sum(M) + (4, 4, 3, 3, 4, 4, 4, 3, 3) + sage: G = Q.vertex_graph() + sage: G.degree() + [4, 4, 3, 3, 4, 4, 4, 3, 3] + TESTS: Check that :trac:`28828` is fixed:: @@ -2565,6 +2577,15 @@ def facet_adjacency_matrix(self): [1 1 1 0 1] [1 1 1 1 0] + The facet adjacency matrix has base ring integers. This way one can express various + counting questions:: + + sage: P = polytopes.cube() + sage: Q = P.stack(P.faces(2)[0]) + sage: M = Q.facet_adjacency_matrix() + sage: sum(M) + (4, 4, 4, 4, 3, 3, 3, 3, 4) + TESTS: Check that :trac:`28828` is fixed:: @@ -2586,6 +2607,10 @@ def incidence_matrix(self): vertices/rays/lines in the order :meth:`Vrepresentation`. + .. SEEALSO:: + + :meth:`slack_matrix`. + EXAMPLES:: sage: p = polytopes.cuboctahedron() @@ -2667,6 +2692,14 @@ def incidence_matrix(self): [0 1 0] [0 0 1] + The incidence matrix has base ring integers. This way one can express various + counting questions:: + + sage: P = polytopes.twenty_four_cell() + sage: M = P.incidence_matrix() + sage: sum(sum(x) for x in M) == P.flag_f_vector(0,3) + True + TESTS: Check that :trac:`28828` is fixed:: @@ -2701,6 +2734,86 @@ def incidence_matrix(self): incidence_matrix.set_immutable() return incidence_matrix + @cached_method + def slack_matrix(self): + r""" + Return the slack matrix. + + The entries correspond to the evaluation of the Hrepresentation + elements on the Vrepresentation elements. + + .. NOTE:: + + The columns correspond to inequalities/equations in the + order :meth:`Hrepresentation`, the rows correspond to + vertices/rays/lines in the order + :meth:`Vrepresentation`. + + .. SEEALSO:: + + :meth:`incidence_matrix`. + + EXAMPLES:: + + sage: P = polytopes.cube() + sage: P.slack_matrix() + [0 2 2 2 0 0] + [0 0 2 2 0 2] + [0 0 0 2 2 2] + [0 2 0 2 2 0] + [2 2 0 0 2 0] + [2 2 2 0 0 0] + [2 0 2 0 0 2] + [2 0 0 0 2 2] + + sage: P = polytopes.cube(intervals='zero_one') + sage: P.slack_matrix() + [0 1 1 1 0 0] + [0 0 1 1 0 1] + [0 0 0 1 1 1] + [0 1 0 1 1 0] + [1 1 0 0 1 0] + [1 1 1 0 0 0] + [1 0 1 0 0 1] + [1 0 0 0 1 1] + + sage: P = polytopes.dodecahedron().faces(2)[0].as_polyhedron() + sage: P.slack_matrix() + [1/2*sqrt5 - 1/2 0 0 1 1/2*sqrt5 - 1/2 0] + [ 0 0 1/2*sqrt5 - 1/2 1/2*sqrt5 - 1/2 1 0] + [ 0 1/2*sqrt5 - 1/2 1 0 1/2*sqrt5 - 1/2 0] + [ 1 1/2*sqrt5 - 1/2 0 1/2*sqrt5 - 1/2 0 0] + [1/2*sqrt5 - 1/2 1 1/2*sqrt5 - 1/2 0 0 0] + + sage: P = Polyhedron(rays=[[1, 0], [0, 1]]) + sage: P.slack_matrix() + [0 0] + [0 1] + [1 0] + + TESTS:: + + sage: Polyhedron().slack_matrix() + [] + sage: Polyhedron(base_ring=QuadraticField(2)).slack_matrix().base_ring() + Number Field in a with defining polynomial x^2 - 2 with a = 1.41... + """ + if not self.n_Vrepresentation() or not self.n_Hrepresentation(): + slack_matrix = matrix(self.base_ring(), self.n_Vrepresentation(), + self.n_Hrepresentation(), 0) + else: + Vrep_matrix = matrix(self.base_ring(), self.Vrepresentation()) + Hrep_matrix = matrix(self.base_ring(), self.Hrepresentation()) + + # Getting homogenous coordinates of the Vrepresentation. + hom_helper = matrix(self.base_ring(), [1 if v.is_vertex() else 0 for v in self.Vrepresentation()]) + hom_Vrep = hom_helper.stack(Vrep_matrix.transpose()) + + slack_matrix = (Hrep_matrix * hom_Vrep).transpose() + + slack_matrix.set_immutable() + return slack_matrix + def base_ring(self): """ Return the base ring. @@ -4730,7 +4843,7 @@ def dilation(self, scalar): sign = one if scalar > 0 else -one make_new_Hrep = lambda h: tuple(scalar*sign*x if i == 0 else sign*x - for i, x in enumerate(h._vector)) + for i, x in enumerate(h._vector)) new_vertices = (tuple(scalar*x for x in v._vector) for v in self.vertex_generator()) new_rays = (tuple(sign*x for x in r._vector) for r in self.ray_generator()) @@ -5595,7 +5708,7 @@ def lawrence_extension(self, v): raise ValueError("{} must not be a vertex or outside self".format(v)) lambda_V = [u + [0] for u in V if u != v] + [v+[1]] + [v+[2]] - parent = self.parent().change_ring(self.base_ring(), ambient_dim=self.ambient_dim()+1) + parent = self.parent().change_ring(self.base_ring(), ambient_dim=self.ambient_dim() + 1) return parent.element_class(parent, [lambda_V, [], []], None) def lawrence_polytope(self): @@ -5657,7 +5770,7 @@ def lawrence_polytope(self): n = self.n_vertices() I_n = matrix.identity(n) lambda_V = block_matrix([[V, I_n], [V, 2*I_n]]) - parent = self.parent().change_ring(self.base_ring(), ambient_dim=self.ambient_dim()+n) + parent = self.parent().change_ring(self.base_ring(), ambient_dim=self.ambient_dim() + n) return parent.element_class(parent, [lambda_V, [], []], None) def is_lawrence_polytope(self): @@ -8003,6 +8116,7 @@ def _integral_points_PALP(self): return list(lp.points()) return [p for p in lp.points() if self.contains(p)] + @cached_method(do_pickle=True) def h_star_vector(self): r""" Return the `h^*`-vector of the lattice polytope. @@ -8066,6 +8180,12 @@ def h_star_vector(self): Traceback (most recent call last): ... TypeError: The h_star vector is only defined for lattice polytopes + + Check that the `h^*`-vector is pickled:: + + sage: new_cube = loads(dumps(cube)) # optional - pynormaliz + sage: new_cube.h_star_vector.is_in_cache() # optional - pynormaliz + True """ if self.is_empty(): return 0 diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 5917c7a262c..917c617ac76 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -4,7 +4,7 @@ from __future__ import absolute_import from sage.rings.all import QQ -from sage.misc.all import prod +from sage.misc.all import cached_method, prod from .base import Polyhedron_base @@ -200,7 +200,7 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, lp.set_min(x[i], a) for i, b in enumerate(box_max): lp.set_max(x[i], b) - p = lp.polyhedron() # this recomputes the double description, which is wasteful + p = lp.polyhedron() # this recomputes the double description, which is wasteful if p.is_empty(): return 0 if p.dimension() == 0: @@ -217,7 +217,8 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, verbose=verbose, **kwds) - def ehrhart_polynomial(self,engine=None,variable='t',verbose=False, + @cached_method(do_pickle=True) + def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None, irrational_primal=None, irrational_all_primal=None, maxdet=None, no_decomposition=None, compute_vertex_cones=None, smith_form=None, dualization=None, triangulation=None, @@ -338,6 +339,17 @@ def ehrhart_polynomial(self,engine=None,variable='t',verbose=False, Traceback (most recent call last): ... TypeError: the polytope has nonintegral vertices, use ehrhart_quasipolynomial with backend 'normaliz' + + TESTS: + + The cache of the Ehrhart polynomial is being pickled:: + + sage: P = polytopes.cube().change_ring(QQ) # optional - latte_int + sage: P.ehrhart_polynomial() # optional - latte_int + 8*t^3 + 12*t^2 + 6*t + 1 + sage: Q = loads(dumps(P)) # optional - latte_int + sage: Q.ehrhart_polynomial.is_in_cache() # optional - latte_int + True """ # check if ``self`` is compact and has vertices in ZZ if self.is_empty(): @@ -370,6 +382,7 @@ def ehrhart_polynomial(self,engine=None,variable='t',verbose=False, else: raise ValueError("engine must be 'latte' or 'normaliz'") + @cached_method(do_pickle=True) def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, dual=None, irrational_primal=None, irrational_all_primal=None, maxdet=None, no_decomposition=None, compute_vertex_cones=None, @@ -397,10 +410,11 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, - ``engine`` -- string; The backend to use. Allowed values are: * ``None`` (default); When no input is given the Ehrhart polynomial - is computed using LattE Integrale (optional) - * ``'latte'``; use LattE integrale program (optional) - * ``'normaliz'``; use Normaliz program (optional package pynormaliz). - The backend of ``self`` must be set to 'normaliz'. + is computed using Normaliz (optional) + * ``'latte'``; use LattE Integrale program (requires optional package + 'latte_int') + * ``'normaliz'``; use the Normaliz program (requires optional package + 'pynormaliz'). The backend of ``self`` must be set to 'normaliz'. - When the ``engine`` is 'latte', the additional input values are: @@ -514,6 +528,24 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: simplex.ehrhart_polynomial() # optional - pynormaliz latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1 + + TESTS: + + The cache of the Ehrhart quasipolynomial is being pickled:: + + sage: P = polytopes.cuboctahedron(backend='normaliz')/2 # optional - pynormaliz + sage: P.ehrhart_quasipolynomial() # optional - pynormaliz + (5/6*t^3 + 2*t^2 + 5/3*t + 1, 5/6*t^3 + 1/2*t^2 + 1/6*t - 1/2) + sage: Q = loads(dumps(P)) # optional - pynormaliz + sage: Q.ehrhart_quasipolynomial.is_in_cache() # optional - pynormaliz + True + + sage: P = polytopes.cuboctahedron().change_ring(QQ) # optional - latte_int + sage: P.ehrhart_quasipolynomial(engine='latte') # optional - latte_int + 20/3*t^3 + 8*t^2 + 10/3*t + 1 + sage: Q = loads(dumps(P)) # optional - latte_int + sage: Q.ehrhart_quasipolynomial.is_in_cache(engine='latte') # optional - latte_int + True """ if self.is_empty(): from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 3b26cf65c2b..587a3359ceb 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -1033,6 +1033,12 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C.incidence_matrix.clear_cache() sage: C.incidence_matrix() [] + + Check that the base ring is ``ZZ``, see :trac:`29840`:: + + sage: C = CombinatorialPolyhedron([[0,1,2], [0,1,3], [0,2,3], [1,2,3]]) + sage: C.incidence_matrix().base_ring() + Integer Ring """ from sage.rings.all import ZZ from sage.matrix.constructor import matrix @@ -1883,7 +1889,7 @@ cdef class CombinatorialPolyhedron(SageObject): cdef simpliciality = dim - 1 # For each face in the iterator, check if its a simplex. - face_iter.lowest_dimension = 2 # every 1-face is a simplex + face_iter.structure.lowest_dimension = 2 # every 1-face is a simplex d = face_iter.next_dimension() while (d < dim): sig_check() @@ -1997,7 +2003,7 @@ cdef class CombinatorialPolyhedron(SageObject): cdef simplicity = dim - 1 # For each coface in the iterator, check if its a simplex. - coface_iter.lowest_dimension = 2 # every coface of dimension 1 is a simplex + coface_iter.structure.lowest_dimension = 2 # every coface of dimension 1 is a simplex d = coface_iter.next_dimension() while (d < dim): sig_check() @@ -2892,8 +2898,8 @@ cdef class CombinatorialPolyhedron(SageObject): face_iter.set_atom_rep() # Copy the information. - edges[one][2*two] = face_iter.atom_rep[0] - edges[one][2*two + 1] = face_iter.atom_rep[1] + edges[one][2*two] = face_iter.structure.atom_rep[0] + edges[one][2*two + 1] = face_iter.structure.atom_rep[1] counter += 1 # Success, copy the data to ``CombinatorialPolyhedron``. @@ -2944,8 +2950,8 @@ cdef class CombinatorialPolyhedron(SageObject): face_iter.set_atom_rep() # Copy the information. - edges[one][2*two] = face_iter.atom_rep[0] - edges[one][2*two + 1] = face_iter.atom_rep[1] + edges[one][2*two] = face_iter.structure.atom_rep[0] + edges[one][2*two + 1] = face_iter.structure.atom_rep[1] counter += 1 d = face_iter.next_dimension() # Go to next face. @@ -3065,8 +3071,8 @@ cdef class CombinatorialPolyhedron(SageObject): face_iter.set_coatom_rep() # Copy the information. - ridges[one][2*two] = face_iter.coatom_rep[0] - ridges[one][2*two + 1] = face_iter.coatom_rep[1] + ridges[one][2*two] = face_iter.structure.coatom_rep[0] + ridges[one][2*two + 1] = face_iter.structure.coatom_rep[1] counter += 1 # Success, copy the data to ``CombinatorialPolyhedron``. diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx index e28b4f035ba..8e9b673c946 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx @@ -183,19 +183,19 @@ cdef class CombinatorialFace(SageObject): # Copy data from FaceIterator. it = data self._dual = it.dual - self.face_mem = ListOfFaces(1, it.face_length*64) + self.face_mem = ListOfFaces(1, it.structure.face_length*64) self.face = self.face_mem.data[0] - memcpy(self.face, it.face, it.face_length*8) + memcpy(self.face, it.structure.face, it.structure.face_length*8) self._mem = MemoryAllocator() - self._dimension = it.current_dimension - self._ambient_dimension = it.dimension - self.face_length = it.face_length + self._dimension = it.structure.current_dimension + self._ambient_dimension = it.structure.dimension + self.face_length = it.structure.face_length self._ambient_Vrep = it._Vrep self._ambient_facets = it._facet_names self._equalities = it._equalities self.atoms = it.atoms self.coatoms = it.coatoms - self._hash_index = it._index + self._hash_index = it.structure._index elif isinstance(data, PolyhedronFaceLattice): all_faces = data diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index 135000a9523..f35d59ff6c1 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -254,10 +254,9 @@ def incidence_matrix_to_bit_rep_of_facets(matrix): ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_rep_to_Vrep_list_wrapper(list_of_faces, index): + ....: def bit_rep_to_Vrep_list_wrapper(ListOfFaces faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output - ....: cdef ListOfFaces faces = list_of_faces ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] @@ -343,10 +342,9 @@ def incidence_matrix_to_bit_rep_of_Vrep(matrix): ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_rep_to_Vrep_list_wrapper(list_of_faces, index): + ....: def bit_rep_to_Vrep_list_wrapper(ListOfFaces faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output - ....: cdef ListOfFaces faces = list_of_faces ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] @@ -439,10 +437,9 @@ def facets_tuple_to_bit_rep_of_facets(tuple facets_input, size_t n_Vrep): ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_rep_to_Vrep_list_wrapper(list_of_faces, index): + ....: def bit_rep_to_Vrep_list_wrapper(ListOfFaces faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output - ....: cdef ListOfFaces faces = list_of_faces ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] @@ -506,10 +503,9 @@ def facets_tuple_to_bit_rep_of_Vrep(tuple facets_input, size_t n_Vrep): ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_rep_to_Vrep_list_wrapper(list_of_faces, index): + ....: def bit_rep_to_Vrep_list_wrapper(ListOfFaces faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output - ....: cdef ListOfFaces faces = list_of_faces ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd index 0e3a9e5cd58..4b601ec4217 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd @@ -5,27 +5,17 @@ from sage.structure.sage_object cimport SageObject from .list_of_faces cimport ListOfFaces from .combinatorial_face cimport CombinatorialFace -@cython.final -cdef class FaceIterator(SageObject): - cdef readonly bint dual # if 1, then iterate over dual Polyhedron - cdef uint64_t *face # the current face of the iterator - cdef size_t *atom_rep # a place where atom-representation of face will be stored - cdef size_t *coatom_rep # a place where coatom-representation of face will be stored - cdef int current_dimension # dimension of current face, dual dimension if ``dual`` - cdef int dimension # dimension of the polyhedron - cdef int output_dimension # only faces of this (dual?) dimension are considered - cdef int lowest_dimension # don't consider faces below this (dual?) dimension - cdef size_t _index # this counts the number of seen faces, useful for hasing the faces - cdef MemoryAllocator _mem - cdef tuple newfaces_lists # tuple to hold the ListOfFaces corresponding to maybe_newfaces - cdef size_t face_length # stores length of the faces in terms of uint64_t - - # some copies from ``CombinatorialPolyhedron`` - cdef tuple _Vrep, _facet_names, _equalities - - # Atoms and coatoms are the vertices/facets of the Polyedron. - # If ``dual == 0``, then coatoms are facets, atoms vertices and vice versa. - cdef ListOfFaces atoms, coatoms +cdef struct iter_struct: + bint dual # if 1, then iterate over dual Polyhedron + uint64_t *face # the current face of the iterator + size_t *atom_rep # a place where atom-representaion of face will be stored + size_t *coatom_rep # a place where coatom-representaion of face will be stored + int current_dimension # dimension of current face, dual dimension if ``dual`` + int dimension # dimension of the polyhedron + int output_dimension # only faces of this (dual?) dimension are considered + int lowest_dimension # don't consider faces below this (dual?) dimension + size_t _index # this counts the number of seen faces, useful for hasing the faces + size_t face_length # stores length of the faces in terms of uint64_t # ``visited_all`` points to faces, of which we have visited all faces already. # The number of faces in ``visited_all` might depend on the current dimension: @@ -37,18 +27,18 @@ cdef class FaceIterator(SageObject): # In this way, we will append ``visited_all`` in lower dimension, but # will ignore those changes when going up in dimension again. # This is why the number of faces in ``visited_all``depends on dimension. - cdef uint64_t **visited_all - cdef size_t *n_visited_all + uint64_t **visited_all + size_t *n_visited_all # ``maybe_newfaces`` is where all possible facets of a face are stored. # In dimension ``dim`` when visiting all faces of some face, # the intersections with other faces are stored in ``newfaces2[dim]``. - cdef uint64_t ***maybe_newfaces + uint64_t ***maybe_newfaces # ``newfaces`` will point to those faces in ``maybe_newfaces`` # that are of codimension 1 and not already visited. - cdef uint64_t ***newfaces - cdef size_t *n_newfaces # number of newfaces for each dimension + uint64_t ***newfaces + size_t *n_newfaces # number of newfaces for each dimension # After having visited a face completely, we want to add it to ``visited_all``. # ``first_dim[i]`` will indicate, wether there is one more face in @@ -56,11 +46,26 @@ cdef class FaceIterator(SageObject): # that has to be added to ``visited_all``. # If ``first_time[i] == False``, we still need to # add ``newfaces[i][n_newfaces[i]]`` to ``visited_all``. - cdef bint *first_time + bint *first_time # The number of elements in newfaces[current_dimension], # that have not been visited yet. - cdef size_t yet_to_visit + size_t yet_to_visit + + +@cython.final +cdef class FaceIterator(SageObject): + cdef iter_struct structure + cdef readonly bint dual # if 1, then iterate over dual Polyhedron + cdef MemoryAllocator _mem + cdef tuple newfaces_lists # tuple to hold the ListOfFaces corresponding to maybe_newfaces + + # some copies from ``CombinatorialPolyhedron`` + cdef tuple _Vrep, _facet_names, _equalities + + # Atoms and coatoms are the vertices/facets of the Polyedron. + # If ``dual == 0``, then coatoms are facets, atoms vertices and vice versa. + cdef ListOfFaces atoms, coatoms cdef inline CombinatorialFace next_face(self) cdef inline int next_dimension(self) except -1 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx index 22f489dbfbe..21d3a272376 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx @@ -470,28 +470,29 @@ cdef class FaceIterator(SageObject): cdef ListOfFaces some_list # make Cython aware of type self.dual = dual - self.face = NULL - self.dimension = C.dimension() - self.current_dimension = self.dimension -1 + self.structure.dual = dual + self.structure.face = NULL + self.structure.dimension = C.dimension() + self.structure.current_dimension = self.structure.dimension -1 self._mem = MemoryAllocator() # We will not yield the empty face. # If there are `n` lines, than there # are no faces below dimension `n`. # The dimension of the level-sets in the face lattice jumps from `n` to `-1`. - self.lowest_dimension = 0 + self.structure.lowest_dimension = 0 if output_dimension is not None: - if not output_dimension in range(0,self.dimension): + if not output_dimension in range(0,self.structure.dimension): raise ValueError("``output_dimension`` must be the dimension of proper faces") if self.dual: # In dual mode, the dimensions are reversed. - self.output_dimension = self.dimension - 1 - output_dimension + self.structure.output_dimension = self.structure.dimension - 1 - output_dimension else: - self.output_dimension = output_dimension - self.lowest_dimension = max(0, self.output_dimension) + self.structure.output_dimension = output_dimension + self.structure.lowest_dimension = max(0, self.structure.output_dimension) else: - self.output_dimension = -2 + self.structure.output_dimension = -2 if dual: self.atoms = C.bitrep_facets() @@ -499,36 +500,36 @@ cdef class FaceIterator(SageObject): else: self.coatoms = C.bitrep_facets() self.atoms = C.bitrep_Vrep() - self.face_length = self.coatoms.face_length + self.structure.face_length = self.coatoms.face_length self._Vrep = C.Vrep() self._facet_names = C.facet_names() self._equalities = C.equalities() - self.atom_rep = self._mem.allocarray(self.coatoms.n_atoms, sizeof(size_t)) - self.coatom_rep = self._mem.allocarray(self.coatoms.n_faces, sizeof(size_t)) + self.structure.atom_rep = self._mem.allocarray(self.coatoms.n_atoms, sizeof(size_t)) + self.structure.coatom_rep = self._mem.allocarray(self.coatoms.n_faces, sizeof(size_t)) - if self.dimension == 0 or self.coatoms.n_faces == 0: + if self.structure.dimension == 0 or self.coatoms.n_faces == 0: # As we will only yield proper faces, # there is nothing to yield in those cases. # We have to discontinue initialization, # as it assumes ``self.dimension > 0`` and ``self.n_faces > 0``. - self.current_dimension = self.dimension + self.structure.current_dimension = self.structure.dimension return # We may assume ``dimension > 0`` and ``n_faces > 0``. # Initialize ``maybe_newfaces``, # the place where the new faces are being stored. self.newfaces_lists = tuple(ListOfFaces(self.coatoms.n_faces, self.coatoms.n_atoms) - for i in range(self.dimension -1)) - self.maybe_newfaces = self._mem.allocarray((self.dimension -1), sizeof(uint64_t **)) - for i in range(self.dimension -1): + for i in range(self.structure.dimension -1)) + self.structure.maybe_newfaces = self._mem.allocarray((self.structure.dimension -1), sizeof(uint64_t **)) + for i in range(self.structure.dimension -1): some_list = self.newfaces_lists[i] - self.maybe_newfaces[i] = some_list.data + self.structure.maybe_newfaces[i] = some_list.data # Initialize ``visited_all``. - self.visited_all = self._mem.allocarray(self.coatoms.n_faces, sizeof(uint64_t *)) - self.n_visited_all = self._mem.allocarray(self.dimension, sizeof(size_t)) - self.n_visited_all[self.dimension -1] = 0 + self.structure.visited_all = self._mem.allocarray(self.coatoms.n_faces, sizeof(uint64_t *)) + self.structure.n_visited_all = self._mem.allocarray(self.structure.dimension, sizeof(size_t)) + self.structure.n_visited_all[self.structure.dimension -1] = 0 if not C.is_bounded(): # Treating the far face as if we had visited all its elements. # Hence we will visit all intersections of facets unless contained in the far face. @@ -539,26 +540,26 @@ cdef class FaceIterator(SageObject): # Hence it is fine to use the first entry already for the far face, # as ``self.visited_all`` holds ``n_facets`` pointers. some_list = C.far_face() - self.visited_all[0] = some_list.data[0] - self.n_visited_all[self.dimension -1] = 1 + self.structure.visited_all[0] = some_list.data[0] + self.structure.n_visited_all[self.structure.dimension -1] = 1 # Initialize ``newfaces``, which will point to the new faces of codimension 1, # which have not been visited yet. - self.newfaces = self._mem.allocarray(self.dimension, sizeof(uint64_t **)) - for i in range(self.dimension - 1): - self.newfaces[i] = self._mem.allocarray(self.coatoms.n_faces, sizeof(uint64_t *)) - self.newfaces[self.dimension - 1] = self.coatoms.data # we start with coatoms + self.structure.newfaces = self._mem.allocarray(self.structure.dimension, sizeof(uint64_t **)) + for i in range(self.structure.dimension - 1): + self.structure.newfaces[i] = self._mem.allocarray(self.coatoms.n_faces, sizeof(uint64_t *)) + self.structure.newfaces[self.structure.dimension - 1] = self.coatoms.data # we start with coatoms # Initialize ``n_newfaces``. - self.n_newfaces = self._mem.allocarray(self.dimension, sizeof(size_t)) - self.n_newfaces[self.dimension - 1] = self.coatoms.n_faces + self.structure.n_newfaces = self._mem.allocarray(self.structure.dimension, sizeof(size_t)) + self.structure.n_newfaces[self.structure.dimension - 1] = self.coatoms.n_faces # Initialize ``first_time``. - self.first_time = self._mem.allocarray(self.dimension, sizeof(bint)) - self.first_time[self.dimension - 1] = True + self.structure.first_time = self._mem.allocarray(self.structure.dimension, sizeof(bint)) + self.structure.first_time[self.structure.dimension - 1] = True - self.yet_to_visit = self.coatoms.n_faces - self._index = 0 + self.structure.yet_to_visit = self.coatoms.n_faces + self.structure._index = 0 def _repr_(self): r""" @@ -572,16 +573,16 @@ cdef class FaceIterator(SageObject): sage: C.face_iter(1) Iterator over the 1-faces of a 3-dimensional combinatorial polyhedron """ - if self.output_dimension != -2: + if self.structure.output_dimension != -2: if self.dual: # ouput_dimension is stored with respect to the dual - intended_dimension = self.dimension - 1 - self.output_dimension + intended_dimension = self.structure.dimension - 1 - self.structure.output_dimension else: - intended_dimension = self.output_dimension + intended_dimension = self.structure.output_dimension output = "Iterator over the {}-faces".format(intended_dimension) else: output = "Iterator over the proper faces" - return output + " of a {}-dimensional combinatorial polyhedron".format(self.dimension) + return output + " of a {}-dimensional combinatorial polyhedron".format(self.structure.dimension) def __next__(self): r""" @@ -601,7 +602,7 @@ cdef class FaceIterator(SageObject): A 1-dimensional face of a 3-dimensional combinatorial polyhedron] """ cdef CombinatorialFace face = self.next_face() - if unlikely(self.current_dimension == self.dimension): + if unlikely(self.structure.current_dimension == self.structure.dimension): raise StopIteration return face @@ -672,15 +673,15 @@ cdef class FaceIterator(SageObject): """ if unlikely(self.dual): raise ValueError("only possible when not in dual mode") - if unlikely(self.face is NULL): + if unlikely(self.structure.face is NULL): raise ValueError("iterator not set to a face yet") # The current face is added to ``visited_all``. # This will make the iterator skip those faces. # Also, this face will not be added a second time to ``visited_all``, # as there are no new faces. - self.visited_all[self.n_visited_all[self.current_dimension]] = self.face - self.n_visited_all[self.current_dimension] += 1 + self.structure.visited_all[self.structure.n_visited_all[self.structure.current_dimension]] = self.structure.face + self.structure.n_visited_all[self.structure.current_dimension] += 1 def ignore_supfaces(self): r""" @@ -705,15 +706,15 @@ cdef class FaceIterator(SageObject): """ if unlikely(not self.dual): raise ValueError("only possible when in dual mode") - if unlikely(self.face is NULL): + if unlikely(self.structure.face is NULL): raise ValueError("iterator not set to a face yet") # The current face is added to ``visited_all``. # This will make the iterator skip those faces. # Also, this face will not be added a second time to ``visited_all``, # as there are no new faces. - self.visited_all[self.n_visited_all[self.current_dimension]] = self.face - self.n_visited_all[self.current_dimension] += 1 + self.structure.visited_all[self.structure.n_visited_all[self.structure.current_dimension]] = self.structure.face + self.structure.n_visited_all[self.structure.current_dimension] += 1 cdef inline CombinatorialFace next_face(self): r""" @@ -721,7 +722,7 @@ cdef class FaceIterator(SageObject): :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace`. """ self.next_dimension() - if unlikely(self.current_dimension == self.dimension): + if unlikely(self.structure.current_dimension == self.structure.dimension): return None return CombinatorialFace(self) @@ -744,11 +745,11 @@ cdef class FaceIterator(SageObject): visiting sub-/supfaces instead of after. One cannot arbitrarily add faces to ``visited_all``, as visited_all has a maximal length. """ - cdef int dim = self.dimension - while (not self.next_face_loop()) and (self.current_dimension < dim): + cdef int dim = self.structure.dimension + while (not self.next_face_loop()) and (self.structure.current_dimension < dim): sig_check() - self._index += 1 - return self.current_dimension + self.structure._index += 1 + return self.structure.current_dimension cdef inline int next_face_loop(self) except -1: r""" @@ -758,53 +759,53 @@ cdef class FaceIterator(SageObject): If ``self.current_dimension == self.dimension``, then the iterator is consumed. """ - if unlikely(self.current_dimension == self.dimension): + if unlikely(self.structure.current_dimension == self.structure.dimension): # The function is not supposed to be called, # just prevent it from crashing. raise StopIteration # Getting ``[faces, n_faces, n_visited_all]`` according to dimension. - cdef uint64_t **faces = self.newfaces[self.current_dimension] - cdef size_t n_faces = self.n_newfaces[self.current_dimension] - cdef size_t n_visited_all = self.n_visited_all[self.current_dimension] + cdef uint64_t **faces = self.structure.newfaces[self.structure.current_dimension] + cdef size_t n_faces = self.structure.n_newfaces[self.structure.current_dimension] + cdef size_t n_visited_all = self.structure.n_visited_all[self.structure.current_dimension] - if (self.output_dimension > -2) and (self.output_dimension != self.current_dimension): + if (self.structure.output_dimension > -2) and (self.structure.output_dimension != self.structure.current_dimension): # If only a specific dimension was requested (i.e. ``self.output_dimension > -2``), # then we will not yield faces in other dimension. - self.yet_to_visit = 0 + self.structure.yet_to_visit = 0 - if self.yet_to_visit: + if self.structure.yet_to_visit: # Set ``face`` to the next face. - self.yet_to_visit -= 1 - self.face = faces[self.yet_to_visit] + self.structure.yet_to_visit -= 1 + self.structure.face = faces[self.structure.yet_to_visit] return 1 - if self.current_dimension <= self.lowest_dimension: + if self.structure.current_dimension <= self.structure.lowest_dimension: # We will not yield the empty face. # We will not yield below requested dimension. - self.current_dimension += 1 + self.structure.current_dimension += 1 return 0 if n_faces <= 1: # There will be no more faces from intersections. - self.current_dimension += 1 + self.structure.current_dimension += 1 return 0 # We will visit the last face now. - self.n_newfaces[self.current_dimension] -= 1 + self.structure.n_newfaces[self.structure.current_dimension] -= 1 n_faces -= 1 - if not self.first_time[self.current_dimension]: + if not self.structure.first_time[self.structure.current_dimension]: # In this case there exists ``faces[n_faces + 1]``, of which we # have visited all faces, but which was not added to # ``visited_all`` yet. - self.visited_all[n_visited_all] = faces[n_faces + 1] - self.n_visited_all[self.current_dimension] += 1 - n_visited_all = self.n_visited_all[self.current_dimension] + self.structure.visited_all[n_visited_all] = faces[n_faces + 1] + self.structure.n_visited_all[self.structure.current_dimension] += 1 + n_visited_all = self.structure.n_visited_all[self.structure.current_dimension] else: # Once we have visited all faces of ``faces[n_faces]``, we want # to add it to ``visited_all``. - self.first_time[self.current_dimension] = False + self.structure.first_time[self.structure.current_dimension] = False # Get the faces of codimension 1 contained in ``faces[n_faces]``, # which we have not yet visited. @@ -812,9 +813,9 @@ cdef class FaceIterator(SageObject): sig_on() newfacescounter = get_next_level( - faces, n_faces + 1, self.maybe_newfaces[self.current_dimension-1], - self.newfaces[self.current_dimension-1], - self.visited_all, n_visited_all, self.face_length) + faces, n_faces + 1, self.structure.maybe_newfaces[self.structure.current_dimension-1], + self.structure.newfaces[self.structure.current_dimension-1], + self.structure.visited_all, n_visited_all, self.structure.face_length) sig_off() if newfacescounter: @@ -822,11 +823,11 @@ cdef class FaceIterator(SageObject): # We will visted them on next call, starting with codimension 1. # Setting the variables correclty for next call of ``next_face_loop``. - self.current_dimension -= 1 - self.first_time[self.current_dimension] = True - self.n_newfaces[self.current_dimension] = newfacescounter - self.n_visited_all[self.current_dimension] = n_visited_all - self.yet_to_visit = newfacescounter + self.structure.current_dimension -= 1 + self.structure.first_time[self.structure.current_dimension] = True + self.structure.n_newfaces[self.structure.current_dimension] = newfacescounter + self.structure.n_visited_all[self.structure.current_dimension] = n_visited_all + self.structure.yet_to_visit = newfacescounter return 0 else: # ``faces[n_faces]`` contains no new faces. @@ -836,7 +837,7 @@ cdef class FaceIterator(SageObject): # this step needs to be done, as ``faces[n_faces]`` might # have been added manually to ``visited_all``. # So this step is required to respect boundaries of ``visited_all``. - self.first_time[self.current_dimension] = True + self.structure.first_time[self.structure.current_dimension] = True return 0 cdef size_t n_atom_rep(self) except -1: @@ -846,8 +847,8 @@ cdef class FaceIterator(SageObject): This is a shortcut of :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace.n_atom_rep` """ - if self.face: - return count_atoms(self.face, self.face_length) + if self.structure.face: + return count_atoms(self.structure.face, self.structure.face_length) # The face was not initialized properly. raise LookupError("``FaceIterator`` does not point to a face") @@ -861,9 +862,9 @@ cdef class FaceIterator(SageObject): """ cdef size_t n_coatoms = self.coatoms.n_faces cdef uint64_t **coatoms = self.coatoms.data - cdef size_t face_length = self.face_length - return bit_rep_to_coatom_rep(self.face, coatoms, n_coatoms, - face_length, self.coatom_rep) + cdef size_t face_length = self.structure.face_length + return bit_rep_to_coatom_rep(self.structure.face, coatoms, n_coatoms, + face_length, self.structure.coatom_rep) cdef size_t set_atom_rep(self) except -1: r""" @@ -872,5 +873,5 @@ cdef class FaceIterator(SageObject): This is a shortcut of :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace.set_atom_rep` """ - cdef size_t face_length = self.face_length - return bit_rep_to_Vrep_list(self.face, self.atom_rep, face_length) + cdef size_t face_length = self.structure.face_length + return bit_rep_to_Vrep_list(self.structure.face, self.structure.atom_rep, face_length) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx index f3bc096549f..c374962d1e9 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx @@ -150,7 +150,7 @@ cdef class PolyhedronFaceLattice: if not C.is_bounded(): self.dual = False cdef FaceIterator face_iter = C._face_iter(self.dual, -2) - self.face_length = face_iter.face_length + self.face_length = face_iter.structure.face_length self._Vrep = C.Vrep() self._facet_names = C.facet_names() self._equalities = C.equalities() @@ -220,14 +220,14 @@ cdef class PolyhedronFaceLattice: # Adding all faces, using the iterator. cdef int d - if face_iter.current_dimension != self.dimension: + if face_iter.structure.current_dimension != self.dimension: # If there are proper faces. d = face_iter.next_dimension() while (d == self.dimension - 1): # We already have the coatoms. d = face_iter.next_dimension() while (d < self.dimension): - self._add_face(d, face_iter.face) + self._add_face(d, face_iter.structure.face) d = face_iter.next_dimension() # Sorting the faces, except for coatoms. @@ -353,14 +353,12 @@ cdef class PolyhedronFaceLattice: ....: from sage.geometry.polyhedron.combinatorial_polyhedron.base \ ....: cimport CombinatorialPolyhedron, FaceIterator, PolyhedronFaceLattice ....: - ....: def find_face_from_iterator(it, C1): - ....: cdef FaceIterator face_iter = it - ....: cdef CombinatorialPolyhedron C = C1 + ....: def find_face_from_iterator(FaceIterator it, CombinatorialPolyhedron C): ....: C._record_all_faces() ....: cdef PolyhedronFaceLattice all_faces = C._all_faces ....: if not (all_faces.dual == it.dual): ....: raise ValueError("iterator and allfaces not in same mode") - ....: return all_faces.find_face(face_iter.current_dimension, face_iter.face) + ....: return all_faces.find_face(it.structure.current_dimension, it.structure.face) ....: ''') sage: P = polytopes.permutahedron(4) sage: C = CombinatorialPolyhedron(P) @@ -439,15 +437,13 @@ cdef class PolyhedronFaceLattice: ....: from sage.geometry.polyhedron.combinatorial_polyhedron.base \ ....: cimport CombinatorialPolyhedron, FaceIterator, PolyhedronFaceLattice ....: - ....: def face_via_all_faces_from_iterator(it, C1): - ....: cdef FaceIterator face_iter = it - ....: cdef CombinatorialPolyhedron C = C1 - ....: cdef int dimension = face_iter.current_dimension + ....: def face_via_all_faces_from_iterator(FaceIterator it, CombinatorialPolyhedron C): + ....: cdef int dimension = it.structure.current_dimension ....: C._record_all_faces() ....: cdef PolyhedronFaceLattice all_faces = C._all_faces ....: if not (all_faces.dual == it.dual): ....: raise ValueError("iterator and allfaces not in same mode") - ....: index = all_faces.find_face(dimension, face_iter.face) + ....: index = all_faces.find_face(dimension, it.structure.face) ....: return all_faces.get_face(dimension, index) ....: ''') sage: P = polytopes.permutahedron(4) diff --git a/src/sage/geometry/polyhedron/modules/__init__.py b/src/sage/geometry/polyhedron/modules/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/sage/geometry/polyhedron/modules/formal_polyhedra_module.py b/src/sage/geometry/polyhedron/modules/formal_polyhedra_module.py new file mode 100644 index 00000000000..fe60332e7b8 --- /dev/null +++ b/src/sage/geometry/polyhedron/modules/formal_polyhedra_module.py @@ -0,0 +1,149 @@ +r""" +Formal modules generated by polyhedra +""" + +from sage.combinat.free_module import CombinatorialFreeModule +from sage.modules.with_basis.subquotient import SubmoduleWithBasis, QuotientModuleWithBasis +from sage.categories.graded_modules_with_basis import GradedModulesWithBasis + +class FormalPolyhedraModule(CombinatorialFreeModule): + r""" + Class for formal modules generated by polyhedra. + + It is formal because it is free -- it does not know + about linear relations of polyhedra. + + A formal polyhedral module is graded by dimension. + + INPUT: + + - ``base_ring`` -- base ring of the module; unrelated to the + base ring of the polyhedra + + - ``dimension`` -- the ambient dimension of the polyhedra + + - ``basis`` -- the basis + + EXAMPLES:: + + sage: from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule + sage: def closed_interval(a,b): return Polyhedron(vertices=[[a], [b]]) + + A three-dimensional vector space of polyhedra:: + + sage: I01 = closed_interval(0, 1); I01.rename("conv([0], [1])") + sage: I11 = closed_interval(1, 1); I11.rename("{[1]}") + sage: I12 = closed_interval(1, 2); I12.rename("conv([1], [2])") + sage: basis = [I01, I11, I12] + sage: M = FormalPolyhedraModule(QQ, 1, basis=basis); M + Free module generated by {conv([0], [1]), {[1]}, conv([1], [2])} over Rational Field + sage: M.get_order() + [conv([0], [1]), {[1]}, conv([1], [2])] + + A one-dimensional subspace; bases of subspaces just use the indexing + set `0, \dots, d-1`, where `d` is the dimension:: + + sage: M_lower = M.submodule([M(I11)]); M_lower + Free module generated by {0} over Rational Field + sage: M_lower.print_options(prefix='S') + sage: M_lower.is_submodule(M) + True + sage: x = M(I01) - 2*M(I11) + M(I12) + sage: M_lower.reduce(x) + [conv([0], [1])] + [conv([1], [2])] + sage: M_lower.retract.domain() is M + True + sage: y = M_lower.retract(M(I11)); y + S[0] + sage: M_lower.lift(y) + [{[1]}] + + Quotient space; bases of quotient space are families indexed by + elements of the ambient space:: + + sage: M_mod_lower = M.quotient_module(M_lower); M_mod_lower + Free module generated by {conv([0], [1]), conv([1], [2])} over Rational Field + sage: M_mod_lower.print_options(prefix='Q') + sage: M_mod_lower.retract(x) + Q[conv([0], [1])] + Q[conv([1], [2])] + sage: M_mod_lower.retract(M(I01) - 2*M(I11) + M(I12)) == M_mod_lower.retract(M(I01) + M(I12)) + True + + """ + + @staticmethod + def __classcall__(cls, base_ring, dimension, basis, category=None): + r""" + Normalize the arguments for caching. + + TESTS:: + + sage: from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule + sage: FormalPolyhedraModule(QQ, 1, ()) is FormalPolyhedraModule(QQ, 1, []) + True + """ + if isinstance(basis, list): + basis = tuple(basis) + if category is None: + category = GradedModulesWithBasis(base_ring) + return super(FormalPolyhedraModule, cls).__classcall__(cls, + base_ring=base_ring, + dimension=dimension, + basis=basis, + category=category) + + def __init__(self, base_ring, dimension, basis, category): + """ + Construct a free module generated by the polyhedra in ``basis``. + + TESTS:: + + sage: from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule + sage: def closed_interval(a,b): return Polyhedron(vertices=[[a], [b]]) + sage: I01 = closed_interval(0, 1); I01.rename("conv([0], [1])") + sage: I11 = closed_interval(1, 1); I11.rename("{[1]}") + sage: I12 = closed_interval(1, 2); I12.rename("conv([1], [2])") + sage: I02 = closed_interval(0, 2); I02.rename("conv([0], [2])") + sage: M = FormalPolyhedraModule(QQ, 1, basis=[I01, I11, I12, I02]) + sage: TestSuite(M).run() + """ + super(FormalPolyhedraModule, self).__init__(base_ring, basis, prefix="", category=category) + + def degree_on_basis(self, m): + r""" + The degree of an element of the basis is defined as the dimension of the polyhedron. + + INPUT: + + - ``m`` -- an element of the basis (a polyhedron) + + EXAMPLES:: + + sage: from sage.geometry.polyhedron.modules.formal_polyhedra_module import FormalPolyhedraModule + sage: def closed_interval(a,b): return Polyhedron(vertices=[[a], [b]]) + sage: I01 = closed_interval(0, 1); I01.rename("conv([0], [1])") + sage: I11 = closed_interval(1, 1); I11.rename("{[1]}") + sage: I12 = closed_interval(1, 2); I12.rename("conv([1], [2])") + sage: I02 = closed_interval(0, 2); I02.rename("conv([0], [2])") + sage: M = FormalPolyhedraModule(QQ, 1, basis=[I01, I11, I12, I02]) + + We can extract homogeneous components:: + + sage: O = M(I01) + M(I11) + M(I12) + sage: O.homogeneous_component(0) + [{[1]}] + sage: O.homogeneous_component(1) + [conv([0], [1])] + [conv([1], [2])] + + We note that modulo the linear relations of polyhedra, this would only be a filtration, + not a grading, as the following example shows:: + + sage: X = M(I01) + M(I12) - M(I02) + sage: X.degree() + 1 + + sage: Y = M(I11) + sage: Y.degree() + 0 + """ + return m.dimension() diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 63c98450b9d..8b2eb3a08f6 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -173,17 +173,50 @@ def __init__(self, base_ring, ambient_dim, backend): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: P = Polyhedra(QQ, 3) sage: TestSuite(P).run(skip='_test_pickling') + sage: P = Polyhedra(QQ, 0) + sage: TestSuite(P).run(skip='_test_pickling') """ self._backend = backend self._ambient_dim = ambient_dim from sage.categories.polyhedra import PolyhedralSets - Parent.__init__(self, base=base_ring, category=PolyhedralSets(base_ring)) + from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets + category = PolyhedralSets(base_ring) + if ambient_dim == 0: + category = category & FiniteEnumeratedSets() + else: + category = category.Infinite() + + Parent.__init__(self, base=base_ring, category=category) self._Inequality_pool = [] self._Equation_pool = [] self._Vertex_pool = [] self._Ray_pool = [] self._Line_pool = [] + def list(self): + """ + Return the two polyhedra in ambient dimension 0, raise an error otherwise + + EXAMPLES:: + + sage: from sage.geometry.polyhedron.parent import Polyhedra + sage: P = Polyhedra(QQ, 3) + sage: P.cardinality() + +Infinity + + sage: P = Polyhedra(AA, 0) + sage: P.category() + Category of finite enumerated polyhedral sets over Algebraic Real Field + sage: P.list() + [The empty polyhedron in AA^0, + A 0-dimensional polyhedron in AA^0 defined as the convex hull of 1 vertex] + sage: P.cardinality() + 2 + """ + if self.ambient_dim(): + raise NotImplementedError + return [self.empty(), self.universe()] + def recycle(self, polyhedron): """ Recycle the H/V-representation objects of a polyhedron. diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 759481057fa..e74859c7866 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -501,7 +501,7 @@ def CompleteBipartiteGraph(n1, n2, set_position=True): ... ValueError: the arguments n1(=1) and n2(=-1) must be positive integers """ - if n1<0 or n2<0: + if n1 < 0 or n2 < 0: raise ValueError('the arguments n1(={}) and n2(={}) must be positive integers'.format(n1,n2)) G = Graph(n1+n2, name="Complete bipartite graph of order {}+{}".format(n1, n2)) @@ -899,20 +899,20 @@ def GridGraph(dim_list): g = Graph() n_dim = len(dim) - if n_dim==1: + if n_dim == 1: # Vertices are labeled from 0 to dim[0]-1 g = PathGraph(dim[0]) - elif n_dim==2: + elif n_dim == 2: # We use the Grid2dGraph generator to also get the positions g = Grid2dGraph(*dim) - elif n_dim>2: + elif n_dim > 2: # Vertices are tuples of dimension n_dim, and the graph contains at # least vertex (0, 0, ..., 0) g.add_vertex(tuple([0]*n_dim)) import itertools for u in itertools.product(*[range(d) for d in dim]): for i in range(n_dim): - if u[i]+1= g.order() - 1: if certificate: diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index a14cc595405..9f63bae48f2 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -309,7 +309,8 @@ def __init__(self, query_string, database=None, param_tuple=None): 21 D@O 5 2 22 D?[ 5 3 """ - if database is None: database = GraphDatabase() + if database is None: + database = GraphDatabase() if not isinstance(database, GraphDatabase): raise TypeError('%s is not a valid GraphDatabase'%database) SQLQuery.__init__(self, database, query_string, param_tuple) @@ -411,7 +412,8 @@ class located in :mod:`sage.databases.sql_db` to make the query F_?Hg 7 [1, 1, 1, 1, 1, 2, 3] F_?XO 7 [1, 1, 1, 1, 2, 2, 2] """ - if graph_db is None: graph_db = GraphDatabase() + if graph_db is None: + graph_db = GraphDatabase() if query_dict is not None: if query_dict['expression'][0] == 'degree_sequence': query_dict['expression'][3] = degseq_to_data(query_dict['expression'][3]) @@ -438,11 +440,16 @@ class located in :mod:`sage.databases.sql_db` to make the query # them including repeats) # set table name - if key in graph_data: qdict['table_name'] = 'graph_data' - elif key in aut_grp: qdict['table_name'] = 'aut_grp' - elif key in degrees: qdict['table_name'] = 'degrees' - elif key in misc: qdict['table_name'] = 'misc' - elif key in spectrum: qdict['table_name'] = 'spectrum' + if key in graph_data: + qdict['table_name'] = 'graph_data' + elif key in aut_grp: + qdict['table_name'] = 'aut_grp' + elif key in degrees: + qdict['table_name'] = 'degrees' + elif key in misc: + qdict['table_name'] = 'misc' + elif key in spectrum: + qdict['table_name'] = 'spectrum' # set expression if not isinstance(kwds[key], list): @@ -481,11 +488,16 @@ class located in :mod:`sage.databases.sql_db` to make the query # organize display if display_cols is not None: for col in display_cols: - if col in graph_data: graph_data_disp.append(col) - elif col in aut_grp: aut_grp_disp.append(col) - elif col in degrees: degrees_disp.append(col) - elif col in misc: misc_disp.append(col) - elif col in spectrum: spectrum_disp.append(col) + if col in graph_data: + graph_data_disp.append(col) + elif col in aut_grp: + aut_grp_disp.append(col) + elif col in degrees: + degrees_disp.append(col) + elif col in misc: + misc_disp.append(col) + elif col in spectrum: + spectrum_disp.append(col) # finish filling master join with display tables for tab in disp_tables: @@ -501,10 +513,14 @@ class located in :mod:`sage.databases.sql_db` to make the query disp_list = ['SELECT graph_data.graph6, '] for col in graph_data_disp[1:]: if col != 'graph6': disp_list.append('graph_data.%s, '%col) - for col in aut_grp_disp[1:]: disp_list.append('aut_grp.%s, '%col) - for col in degrees_disp[1:]: disp_list.append('degrees.%s, '%col) - for col in misc_disp[1:]: disp_list.append('misc.%s, '%col) - for col in spectrum_disp[1:]: disp_list.append('spectrum.%s, '%col) + for col in aut_grp_disp[1:]: + disp_list.append('aut_grp.%s, '%col) + for col in degrees_disp[1:]: + disp_list.append('degrees.%s, '%col) + for col in misc_disp[1:]: + disp_list.append('misc.%s, '%col) + for col in spectrum_disp[1:]: + disp_list.append('spectrum.%s, '%col) disp_list[-1] = disp_list[-1].rstrip(', ') + ' ' disp_str = ''.join(disp_list) diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index f8f126c9d1e..06c708486cf 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -328,17 +328,18 @@ def from_incidence_matrix(G, M, loops=False, multiedges=False, weighted=False): if loops is None: loops = True positions.append((NZ[0], NZ[0])) - elif len(NZ) != 2 or \ - (oriented and not ((M[NZ[0], i] == +1 and M[NZ[1], i] == -1) or \ - (M[NZ[0], i] == -1 and M[NZ[1], i] == +1))) or \ - (not oriented and (M[NZ[0], i] != 1 or M[NZ[1], i] != 1)): + elif (len(NZ) != 2 or + (oriented and not ((M[NZ[0], i] == +1 and M[NZ[1], i] == -1) or + (M[NZ[0], i] == -1 and M[NZ[1], i] == +1))) or + (not oriented and (M[NZ[0], i] != 1 or M[NZ[1], i] != 1))): msg = "there must be one or two nonzero entries per column in an incidence matrix, " msg += "got entries {} in column {}".format([M[j, i] for j in NZ], i) raise ValueError(msg) else: positions.append(tuple(NZ)) - if weighted is None: G._weighted = False + if weighted is None: + G._weighted = False if multiedges is None: total = len(positions) multiedges = len(set(positions)) < total @@ -419,7 +420,8 @@ def from_oriented_incidence_matrix(G, M, loops=False, multiedges=False, weighted positions.append(tuple(NZ)) else: positions.append((NZ[1], NZ[0])) - if weighted is None: weighted = False + if weighted is None: + weighted = False if multiedges is None: total = len(positions) multiedges = len(set(positions)) < total diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index da39caab2ce..a9b75e82d62 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -1313,6 +1313,37 @@ def latex(self): \Edge[lw=0.1cm,style={color=cv0v1,},](v0)(v1) % \end{tikzpicture} + + We check that :trac:`22070` is fixed:: + + sage: edges = [(i,(i+1)%3,a) for i,a in enumerate('abc')] + sage: G_with_labels = DiGraph(edges) + sage: C = [[0,1], [2]] + sage: kwds = dict(subgraph_clusters=C,color_by_label=True,prog='dot',format='dot2tex') + sage: opts = G_with_labels.latex_options() + sage: opts.set_options(edge_labels=True, **kwds) # optional - dot2tex graphviz + sage: latex(G_with_labels) # optional - dot2tex graphviz + \begin{tikzpicture}[>=latex,line join=bevel,] + %% + \begin{scope} + \pgfsetstrokecolor{black} + \definecolor{strokecol}{rgb}{...}; + \pgfsetstrokecolor{strokecol} + \definecolor{fillcol}{rgb}{...}; + \pgfsetfillcolor{fillcol} + \filldraw ... cycle; + \end{scope} + \begin{scope} + \pgfsetstrokecolor{black} + \definecolor{strokecol}{rgb}{...}; + \pgfsetstrokecolor{strokecol} + \definecolor{fillcol}{rgb}{...}; + \pgfsetfillcolor{fillcol} + \filldraw ... cycle; + \end{scope} + ... + \end{tikzpicture} + """ format = self.get_option('format') if format == "tkz_graph": diff --git a/src/sage/graphs/graph_plot.py b/src/sage/graphs/graph_plot.py index 4f65bedaef1..453e3325b3c 100644 --- a/src/sage/graphs/graph_plot.py +++ b/src/sage/graphs/graph_plot.py @@ -590,7 +590,8 @@ def set_edges(self, **edge_options): """ for arg in edge_options: self._options[arg] = edge_options[arg] - if 'edge_colors' in edge_options: self._options['color_by_label'] = False + if 'edge_colors' in edge_options: + self._options['color_by_label'] = False if self._options['edge_labels_background'] == "transparent": self._options['edge_labels_background'] = "None" @@ -661,10 +662,10 @@ def append_or_set(key, label, color, head): # Add unspecified edges (default color black set in DEFAULT_PLOT_OPTIONS) for edge in self._graph.edge_iterator(): - if (edge[0], edge[1], edge[2]) not in edges_drawn and \ - ( self._graph.is_directed() or - (edge[1], edge[0], edge[2]) not in edges_drawn - ): + if ((edge[0], edge[1], edge[2]) not in edges_drawn and + (self._graph.is_directed() or + (edge[1], edge[0], edge[2]) not in edges_drawn + )): if v_to_int[edge[0]] < v_to_int[edge[1]]: key = (edge[0], edge[1]) head = 1 diff --git a/src/sage/graphs/graph_plot_js.py b/src/sage/graphs/graph_plot_js.py index b145920c33b..f845d7ef115 100644 --- a/src/sage/graphs/graph_plot_js.py +++ b/src/sage/graphs/graph_plot_js.py @@ -2,12 +2,15 @@ Graph plotting in Javascript with d3.js This module implements everything that can be used to draw graphs with `d3.js -`_ in Sage. +`_ in Sage. On Python's side, this is mainly done by wrapping a graph's edges and vertices in a structure that can then be used in the javascript code. This javascript code is then inserted into a .html file to be opened by a browser. +In the browser, the displayed page contains at the bottom right a menu +that allows to save the picture under the svg file format. + What Sage feeds javascript with is a "graph" object with the following content: - ``vertices`` -- each vertex is a dictionary defining : @@ -62,7 +65,7 @@ - Nathann Cohen, Brice Onfroy -- July 2013 -- Initial version of the Sage code, - Javascript code, using examples from `d3.js `_. + Javascript code, using examples from `d3.js `_. - Thierry Monteil (June 2014): allow offline use of d3.js provided by d3js spkg. @@ -98,7 +101,7 @@ def gen_html_code(G, vertex_size=7, edge_thickness=4): r""" - Creates a .html file showing the graph using `d3.js `_. + Create a .html file showing the graph using `d3.js `_. This function returns the name of the .html file. If you want to visualize the actual graph use :meth:`~sage.graphs.generic_graph.GenericGraph.show`. @@ -325,8 +328,7 @@ def gen_html_code(G, # Writes the temporary .html file filename = tmp_filename(ext='.html') - f = open(filename, 'w') - f.write(js_code) - f.close() + with open(filename, 'w') as f: + f.write(js_code) return filename diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py index a4925add972..eed0c6af967 100644 --- a/src/sage/graphs/hypergraph_generators.py +++ b/src/sage/graphs/hypergraph_generators.py @@ -51,7 +51,9 @@ def nauty(self, number_of_sets, number_of_vertices, INPUT: - - ``number_of_sets``, ``number_of_vertices`` -- integers. + - ``number_of_sets`` -- integer, at most 64 minus ``number_of_vertices`` + + - ``number_of_vertices`` -- integer, at most 30 - ``multiple_sets`` -- boolean (default: ``False``); whether to allow several sets of the hypergraph to be equal. @@ -79,19 +81,19 @@ def nauty(self, number_of_sets, number_of_vertices, hypergraphs to be connected. - ``debug`` -- boolean (default: ``False``); if ``True`` the first line - of genbg's output to standard error is captured and the first call to + of genbgL's output to standard error is captured and the first call to the generator's ``next()`` function will return this line as a string. A line leading with ">A" indicates a successful initiation of the program with some information on the arguments, while a line beginning with ">E" indicates an error with the input. - ``options`` -- string (default: ``""``) -- anything else that should - be forwarded as input to Nauty's genbg. See its documentation for more + be forwarded as input to Nauty's genbgL. See its documentation for more information : ``_. .. NOTE:: - For genbg the *first class* elements are vertices, and *second + For genbgL the *first class* elements are vertices, and *second class* elements are the hypergraph's sets. OUTPUT: @@ -128,7 +130,25 @@ def nauty(self, number_of_sets, number_of_vertices, sage: fano = next(hypergraphs.nauty(7, 7, regular=3, max_intersection=1)) sage: print(fano) ((0, 1, 2), (0, 3, 4), (0, 5, 6), (1, 3, 5), (2, 4, 5), (2, 3, 6), (1, 4, 6)) + + TESTS:: + + sage: len(list(hypergraphs.nauty(20, 20, uniform=2, regular=2,max_intersection=1))) + 49 + sage: list(hypergraphs.nauty(40, 40, uniform=2, regular=2,max_intersection=1)) + Traceback (most recent call last): + ... + ValueError: cannot have more than 30 vertices + sage: list(hypergraphs.nauty(40, 30, uniform=2, regular=2,max_intersection=1)) + Traceback (most recent call last): + ... + ValueError: cannot have more than 64 sets+vertices """ + if number_of_vertices > 30: + raise ValueError("cannot have more than 30 vertices") + if number_of_sets + number_of_vertices > 64: + raise ValueError("cannot have more than 64 sets+vertices") + import subprocess nauty_input = options @@ -162,7 +182,7 @@ def nauty(self, number_of_sets, number_of_vertices, nauty_input += " " + str(number_of_vertices) + " " + str(number_of_sets) + " " - sp = subprocess.Popen(nautyprefix+"genbg {0}".format(nauty_input), shell=True, + sp = subprocess.Popen(nautyprefix + "genbgL {0}".format(nauty_input), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 0e07ef86be0..12137eb841b 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -714,8 +714,7 @@ def __classcall_private__(cls, n=None, names='c', cbg_type=None): n = None # derive n from counting names if n is None: - import six - if isinstance(names, six.string_types): + if isinstance(names, str): n = len(names.split(',')) else: names = list(names) diff --git a/src/sage/homology/simplicial_complex.py b/src/sage/homology/simplicial_complex.py index 322db093bdc..1c9dd8da8ea 100644 --- a/src/sage/homology/simplicial_complex.py +++ b/src/sage/homology/simplicial_complex.py @@ -773,7 +773,7 @@ def __lt__(self, other): try: return sorted(self) < sorted(other) except TypeError: - return sorted(map(str,self)) < sorted(map(str, other)) + return sorted(map(str, self)) < sorted(map(str, other)) def __hash__(self): """ @@ -4223,7 +4223,7 @@ def fixed_complex(self, G): G = self.automorphism_group().subgroup(gens) invariant_f = [list(u) for u in self.face_iterator() - if all(sorted([sigma(j) for j in u]) == sorted(list(u)) + if all(sorted(sigma(j) for j in u) == sorted(u) for sigma in gens)] new_verts = [min(o) for o in G.orbits() if o in invariant_f] return SimplicialComplex([[s for s in f if s in new_verts] diff --git a/src/sage/homology/simplicial_set.py b/src/sage/homology/simplicial_set.py index fc94b055cba..7f6403299cb 100644 --- a/src/sage/homology/simplicial_set.py +++ b/src/sage/homology/simplicial_set.py @@ -1548,7 +1548,7 @@ def all_n_simplices(self, n): d = sigma.dimension() ans.update([sigma.apply_degeneracies(*_) for _ in all_degeneracies(d, n-d)]) - return sorted(list(ans)) + return sorted(ans) def _map_from_empty_set(self): """ @@ -3532,7 +3532,7 @@ def _facets_(self): for dim in range(self.dimension(), 0, -1): for sigma in self.n_cells(dim): faces.update([tau.nondegenerate() for tau in self.faces(sigma)]) - return sorted(list(set(self.nondegenerate_simplices()).difference(faces))) + return sorted(set(self.nondegenerate_simplices()).difference(faces)) def f_vector(self): """ diff --git a/src/sage/interfaces/mathematica.py b/src/sage/interfaces/mathematica.py index 46eb80b1870..802130b7a7b 100644 --- a/src/sage/interfaces/mathematica.py +++ b/src/sage/interfaces/mathematica.py @@ -172,8 +172,8 @@ :: - sage: e = mathematica('Exp[x] - 3x == 0') # optional - mathematica - sage: e.FindRoot(['x', 2]) # optional - mathematica + sage: eqn = mathematica('Exp[x] - 3x == 0') # optional - mathematica + sage: eqn.FindRoot(['x', 2]) # optional - mathematica {x -> 1.512134551657842} Note that this agrees with what the PARI interpreter gp produces:: @@ -354,6 +354,15 @@ sage: str(mathematica('Pi*x^2-1/2').N()) # optional -- mathematica 2 -0.5 + 3.14159 x + +Check that Mathematica's `E` exponential symbol is correctly backtranslated +as Sage's `e` (:trac:`29833`):: + + sage: x = var('x') + sage: (e^x)._mathematica_().sage() # optional -- mathematica + e^x + sage: exp(x)._mathematica_().sage() # optional -- mathematica + e^x """ #***************************************************************************** diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index c21b226353c..9484212f5c6 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -1621,7 +1621,7 @@ def qepcad(formula, assume=None, interact=False, solution=None, formula = qepcad_formula.formula(formula) if len(formula.qvars) == 0: if vars is None: - vars = sorted(list(formula.vars)) + vars = sorted(formula.vars) formula = qepcad_formula.exists(vars, formula) vars = None use_witness = True diff --git a/src/sage/interfaces/rubik.py b/src/sage/interfaces/rubik.py index 233626de4ef..298bceabd0c 100644 --- a/src/sage/interfaces/rubik.py +++ b/src/sage/interfaces/rubik.py @@ -65,6 +65,7 @@ class SingNot: """ This class is to resolve difference between various Singmaster notation. + Case is ignored, and the second and third letters may be swapped. EXAMPLES:: @@ -77,7 +78,7 @@ class SingNot: """ def __init__(self, s): self.rep = s - self.canonical = (s[0] + "".join(sorted(list(s[1:])))).lower() + self.canonical = (s[0] + "".join(sorted(s[1:]))).lower() def __eq__(self, other): return isinstance(other, SingNot) and other.canonical == self.canonical def __repr__(self): @@ -88,6 +89,7 @@ def __hash__(self): # This is our list singmaster_list = [''] + [SingNot(index2singmaster(i+1)) for i in range(48)]; singmaster_list + class OptimalSolver: """ Interface to Michael Reid's optimal Rubik's Cube solver. diff --git a/src/sage/lfunctions/pari.py b/src/sage/lfunctions/pari.py index 361d1db2d77..c45f3bfd5c0 100644 --- a/src/sage/lfunctions/pari.py +++ b/src/sage/lfunctions/pari.py @@ -25,9 +25,7 @@ from cypari2.gen import Gen from sage.libs.pari import pari from sage.structure.sage_object import SageObject -from sage.rings.all import (ZZ, RealField, ComplexField, - PowerSeriesRing, IntegerModRing) -from sage.rings.complex_field import is_ComplexField +from sage.rings.all import (ZZ, RealField, ComplexField, PowerSeriesRing) class lfun_generic(object): @@ -235,7 +233,7 @@ def lfun_character(chi): sage: chi = DirichletGroup(6).gen().primitive_character() sage: L = LFunction(lfun_character(chi)) sage: L(3) - 1.20205690315959 + 0.884023811750080 TESTS: @@ -243,7 +241,7 @@ def lfun_character(chi): sage: L = LFunction(lfun_character(DirichletGroup(6).gen())) sage: L(4) - 1.08232323371114 + 0.940025680877124 With complex arguments:: @@ -251,34 +249,21 @@ def lfun_character(chi): sage: chi = DirichletGroup(6, CC).gen().primitive_character() sage: L = LFunction(lfun_character(chi)) sage: L(3) - 1.20205690315959 + 0.884023811750080 + + Check the values:: + + sage: chi = DirichletGroup(24)([1,-1,-1]); chi + Dirichlet character modulo 24 of conductor 24 + mapping 7 |--> 1, 13 |--> -1, 17 |--> -1 + sage: Lchi = lfun_character(chi) + sage: v = [0] + Lchi.lfunan(30).sage() + sage: all(v[i] == chi(i) for i in (7,13,17)) + True """ if not chi.is_primitive(): chi = chi.primitive_character() - - conductor = chi.conductor() - G = pari.znstar(conductor, 1) - - pari_orders = [pari(o) for o in G[2][1]] - pari_gens = IntegerModRing(conductor).unit_gens(algorithm="pari") - # should coincide with G[2][2] - - values_on_gens = (chi(x) for x in pari_gens) - - # now compute the input for pari (list of exponents) - P = chi.parent() - if is_ComplexField(P.base_ring()): - zeta = P.zeta() - zeta_argument = zeta.argument() - v = [int(x.argument() / zeta_argument) - for x in values_on_gens] - else: - dlog = P._zeta_dlog - v = [dlog[x] for x in values_on_gens] - - m = P.zeta_order() - v = [(vi * oi) // m for vi, oi in zip(v, pari_orders)] - + G, v = chi._pari_conversion() return pari.lfuncreate([G, v]) diff --git a/src/sage/matrix/all.py b/src/sage/matrix/all.py index cf4a4f30a7f..041624f3853 100644 --- a/src/sage/matrix/all.py +++ b/src/sage/matrix/all.py @@ -1,26 +1,7 @@ -""" -Test for deprecations of imports into global namespace:: - - sage: berlekamp_massey - doctest:warning...: - DeprecationWarning: - Importing berlekamp_massey from here is deprecated. If you need to use it, please import it directly from sage.matrix.berlekamp_massey - See https://trac.sagemath.org/27066 for details. - -""" -from __future__ import absolute_import - from sage.misc.lazy_import import lazy_import - from .matrix_space import MatrixSpace from .constructor import (matrix, Matrix, column_matrix, random_matrix, diagonal_matrix, identity_matrix, block_matrix, block_diagonal_matrix, jordan_block, zero_matrix, ones_matrix, elementary_matrix, companion_matrix) - -lazy_import("sage.matrix.berlekamp_massey", 'berlekamp_massey', - deprecation=27066) - Mat = MatrixSpace - -del absolute_import diff --git a/src/sage/matrix/matrix0.pxd b/src/sage/matrix/matrix0.pxd index e8fedda5ff0..8fbc2195563 100644 --- a/src/sage/matrix/matrix0.pxd +++ b/src/sage/matrix/matrix0.pxd @@ -49,6 +49,7 @@ cdef class Matrix(sage.structure.element.Matrix): cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, object x) cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j) cdef _coerce_element(self, x) + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j) # Row and column operations cdef check_row_bounds(self, Py_ssize_t r1, Py_ssize_t r2) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 76666ccf101..b1c0ed38ee6 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -521,6 +521,17 @@ cdef class Matrix(sage.structure.element.Matrix): """ raise NotImplementedError("this must be defined in the derived type.") + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + """ + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + Might/should be optimized for derived type. + """ + if self.get_unsafe(i, j): + return 0 + else: + return 1 + def add_to_entry(self, Py_ssize_t i, Py_ssize_t j, elt): r""" Add ``elt`` to the entry at position ``(i, j)``. @@ -3659,9 +3670,8 @@ cdef class Matrix(sage.structure.element.Matrix): if skew: # testing the diagonal entries to be zero - zero = self.parent().base_ring().zero() for i from 0 <= i < self._nrows: - if self.get_unsafe(i,i) != zero: + if not self.get_is_zero_unsafe(i,i): return False sign = -1 else: @@ -4432,20 +4442,18 @@ cdef class Matrix(sage.structure.element.Matrix): return np def nonzero_positions(self, copy=True, column_order=False): - """ - Returns the sorted list of pairs (i,j) such that self[i,j] != 0. + r""" + Return the sorted list of pairs ``(i,j)`` such that ``self[i,j] != 0``. INPUT: + - ``copy`` -- (default: ``True``) it is safe to change the + resulting list (unless you give the option ``copy=False``) - - ``copy`` - (default: True) It is safe to change the - resulting list (unless you give the option copy=False). - - - ``column_order`` - (default: False) If true, - returns the list of pairs (i,j) such that self[i,j] != 0, but - sorted by columns, i.e., column j=0 entries occur first, then - column j=1 entries, etc. - + - ``column_order`` -- (default: ``False``) If ``True``, + returns the list of pairs ``(i,j)`` such that ``self[i,j] != 0``, but + sorted by columns, i.e., column ``j=0`` entries occur first, then + column ``j=1`` entries, etc. EXAMPLES:: @@ -4475,16 +4483,16 @@ cdef class Matrix(sage.structure.element.Matrix): def _nonzero_positions_by_row(self, copy=True): """ - Returns the list of pairs (i,j) such that self[i,j] != 0. + Returns the list of pairs ``(i,j)`` such that ``self[i,j] != 0``. - It is safe to change the resulting list (unless you give the option copy=False). + It is safe to change the resulting list (unless you give the + option ``copy=False``). EXAMPLES:: sage: M = Matrix(CC, [[1,0],[0,1]], sparse=True) sage: M._nonzero_positions_by_row() [(0, 0), (1, 1)] - """ x = self.fetch('nonzero_positions') if not x is None: @@ -4492,11 +4500,10 @@ cdef class Matrix(sage.structure.element.Matrix): return list(x) return x cdef Py_ssize_t i, j - z = self._base_ring(0) nzp = [] for i from 0 <= i < self._nrows: for j from 0 <= j < self._ncols: - if self.get_unsafe(i,j) != z: + if not self.get_is_zero_unsafe(i,j): nzp.append((i,j)) self.cache('nonzero_positions', nzp) if copy: @@ -4505,19 +4512,18 @@ cdef class Matrix(sage.structure.element.Matrix): def _nonzero_positions_by_column(self, copy=True): """ - Returns the list of pairs (i,j) such that self[i,j] != 0, but - sorted by columns, i.e., column j=0 entries occur first, then - column j=1 entries, etc. + Returns the list of pairs ``(i,j)`` such that ``self[i,j] != 0``, but + sorted by columns, i.e., column ``j=0`` entries occur first, then + column ``j=1`` entries, etc. It is safe to change the resulting list (unless you give the option - copy=False). + ``copy=False``). EXAMPLES:: sage: m=matrix(QQ,2,[1,0,1,1,1,0]) sage: m._nonzero_positions_by_column() [(0, 0), (1, 0), (1, 1), (0, 2)] - """ x = self.fetch('nonzero_positions_by_column') if not x is None: @@ -4525,11 +4531,10 @@ cdef class Matrix(sage.structure.element.Matrix): return list(x) return x cdef Py_ssize_t i, j - z = self._base_ring(0) nzp = [] for j from 0 <= j < self._ncols: for i from 0 <= i < self._nrows: - if self.get_unsafe(i,j) != z: + if not self.get_is_zero_unsafe(i,j): nzp.append((i,j)) self.cache('nonzero_positions_by_column', nzp) if copy: @@ -4538,15 +4543,13 @@ cdef class Matrix(sage.structure.element.Matrix): def nonzero_positions_in_column(self, Py_ssize_t i): """ - Return a sorted list of the integers j such that self[j,i] is - nonzero, i.e., such that the j-th position of the i-th column is - nonzero. + Return a sorted list of the integers ``j`` such that ``self[j,i]`` is + nonzero, i.e., such that the ``j``-th position of the ``i``-th column + is nonzero. INPUT: - - - ``i`` - an integer - + - ``i`` -- an integer OUTPUT: list @@ -4561,7 +4564,7 @@ cdef class Matrix(sage.structure.element.Matrix): sage: a.nonzero_positions_in_column(1) [0, 1] - You'll get an IndexError, if you select an invalid column:: + You will get an ``IndexError`` if you select an invalid column:: sage: a.nonzero_positions_in_column(2) Traceback (most recent call last): @@ -4569,26 +4572,23 @@ cdef class Matrix(sage.structure.element.Matrix): IndexError: matrix column index out of range """ cdef Py_ssize_t j - z = self._base_ring(0) tmp = [] if i<0 or i >= self._ncols: raise IndexError("matrix column index out of range") for j from 0 <= j < self._nrows: - if self.get_unsafe(j,i) != z: + if not self.get_is_zero_unsafe(j,i): tmp.append(j) return tmp def nonzero_positions_in_row(self, Py_ssize_t i): """ - Return the integers j such that self[i,j] is nonzero, i.e., such - that the j-th position of the i-th row is nonzero. + Return the integers ``j`` such that ``self[i,j]`` is nonzero, i.e., + such that the ``j``-th position of the ``i``-th row is nonzero. INPUT: - - - ``i`` - an integer - + - ``i`` -- an integer OUTPUT: list @@ -4607,14 +4607,13 @@ cdef class Matrix(sage.structure.element.Matrix): """ cdef Py_ssize_t j - if i<0 or i >= self._nrows: + if i < 0 or i >= self._nrows: raise IndexError("matrix row index out of range") - z = self._base_ring(0) tmp = [] for j from 0 <= j < self._ncols: - if self.get_unsafe(i,j) != z: + if not self.get_is_zero_unsafe(i,j): tmp.append(j) return tmp @@ -5634,9 +5633,9 @@ cdef class Matrix(sage.structure.element.Matrix): [1] sage: 0^0 1 - + Non-integer (symbolic) exponents are also supported:: - + sage: k = var('k') sage: A = matrix([[2, -1], [1, 0]]) sage: A^(2*k+1) @@ -5829,7 +5828,7 @@ cdef class Matrix(sage.structure.element.Matrix): cdef Py_ssize_t i, j for i from 0 <= i < self._nrows: for j from 0 <= j < self._ncols: - if self.get_unsafe(i,j): + if not self.get_is_zero_unsafe(i,j): return True return False diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index fbdbe4fc5e2..689195dc858 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -2204,6 +2204,112 @@ cdef class Matrix(Matrix0): msg = "Cannot set column with {0} elements over {1}, use change_ring first." raise TypeError(msg.format(v[i].parent(), self.base_ring())) + def zero_pattern_matrix(self, ring=None): + """ + Return a matrix that contains one for corresponding zero entries. + + All other entries are zero. + + INPUT: + + - ``ring`` -- (optional); base ring of the output; default is ``ZZ`` + + OUTPUT: + + A new dense matrix with same dimensions as ``self`` + and with base ring ``ring``. + + EXAMPLES:: + + sage: M = Matrix(ZZ, 2, [1,2,-2,0]) + sage: M.zero_pattern_matrix() + [0 0] + [0 1] + + sage: M = Matrix(QQ, 2, [1,2/3,-2,0]) + sage: M.zero_pattern_matrix() + [0 0] + [0 1] + + Default base ring for the output is ``ZZ``:: + + sage: M.zero_pattern_matrix().base_ring() + Integer Ring + + Specify a different base ring for the output:: + + sage: M.zero_pattern_matrix(GF(2)).base_ring() + Finite Field of size 2 + + Examples for different base rings for ``self``:: + + sage: M = Matrix(Zmod(8), 3, 2, [2, 3, 9, 8, 1, 0]); M + [2 3] + [1 0] + [1 0] + sage: M.zero_pattern_matrix() + [0 0] + [0 1] + [0 1] + + :: + + sage: W. = CyclotomicField(100) + sage: M = Matrix(2, 3, [a, a/2, 0, a^2, a^100-1, a^2 - a]); M + [ a 1/2*a 0] + [ a^2 0 a^2 - a] + sage: M.zero_pattern_matrix() + [0 0 1] + [0 1 0] + + :: + + sage: K. = GF(2^4) + sage: l = [a^2 + 1, a^3 + 1, 0, 0, a, a^3 + a + 1, a + 1, + ....: a + 1, a^2, a^3 + a + 1, a^3 + a, a^3 + a] + sage: M = Matrix(K, 3, 4, l); M + [ a^2 + 1 a^3 + 1 0 0] + [ a a^3 + a + 1 a + 1 a + 1] + [ a^2 a^3 + a + 1 a^3 + a a^3 + a] + sage: M.zero_pattern_matrix() + [0 0 1 1] + [0 0 0 0] + [0 0 0 0] + + :: + + sage: K. = GF(25) + sage: M = Matrix(K, 2, 3, [0, 2, 3, 5, a, a^2]) + sage: M + [ 0 2 3] + [ 0 a a + 3] + sage: M.zero_pattern_matrix() + [1 0 0] + [1 0 0] + + .. NOTE:: + + This method can be optimized by improving + :meth:`get_is_zero_unsafe` for derived matrix classes. + """ + if ring is None: + from sage.rings.all import ZZ + ring = ZZ + + cdef object zero = ring.zero() + cdef object one = ring.one() + cdef Py_ssize_t i, j + + from sage.matrix.matrix_space import MatrixSpace + MZ = MatrixSpace(ring, self._nrows, self._ncols, sparse=False) + cdef Matrix M = MZ(zero, None, None) # initialize with zeros + + for i from 0 <= i < self._nrows: + for j from 0 <= j < self._ncols: + if self.get_is_zero_unsafe(i, j): + M.set_unsafe(i, j, one) + return M + #################################################################################### # Change of representation between dense and sparse. diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 707d9cc031d..5e7a0768fc0 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -3206,13 +3206,13 @@ cdef class Matrix(Matrix1): # Search for a non-zero entry in column m-1 i = -1 for r from m+1 <= r < n: - if self.get_unsafe(r, m-1) != zero: + if not self.get_is_zero_unsafe(r, m-1): i = r break if i != -1: # Found a nonzero entry in column m-1 that is strictly below row m # Now set i to be the first nonzero position >= m in column m-1 - if self.get_unsafe(m,m-1) != zero: + if not self.get_is_zero_unsafe(m,m-1): i = m t = self.get_unsafe(i,m-1) t_inv = None diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index 5b440ab540b..f930c329751 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -404,6 +404,26 @@ cdef class Matrix_cyclo_dense(Matrix_dense): return x + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + r""" + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: K. = CyclotomicField(3) + sage: A = matrix(K, 4, 3, [0, -z, -2, -2*z + 2, 2*z, z, z, 1-z, 2+3*z, z, 1+z, 0]) + sage: A.zero_pattern_matrix() # indirect doctest + [1 0 0] + [0 0 0] + [0 0 0] + [0 0 1] + """ + cdef int a + for a in range(self._degree): + if not self._matrix.get_is_zero_unsafe(a, j+i*self._ncols): + return False + return True + def _pickle(self): """ Used for pickling matrices. This function returns the diff --git a/src/sage/matrix/matrix_generic_sparse.pyx b/src/sage/matrix/matrix_generic_sparse.pyx index 7618257e13a..51858e0e1af 100644 --- a/src/sage/matrix/matrix_generic_sparse.pyx +++ b/src/sage/matrix/matrix_generic_sparse.pyx @@ -202,6 +202,20 @@ cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j): return self._entries.get((i,j), self._zero) + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + """ + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: R. = Zmod(5)['a','b'] + sage: m = matrix(R,2,4, {(1,3): a, (0,0):b}, sparse=True) + sage: m.zero_pattern_matrix() # indirect doctest + [0 1 1 1] + [1 1 1 0] + """ + return (i,j) not in self._entries + def _pickle(self): version = 0 return self._entries, version diff --git a/src/sage/matrix/matrix_gf2e_dense.pxd b/src/sage/matrix/matrix_gf2e_dense.pxd index 6050b3da431..c8d81d279f9 100644 --- a/src/sage/matrix/matrix_gf2e_dense.pxd +++ b/src/sage/matrix/matrix_gf2e_dense.pxd @@ -1,4 +1,5 @@ from sage.libs.m4rie cimport mzed_t +from sage.libs.m4ri cimport m4ri_word from .matrix_dense cimport Matrix_dense @@ -6,6 +7,7 @@ cdef class Matrix_gf2e_dense(Matrix_dense): cdef mzed_t *_entries cdef object _one cdef object _zero + cdef m4ri_word _zero_word # m4ri_word representation of _zero cpdef Matrix_gf2e_dense _multiply_newton_john(Matrix_gf2e_dense self, Matrix_gf2e_dense right) cpdef Matrix_gf2e_dense _multiply_karatsuba(Matrix_gf2e_dense self, Matrix_gf2e_dense right) diff --git a/src/sage/matrix/matrix_gf2e_dense.pyx b/src/sage/matrix/matrix_gf2e_dense.pyx index 1f92788b310..6c0a6c42c49 100644 --- a/src/sage/matrix/matrix_gf2e_dense.pyx +++ b/src/sage/matrix/matrix_gf2e_dense.pyx @@ -188,6 +188,7 @@ cdef class Matrix_gf2e_dense(matrix_dense.Matrix_dense): # cache elements self._zero = self._base_ring(0) + self._zero_word = poly_to_word(self._zero) self._one = self._base_ring(1) def __dealloc__(self): @@ -295,6 +296,20 @@ cdef class Matrix_gf2e_dense(matrix_dense.Matrix_dense): cdef int r = mzed_read_elem(self._entries, i, j) return word_to_poly(r, self._base_ring) + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + r""" + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: K. = GF(2^4) + sage: A = Matrix(K, 2, 2, a) + sage: A.zero_pattern_matrix() # indirect doctest + [0 1] + [1 0] + """ + return mzed_read_elem(self._entries, i, j) == self._zero_word + cpdef _add_(self, right): """ Return A+B @@ -712,6 +727,24 @@ cdef class Matrix_gf2e_dense(matrix_dense.Matrix_dense): return A + def __bool__(self): + """ + Return if ``self`` is a zero matrix or not. + + EXAMPLES:: + + sage: K. = GF(2^4) + sage: A = Matrix(K, 2, 2, a) + sage: bool(A) + True + sage: zero = MatrixSpace(K, 3, 3).zero() + sage: bool(zero) + False + """ + if self._nrows and self._ncols: + return not mzed_is_zero(self._entries) + return False + def _list(self): """ EXAMPLES:: @@ -955,7 +988,7 @@ cdef class Matrix_gf2e_dense(matrix_dense.Matrix_dense): i = 0 while i < self._nrows: for j from i <= j < nc: - if self.get_unsafe(i,j): + if not self.get_is_zero_unsafe(i,j): pivots.append(j) i += 1 break diff --git a/src/sage/matrix/matrix_gfpn_dense.pxd b/src/sage/matrix/matrix_gfpn_dense.pxd index 39b524a20f9..5929141ff89 100644 --- a/src/sage/matrix/matrix_gfpn_dense.pxd +++ b/src/sage/matrix/matrix_gfpn_dense.pxd @@ -15,6 +15,7 @@ from sage.libs.meataxe cimport * cdef class FieldConverter_class: cdef field # A function converting an int to a field element + cdef FEL zero_FEL # the FEL representation of zero cpdef fel_to_field(self, FEL x) cpdef FEL field_to_fel(self, x) except 255 diff --git a/src/sage/matrix/matrix_gfpn_dense.pyx b/src/sage/matrix/matrix_gfpn_dense.pyx index 42af34dc10b..0735177b1bb 100644 --- a/src/sage/matrix/matrix_gfpn_dense.pyx +++ b/src/sage/matrix/matrix_gfpn_dense.pyx @@ -120,6 +120,7 @@ cdef class FieldConverter_class: """ self.field = field._cache.fetch_int + self.zero_FEL = self.field_to_fel(field.zero()) cpdef fel_to_field(self, FEL x): """ @@ -577,6 +578,21 @@ cdef class Matrix_gfpn_dense(Matrix_dense): # This method is here for speed! return FfToInt(FfExtract(MatGetPtr(self.Data,i), j)) + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + r""" + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: F. = GF(9) + sage: M = MatrixSpace(F,2,5)(sorted(list(F))+[0]) + sage: M.zero_pattern_matrix() # indirect doctest + [1 0 0 0 0] + [0 0 0 0 1] + """ + FfSetField(self.Data.Field) + return FfExtract(MatGetPtr(self.Data,i), j) == self._converter.zero_FEL + cpdef Matrix_gfpn_dense get_slice(self, Py_ssize_t i, Py_ssize_t j): """ Return a horizontal slice of this matrix. diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 06fee14437e..cca38cb7840 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -120,6 +120,7 @@ from .matrix_modn_dense_double cimport Matrix_modn_dense_double from .matrix_mod2_dense import Matrix_mod2_dense from .matrix_mod2_dense cimport Matrix_mod2_dense +from sage.rings.finite_rings.finite_field_constructor import GF from .matrix2 import decomp_seq @@ -377,7 +378,7 @@ cdef class Matrix_integer_dense(Matrix_dense): """ Returns (i, j) entry of self as a new Integer. - .. warning:: + .. WARNING:: This is very unsafe; it assumes i and j are in the right range. @@ -405,7 +406,7 @@ cdef class Matrix_integer_dense(Matrix_dense): """ Copy entry i,j of the matrix ``self`` to ``value``. - .. warning:: + .. WARNING:: This is very unsafe; it assumes i and j are in the right range. @@ -431,7 +432,7 @@ cdef class Matrix_integer_dense(Matrix_dense): """ Returns (j, i) entry of self as a new Integer. - .. warning:: + .. WARNING:: This is very unsafe; it assumes i and j are in the right range. @@ -453,6 +454,17 @@ cdef class Matrix_integer_dense(Matrix_dense): """ return fmpz_get_d(fmpz_mat_entry(self._matrix, i, j)) + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + """ + Return 1 if the entry (i, j) is zero, otherwise 0. + + .. WARNING:: + + This is very unsafe; it assumes i and j are in the right + range. + """ + return fmpz_is_zero(fmpz_mat_entry(self._matrix, i,j)) + def _pickle(self): """ EXAMPLES:: @@ -680,7 +692,7 @@ cdef class Matrix_integer_dense(Matrix_dense): """ Multiply matrices over ZZ using linbox. - .. warning:: + .. WARNING:: This is very slow right now, i.e., linbox is very slow. @@ -1546,7 +1558,17 @@ cdef class Matrix_integer_dense(Matrix_dense): return self._mod_int_c(modulus) cdef _mod_two(self): - MS = matrix_space.MatrixSpace(IntegerModRing(2), self._nrows, self._ncols) + """ + TESTS: + + Check that bug discovered in :trac:`29839` is fixed:: + + sage: M = Matrix(ZZ, [[0,1],[0,1]]) + sage: M._mod_int(2).transpose() + [0 0] + [1 1] + """ + MS = matrix_space.MatrixSpace(GF(2), self._nrows, self._ncols) return Matrix_mod2_dense(MS, self, True, True) cdef _mod_int_c(self, mod_int p): @@ -2239,7 +2261,7 @@ cdef class Matrix_integer_dense(Matrix_dense): """ Return the elementary divisors of self, in order. - .. warning:: + .. WARNING:: This is MUCH faster than the :meth:`smith_form` function. @@ -4846,7 +4868,7 @@ cdef class Matrix_integer_dense(Matrix_dense): a new matrix that is the echelon form of self with row appended to the bottom. - .. warning:: + .. WARNING:: It is assumed that self is in echelon form. diff --git a/src/sage/matrix/matrix_integer_sparse.pyx b/src/sage/matrix/matrix_integer_sparse.pyx index 8163172d862..f21a9975af3 100644 --- a/src/sage/matrix/matrix_integer_sparse.pyx +++ b/src/sage/matrix/matrix_integer_sparse.pyx @@ -119,6 +119,20 @@ cdef class Matrix_integer_sparse(Matrix_sparse): mpz_vector_get_entry(x.value, &self._matrix[i], j) return x + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + """ + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: M = matrix(ZZ, [[0,1,0],[0,0,0]], sparse=True) + sage: M.zero_pattern_matrix() # indirect doctest + [1 0 1] + [1 1 1] + """ + return mpz_vector_is_entry_zero_unsafe(&self._matrix[i], j) + + ######################################################################## # LEVEL 2 functionality # * def _pickle diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index 0877ee78b43..829ec80bded 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -3368,3 +3368,22 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cdef celement *_from = self._entries+(i*self._ncols) for j in range(self._ncols): to[j] = _from[j] + + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + r""" + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: M = Matrix(GF(49), 2, [1,2,-2,0]) + sage: M.zero_pattern_matrix() # indirect doctest + [0 0] + [0 1] + + sage: M = Matrix(Integers(10), 2, [1,2,-2,0]) + sage: M.zero_pattern_matrix() # indirect doctest + [0 0] + [0 1] + """ + return self._entries[j+i*self._ncols] == 0 + diff --git a/src/sage/matrix/matrix_modn_sparse.pyx b/src/sage/matrix/matrix_modn_sparse.pyx index 335be5fb687..52e846c4e94 100644 --- a/src/sage/matrix/matrix_modn_sparse.pyx +++ b/src/sage/matrix/matrix_modn_sparse.pyx @@ -193,6 +193,19 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): n.ivalue = get_entry(&self.rows[i], j) return n + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + """ + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: M = matrix(GF(13), [[0,1,0],[0,0,0]], sparse=True) + sage: M.zero_pattern_matrix() # indirect doctest + [1 0 1] + [1 1 1] + """ + return is_entry_zero_unsafe(&self.rows[i], j) + def _dict(self): """ Unsafe version of the dict method, mainly for internal use. This diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index 3f6c60e9001..9296e1b8698 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -115,6 +115,7 @@ from sage.arith.all import gcd from .matrix2 import decomp_seq from .matrix0 import Matrix as Matrix_base + from sage.misc.all import verbose, get_verbose, prod ######################################################### @@ -139,7 +140,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: type(a) - .. warning:: + .. WARNING:: This is for internal use only, or if you really know what you're doing. @@ -265,6 +266,17 @@ cdef class Matrix_rational_dense(Matrix_dense): fmpq_get_mpq(x.value, fmpq_mat_entry(self._matrix, i, j)) return x + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + """ + Return 1 if the entry (i, j) is zero, otherwise 0. + + .. WARNING:: + + This is very unsafe; it assumes i and j are in the right + range. + """ + return fmpq_is_zero(fmpq_mat_entry(self._matrix, i,j)) + cdef _add_ui_unsafe_assuming_int(self, Py_ssize_t i, Py_ssize_t j, unsigned long int n): # doesn't check immutability # doesn't do bounds checks. diff --git a/src/sage/matrix/matrix_rational_sparse.pyx b/src/sage/matrix/matrix_rational_sparse.pyx index aa532514023..23f1e147626 100644 --- a/src/sage/matrix/matrix_rational_sparse.pyx +++ b/src/sage/matrix/matrix_rational_sparse.pyx @@ -103,6 +103,19 @@ cdef class Matrix_rational_sparse(Matrix_sparse): mpq_vector_get_entry(x.value, &self._matrix[i], j) return x + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + """ + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: M = matrix(QQ, [[0,1,0],[0,0,0]], sparse=True) + sage: M.zero_pattern_matrix() # indirect doctest + [1 0 1] + [1 1 1] + """ + return mpq_vector_is_entry_zero_unsafe(&self._matrix[i], j) + def add_to_entry(self, Py_ssize_t i, Py_ssize_t j, elt): r""" Add ``elt`` to the entry at position ``(i, j)``. diff --git a/src/sage/matrix/matrix_symbolic_dense.pyx b/src/sage/matrix/matrix_symbolic_dense.pyx index 2065a61e844..e4e009e68d2 100644 --- a/src/sage/matrix/matrix_symbolic_dense.pyx +++ b/src/sage/matrix/matrix_symbolic_dense.pyx @@ -772,7 +772,7 @@ cdef class Matrix_symbolic_dense(Matrix_generic_dense): [ x^2 + 2 -2*x + 3] [ -4*x + 6 x^2 - 6*x + 11] """ - from sage.misc.misc import attrcall + from sage.misc.call import attrcall return self.apply_map(attrcall('expand')) def variables(self): @@ -905,3 +905,24 @@ cdef class Matrix_symbolic_dense(Matrix_generic_dense): new_entries.append(entry) return self.parent(new_entries) + + cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j): + r""" + Return 1 if the entry ``(i, j)`` is zero, otherwise 0. + + EXAMPLES:: + + sage: M = matrix(SR, [[0,1,0],[0,0,0]]) + sage: M.zero_pattern_matrix() # indirect doctest + [1 0 1] + [1 1 1] + """ + entry = self.get_unsafe(i, j) + # See if we can avoid the full proof machinery that the entry is 0 + if entry.is_trivial_zero(): + return 1 + if entry: + return 0 + else: + return 1 + diff --git a/src/sage/matroids/matroids_plot_helpers.py b/src/sage/matroids/matroids_plot_helpers.py index 1967c76c485..bef61c33bfd 100644 --- a/src/sage/matroids/matroids_plot_helpers.py +++ b/src/sage/matroids/matroids_plot_helpers.py @@ -524,7 +524,7 @@ def addlp(M, M1, L, P, ptsdict, G=None, limits=None): if P: # create list of lists where inner lists are parallel classes pcls = [] - gnd = sorted(list(M1.groundset())) + gnd = sorted(M1.groundset()) for g in gnd: pcl = [g] for p in P: diff --git a/src/sage/misc/all.py b/src/sage/misc/all.py index 75d8295622c..1eb98169cdc 100644 --- a/src/sage/misc/all.py +++ b/src/sage/misc/all.py @@ -9,11 +9,13 @@ exists, forall, is_iterator, random_sublist, walltime, repr_lincomb, - pad_zeros, attrcall, + pad_zeros, SAGE_DB, SAGE_TMP, newton_method_sizes, compose, nest) +from .call import attrcall + from .banner import version, banner from .temporary_file import tmp_dir, tmp_filename diff --git a/src/sage/misc/call.py b/src/sage/misc/call.py new file mode 100644 index 00000000000..5b259b8f5a2 --- /dev/null +++ b/src/sage/misc/call.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +""" +Attribute and method calling +""" + +# **************************************************************************** +# Copyright (C) 2008 Mike Hansen +# Copyright (C) 2010, 2013 Nicolas M. Thiery +# Copyright (C) 2018 Frédéric Chapoton +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +############################################# +# Operators +############################################# +class AttrCallObject(object): + def __init__(self, name, args, kwds): + """ + TESTS:: + + sage: f = attrcall('core', 3); f + *.core(3) + sage: TestSuite(f).run() + """ + self.name = name + self.args = args + self.kwds = kwds + + def __call__(self, x, *args): + """ + Gets the ``self.name`` method from ``x``, calls it with + ``self.args`` and ``args`` as positional parameters and + ``self.kwds`` as keyword parameters, and returns the result. + + EXAMPLES:: + + sage: core = attrcall('core', 3) + sage: core(Partition([4,2])) + [4, 2] + + sage: series = attrcall('series', x) + sage: series(sin(x), 4) + 1*x + (-1/6)*x^3 + Order(x^4) + """ + return getattr(x, self.name)(*(self.args + args), **self.kwds) + + def __repr__(self): + """ + Return a string representation of this object. + + The star in the output represents the object passed into ``self``. + + EXAMPLES:: + + sage: attrcall('core', 3) + *.core(3) + sage: attrcall('hooks', flatten=True) + *.hooks(flatten=True) + sage: attrcall('hooks', 3, flatten=True) + *.hooks(3, flatten=True) + """ + s = "*.%s(%s" % (self.name, ", ".join(map(repr, self.args))) + if self.kwds: + if self.args: + s += ", " + s += ", ".join("%s=%s" % keyvalue for keyvalue in self.kwds.items()) + s += ")" + return s + + def __eq__(self, other): + """ + Equality testing + + EXAMPLES:: + + sage: attrcall('core', 3, flatten = True) == attrcall('core', 3, flatten = True) + True + sage: attrcall('core', 2) == attrcall('core', 3) + False + sage: attrcall('core', 2) == 1 + False + """ + return self.__class__ == other.__class__ and self.__dict__ == other.__dict__ + + def __ne__(self, other): + """ + Equality testing + + EXAMPLES:: + + sage: attrcall('core', 3, flatten = True) != attrcall('core', 3, flatten = True) + False + sage: attrcall('core', 2) != attrcall('core', 3) + True + sage: attrcall('core', 2) != 1 + True + """ + return not self == other + + def __hash__(self): + """ + Hash value + + This method tries to ensure that, when two ``attrcall`` + objects are equal, they have the same hash value. + + .. warning:: dicts are not hashable, so we instead hash their + items; however the order of those items might differ. The + proper fix would be to use a frozen dict for ``kwds``, when + frozen dicts will be available in Python. + + EXAMPLES:: + + sage: x = attrcall('core', 3, flatten = True, blah = 1) + sage: hash(x) # random # indirect doctest + 210434060 + sage: type(hash(x)) + + sage: y = attrcall('core', 3, blah = 1, flatten = True) + sage: hash(y) == hash(x) + True + sage: y = attrcall('core', 3, flatten = True, blah = 2) + sage: hash(y) != hash(x) + True + sage: hash(attrcall('core', 2)) != hash(attrcall('core', 3)) + True + sage: hash(attrcall('core', 2)) != hash(1) + True + + Note: a missing ``__hash__`` method here used to break the + unique representation of parents taking ``attrcall`` objects + as input; see :trac:`8911`. + """ + return hash((self.args, tuple(sorted(self.kwds.items())))) + + +def attrcall(name, *args, **kwds): + """ + Returns a callable which takes in an object, gets the method named + name from that object, and calls it with the specified arguments + and keywords. + + INPUT: + + - ``name`` - a string of the name of the method you + want to call + + - ``args, kwds`` - arguments and keywords to be passed + to the method + + EXAMPLES:: + + sage: f = attrcall('core', 3); f + *.core(3) + sage: [f(p) for p in Partitions(5)] + [[2], [1, 1], [1, 1], [3, 1, 1], [2], [2], [1, 1]] + """ + return AttrCallObject(name, args, kwds) + + +def call_method(obj, name, *args, **kwds): + """ + Call the method ``name`` on ``obj``. + + This has to exist somewhere in Python!!! + + .. SEEALSO:: :func:`operator.methodcaller` :func:`attrcal` + + EXAMPLES:: + + sage: from sage.misc.call import call_method + sage: call_method(1, "__add__", 2) + 3 + """ + return getattr(obj, name)(*args, **kwds) + +from sage.misc.persist import register_unpickle_override +register_unpickle_override("sage.misc.misc", "call_method", call_method) diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index af5f99d03eb..0600603e62d 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -41,7 +41,7 @@ cblas_include_dirs = list(cblas_pc['include_dirs']) standard_libs = [ - 'mpfr', 'gmp', 'gmpxx', 'stdc++', 'pari', 'm', + 'mpfr', 'gmp', 'gmpxx', 'pari', 'm', 'ec', 'gsl', ] + cblas_libs + [ 'ntl'] diff --git a/src/sage/misc/defaults.py b/src/sage/misc/defaults.py index 44e455a25ae..2aa3ad84013 100644 --- a/src/sage/misc/defaults.py +++ b/src/sage/misc/defaults.py @@ -25,19 +25,65 @@ def variable_names(n, name=None): + r""" + Converts a root string into a tuple of variable names by adding + numbers in sequence. + + INPUT: + + - ``n`` a non-negative Integer; the number of variable names to + output + - ``names`` a string (default: ``None``); the root of the variable + name. + + EXAMPLES:: + + sage: from sage.misc.defaults import variable_names + sage: variable_names(0) + () + sage: variable_names(1) + ('x',) + sage: variable_names(1,'alpha') + ('alpha',) + sage: variable_names(2,'alpha') + ('alpha0', 'alpha1') + """ if name is None: name = var_name n = int(n) if n == 1: - return [name] + return (name,) return tuple(['%s%s'%(name,i) for i in range(n)]) def latex_variable_names(n, name=None): + r""" + Converts a root string into a tuple of variable names by adding + numbers in sequence. + + INPUT: + + - ``n`` a non-negative Integer; the number of variable names to + output + - ``names`` a string (default: ``None``); the root of the variable + name. + + EXAMPLES:: + + sage: from sage.misc.defaults import latex_variable_names + sage: latex_variable_names(0) + () + sage: latex_variable_names(1,'a') + ('a',) + sage: latex_variable_names(3,beta) + ('beta_{0}', 'beta_{1}', 'beta_{2}') + sage: latex_variable_names(3,r'\beta') + ('\\beta_{0}', '\\beta_{1}', '\\beta_{2}') + """ if name is None: name = var_name n = int(n) if n == 1: - return [name] + return (name,) v = tuple(['%s_{%s}'%(name,i) for i in range(n)]) return v diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index b3c538d7c88..1583f4d8626 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -49,6 +49,11 @@ from .lazy_string import lazy_string import sage.server.support +from sage.misc.lazy_import import lazy_import + +lazy_import("sage.misc.call", ["AttrCallObject", "attrcall", "call_method"], + deprecation=29869) + from sage.env import DOT_SAGE, HOSTNAME LOCAL_IDENTIFIER = '%s.%s' % (HOSTNAME, os.getpid()) @@ -1563,172 +1568,6 @@ def embedded(): """ return sage.server.support.EMBEDDED_MODE - -############################################# -# Operators -############################################# -class AttrCallObject(object): - def __init__(self, name, args, kwds): - """ - TESTS:: - - sage: f = attrcall('core', 3); f - *.core(3) - sage: TestSuite(f).run() - """ - self.name = name - self.args = args - self.kwds = kwds - - def __call__(self, x, *args): - """ - Gets the ``self.name`` method from ``x``, calls it with - ``self.args`` and ``args`` as positional parameters and - ``self.kwds`` as keyword parameters, and returns the result. - - EXAMPLES:: - - sage: core = attrcall('core', 3) - sage: core(Partition([4,2])) - [4, 2] - - sage: series = attrcall('series', x) - sage: series(sin(x), 4) - 1*x + (-1/6)*x^3 + Order(x^4) - """ - return getattr(x, self.name)(*(self.args + args), **self.kwds) - - def __repr__(self): - """ - Return a string representation of this object. - - The star in the output represents the object passed into ``self``. - - EXAMPLES:: - - sage: attrcall('core', 3) - *.core(3) - sage: attrcall('hooks', flatten=True) - *.hooks(flatten=True) - sage: attrcall('hooks', 3, flatten=True) - *.hooks(3, flatten=True) - """ - s = "*.%s(%s" % (self.name, ", ".join(map(repr, self.args))) - if self.kwds: - if self.args: - s += ", " - s += ", ".join("%s=%s" % keyvalue for keyvalue in self.kwds.items()) - s += ")" - return s - - def __eq__(self, other): - """ - Equality testing - - EXAMPLES:: - - sage: attrcall('core', 3, flatten = True) == attrcall('core', 3, flatten = True) - True - sage: attrcall('core', 2) == attrcall('core', 3) - False - sage: attrcall('core', 2) == 1 - False - """ - return self.__class__ == other.__class__ and self.__dict__ == other.__dict__ - - def __ne__(self, other): - """ - Equality testing - - EXAMPLES:: - - sage: attrcall('core', 3, flatten = True) != attrcall('core', 3, flatten = True) - False - sage: attrcall('core', 2) != attrcall('core', 3) - True - sage: attrcall('core', 2) != 1 - True - """ - return not self == other - - def __hash__(self): - """ - Hash value - - This method tries to ensure that, when two ``attrcall`` - objects are equal, they have the same hash value. - - .. warning:: dicts are not hashable, so we instead hash their - items; however the order of those items might differ. The - proper fix would be to use a frozen dict for ``kwds``, when - frozen dicts will be available in Python. - - EXAMPLES:: - - sage: x = attrcall('core', 3, flatten = True, blah = 1) - sage: hash(x) # random # indirect doctest - 210434060 - sage: type(hash(x)) - - sage: y = attrcall('core', 3, blah = 1, flatten = True) - sage: hash(y) == hash(x) - True - sage: y = attrcall('core', 3, flatten = True, blah = 2) - sage: hash(y) != hash(x) - True - sage: hash(attrcall('core', 2)) != hash(attrcall('core', 3)) - True - sage: hash(attrcall('core', 2)) != hash(1) - True - - Note: a missing ``__hash__`` method here used to break the - unique representation of parents taking ``attrcall`` objects - as input; see :trac:`8911`. - """ - return hash((self.args, tuple(sorted(self.kwds.items())))) - - -def attrcall(name, *args, **kwds): - """ - Returns a callable which takes in an object, gets the method named - name from that object, and calls it with the specified arguments - and keywords. - - INPUT: - - - ``name`` - a string of the name of the method you - want to call - - - ``args, kwds`` - arguments and keywords to be passed - to the method - - EXAMPLES:: - - sage: f = attrcall('core', 3); f - *.core(3) - sage: [f(p) for p in Partitions(5)] - [[2], [1, 1], [1, 1], [3, 1, 1], [2], [2], [1, 1]] - """ - return AttrCallObject(name, args, kwds) - - -def call_method(obj, name, *args, **kwds): - """ - Call the method ``name`` on ``obj``. - - This has to exist somewhere in Python!!! - - .. SEEALSO:: :func:`operator.methodcaller` :func:`attrcal` - - EXAMPLES:: - - sage: from sage.misc.misc import call_method - sage: call_method(1, "__add__", 2) - 3 - """ - return getattr(obj, name)(*args, **kwds) - - def is_in_string(line, pos): r""" Returns True if the character at position pos in line occurs diff --git a/src/sage/modular/all.py b/src/sage/modular/all.py index 83ca4ab58f5..e9c96d04cda 100644 --- a/src/sage/modular/all.py +++ b/src/sage/modular/all.py @@ -1,14 +1,3 @@ -""" -Test for deprecations of imports into global namespace:: - - sage: buzzard_tpslopes - doctest:warning...: - DeprecationWarning: - Importing buzzard_tpslopes from here is deprecated. If you need to use it, please import it directly from sage.modular.buzzard - See https://trac.sagemath.org/27066 for details. - -""" -from __future__ import absolute_import from sage.misc.lazy_import import lazy_import from .quatalg.all import * @@ -37,8 +26,6 @@ dimension_modular_forms, sturm_bound) -lazy_import("sage.modular.buzzard", 'buzzard_tpslopes', deprecation=27066) - from .etaproducts import (EtaGroup, EtaProduct, EtaGroupElement, AllCusps, CuspFamily) @@ -53,5 +40,3 @@ from .btquotients.all import * from .pollack_stevens.all import * - -del absolute_import diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index 1204e393221..293f439d002 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -65,7 +65,8 @@ import sage.modules.free_module_element as free_module_element import sage.rings.all as rings import sage.rings.number_field.number_field as number_field - +from sage.libs.pari import pari + from sage.categories.map import Map from sage.rings.rational_field import is_RationalField from sage.rings.complex_field import is_ComplexField @@ -878,6 +879,109 @@ def extend(self, M): H = DirichletGroup(M, self.base_ring()) return H(self) + def _pari_conversion(self): + r""" + Prepare data for the conversion of the character to Pari. + + OUTPUT: + + pair (G, v) where G is `(\ZZ / N \ZZ)^*` where `N` is the modulus + + EXAMPLES:: + + sage: chi4 = DirichletGroup(4).gen() + sage: chi4._pari_conversion() + ([[4, [0]], [2, [2], [3]], [[2]~, Vecsmall([2])], + [[4], [[1, matrix(0,2)]], Mat(1), [3], [2], [0]], Mat(1)], [1]) + + sage: chi = DirichletGroup(24)([1,-1,-1]); chi + Dirichlet character modulo 24 of conductor 24 + mapping 7 |--> 1, 13 |--> -1, 17 |--> -1 + sage: chi._pari_conversion() + ([[24, [0]], [8, [2, 2, 2], [7, 13, 17]], + [[2, 2, 3]~, Vecsmall([3, 3, 1])], + [[8, 8, 3], [[1, matrix(0,2)], [1, matrix(0,2)], [2, Mat([2, 1])]], + [1, 0, 0; 0, 1, 0; 0, 0, 1], [7, 13, 17], [2, 2, 2], [0, 0, 0]], + [1, 0, 0; 0, 1, 0; 0, 0, 1]], [0, 1, 1]) + """ + G = pari.znstar(self.modulus(), 1) + + pari_orders = G[1][1] + pari_gens = G[1][2] + # one should use the following, but this does not work + # pari_orders = G.cyc() + # pari_gens = G.gen() + + values_on_gens = (self(x) for x in pari_gens) + + # now compute the input for pari (list of exponents) + P = self.parent() + if is_ComplexField(P.base_ring()): + zeta = P.zeta() + zeta_argument = zeta.argument() + v = [int(x.argument() / zeta_argument) for x in values_on_gens] + else: + dlog = P._zeta_dlog + v = [dlog[x] for x in values_on_gens] + + m = P.zeta_order() + v = [(vi * oi) // m for vi, oi in zip(v, pari_orders)] + return (G, v) + + def conrey_number(self): + r""" + Return the Conrey number for this character. + + This is a positive integer coprime to q that identifies a + Dirichlet character of modulus q. + + See https://www.lmfdb.org/knowledge/show/character.dirichlet.conrey + + EXAMPLES:: + + sage: chi4 = DirichletGroup(4).gen() + sage: chi4.conrey_number() + 3 + sage: chi = DirichletGroup(24)([1,-1,-1]); chi + Dirichlet character modulo 24 of conductor 24 + mapping 7 |--> 1, 13 |--> -1, 17 |--> -1 + sage: chi.conrey_number() + 5 + + sage: chi = DirichletGroup(60)([1,-1,I]) + sage: chi.conrey_number() + 17 + + sage: chi = DirichletGroup(420)([1,-1,-I,1]) + sage: chi.conrey_number() + 113 + + TESTS:: + + sage: eps1 = DirichletGroup(5)([-1]) + sage: eps2 = DirichletGroup(5,QQ)([-1]) + sage: eps1.conrey_number() == eps2.conrey_number() + True + """ + G, v = self._pari_conversion() + return pari.znconreyexp(G, v).sage() + + def lmfdb_page(self): + r""" + Open the LMFDB web page of the character in a browser. + + See https://www.lmfdb.org + + EXAMPLES:: + + sage: E = DirichletGroup(4).gen() + sage: E.lmfdb_page() # optional -- webbrowser + """ + import webbrowser + lmfdb_url = 'https://www.lmfdb.org/Character/Dirichlet/{}/{}' + url = lmfdb_url.format(self.modulus(), self.conrey_number()) + webbrowser.open(url) + def galois_orbit(self, sort=True): r""" Return the orbit of this character under the action of the absolute diff --git a/src/sage/modular/multiple_zeta.py b/src/sage/modular/multiple_zeta.py index 4416e70aa1f..540e29d0e50 100644 --- a/src/sage/modular/multiple_zeta.py +++ b/src/sage/modular/multiple_zeta.py @@ -151,6 +151,9 @@ .. [Deli2012] Pierre Deligne, *Multizêtas, d’après Francis Brown*, Séminaire Bourbaki, janvier 2012. http://www.bourbaki.ens.fr/TEXTES/1048.pdf +.. [Stie2020] \S. Stieberger, *Periods and Superstring Amplitudes*, + Periods in Quantum Field Theory and Arithmetic, Springer Proceedings + in Mathematics and Statistics 314, 2020 """ # **************************************************************************** # Copyright (C) 2020 Frédéric Chapoton @@ -198,7 +201,6 @@ [(17,), (7, 5, 5), (9, 3, 5), (9, 5, 3), (11, 3, 3), (5, 3, 3, 3, 3), (5, 5, 3, 2, 2)]] - Words10 = Words((1, 0), infinite=False) @@ -340,13 +342,13 @@ def dual_composition(c): def minimize_term(w, cf): """ - Return the smallest among w and the dual word of w. + Return the largest among ``w`` and the dual word of ``w``. INPUT: - - w -- a word in the letters 0 and 1 + - ``w`` -- a word in the letters 0 and 1 - - cf -- a coefficient + - ``cf`` -- a coefficient OUTPUT: @@ -361,15 +363,15 @@ def minimize_term(w, cf): sage: from sage.modular.multiple_zeta import minimize_term, Words10 sage: minimize_term(Words10((1,1,0)), 1) - (word: 110, 1) + (word: 100, -1) sage: minimize_term(Words10((1,0,0)), 1) - (word: 110, -1) + (word: 100, 1) """ reverse_w = tuple(1 - t for t in reversed(w)) for x, y in zip(w, reverse_w): - if x > y: - return (w, cf) if x < y: + return (w, cf) + if x > y: return (Words10(reverse_w), (-1)**len(w) * cf) return (w, cf) @@ -436,6 +438,8 @@ def __repr__(self): def reset(self, max_weight=8, prec=1024): r""" + Reset the cache to its default values or to given arguments. + TESTS:: sage: from sage.modular.multiple_zeta import MultizetaValues @@ -487,7 +491,7 @@ def pari_eval(self, index): index = list(reversed(index)) if weight <= self.max_weight: index = pari.zetamultconvert(index, 2) - return self._data[index - 1] + return self._data[index - 1] else: return pari.zetamult(index, precision=self.prec) @@ -520,8 +524,10 @@ def __call__(self, index, prec=None, reverse=True): else: return pari.zetamult(index, precision=prec).sage().n(prec=prec) + Values = MultizetaValues() + def basis_f_odd_iterator(n): """ Return an iterator over compositions of ``n`` with parts in ``(3,5,7,...)`` @@ -797,6 +803,8 @@ def half_product(self, w1, w2): This comes from half of the shuffle product. + .. WARNING:: This is not a motivic operation. + INPUT: - ``w1``, ``w2`` -- elements @@ -1053,7 +1061,7 @@ def simplify(self): sage: M = Multizetas(QQ) sage: z = 3*M((3,)) + 5*M((1,2)) sage: z.simplify() - 8*ζ(1,2) + 8*ζ(3) """ return self.iterated().simplify().composition() @@ -1309,6 +1317,8 @@ def half_product_on_basis(self, w1, w2): This is half of the shuffle product. + .. WARNING:: This is not a motivic operation. + INPUT: - ``w1``, ``w2`` -- monomials @@ -1319,10 +1329,11 @@ def half_product_on_basis(self, w1, w2): sage: M = Multizetas_iterated(QQ) sage: x = Word([1,0]) sage: M.half_product_on_basis(x,x) - I(1010) + 2*I(1100) + 2*I(1100) + I(1010) """ assert w1 - u1 = Word([w1[0]]) + W = self.basis().keys() + u1 = W([w1[0]]) r1 = w1[1:] return sum(self.basis()[u1 + u] for u in r1.shuffle(w2)) @@ -1333,6 +1344,8 @@ def half_product(self): This is half of the shuffle product. + .. WARNING:: This is not a motivic operation. + INPUT: - ``w1``, ``w2`` -- elements @@ -1343,7 +1356,7 @@ def half_product(self): sage: M = Multizetas_iterated(QQ) sage: x = M(Word([1,0])) sage: M.half_product(x,x) - I(1010) + 2*I(1100) + 2*I(1100) + I(1010) """ half = self.half_product_on_basis return self._module_morphism(self._module_morphism(half, position=0, @@ -1688,7 +1701,7 @@ def simplify(self): sage: M = Multizetas_iterated(QQ) sage: z = 4*M((1,0,0)) + 3*M((1,1,0)) sage: z.simplify() - -I(110) + I(100) """ summing = self.parent().sum_of_terms return summing(minimize_term(w, cf) @@ -2540,7 +2553,7 @@ def rho_inverse(elt): return M_BR.zero() a, b = next(iter(elt)) - N = sum(int(x[1]) for x in a) + 2 * b.degree() + N = sum(int(x[1:]) for x in a) + 2 * b.degree() v = f_to_vector(elt) w = v * rho_matrix_inverse(N) diff --git a/src/sage/modules/vector_integer_sparse.pxd b/src/sage/modules/vector_integer_sparse.pxd index 1cd823ee756..463b3b2c0e1 100644 --- a/src/sage/modules/vector_integer_sparse.pxd +++ b/src/sage/modules/vector_integer_sparse.pxd @@ -18,10 +18,11 @@ cdef void mpz_vector_clear(mpz_vector* v) cdef Py_ssize_t mpz_binary_search0(mpz_t* v, Py_ssize_t n, mpz_t x) cdef Py_ssize_t mpz_binary_search(mpz_t* v, Py_ssize_t n, mpz_t x, Py_ssize_t* ins) cdef int mpz_vector_get_entry(mpz_t ans, mpz_vector* v, Py_ssize_t n) except -1 +cdef bint mpz_vector_is_entry_zero_unsafe(mpz_vector* v, Py_ssize_t n) cdef object mpz_vector_to_list(mpz_vector* v) cdef int mpz_vector_set_entry(mpz_vector* v, Py_ssize_t n, mpz_t x) except -1 cdef int mpz_vector_set_entry_str(mpz_vector* v, Py_ssize_t n, char *x_str) except -1 cdef int add_mpz_vector_init(mpz_vector* sum, mpz_vector* v, mpz_vector* w, mpz_t multiple) except -1 cdef int mpz_vector_scale(mpz_vector* v, mpz_t scalar) except -1 cdef int mpz_vector_scalar_multiply(mpz_vector* v, mpz_vector* w, mpz_t scalar) except -1 -cdef int mpz_vector_cmp(mpz_vector* v, mpz_vector* w) \ No newline at end of file +cdef int mpz_vector_cmp(mpz_vector* v, mpz_vector* w) diff --git a/src/sage/modules/vector_integer_sparse.pyx b/src/sage/modules/vector_integer_sparse.pyx index 80a5b6efdee..7f94092a286 100644 --- a/src/sage/modules/vector_integer_sparse.pyx +++ b/src/sage/modules/vector_integer_sparse.pyx @@ -142,6 +142,15 @@ cdef int mpz_vector_get_entry(mpz_t ans, mpz_vector* v, Py_ssize_t n) except -1: mpz_set(ans, v.entries[m]) return 0 +cdef bint mpz_vector_is_entry_zero_unsafe(mpz_vector* v, Py_ssize_t n): + """ + Return if the ``n``-th entry of the sparse vector ``v`` is zero. + + This is meant for internal use only. If ``n`` is not valid, then + this might lead to a segfault. + """ + return binary_search0(v.positions, v.num_nonzero, n) == -1 + cdef object mpz_vector_to_list(mpz_vector* v): """ Returns a Python list of 2-tuples (i,x), where x=v[i] runs diff --git a/src/sage/modules/vector_modn_sparse.pxd b/src/sage/modules/vector_modn_sparse.pxd index 2e4e9f6ab41..41d2dd1dd43 100644 --- a/src/sage/modules/vector_modn_sparse.pxd +++ b/src/sage/modules/vector_modn_sparse.pxd @@ -13,7 +13,8 @@ cdef void clear_c_vector_modint(c_vector_modint* v) cdef Py_ssize_t binary_search0_modn(Py_ssize_t* v, Py_ssize_t n, int_fast64_t x) cdef Py_ssize_t binary_search_modn(Py_ssize_t* v, Py_ssize_t n, int_fast64_t x, Py_ssize_t* ins) cdef int_fast64_t get_entry(c_vector_modint* v, Py_ssize_t n) except -1 +cdef bint is_entry_zero_unsafe(c_vector_modint* v, Py_ssize_t n) cdef object to_list(c_vector_modint* v) cdef int set_entry(c_vector_modint* v, Py_ssize_t n, int_fast64_t x) except -1 cdef int add_c_vector_modint_init(c_vector_modint* sum, c_vector_modint* v, c_vector_modint* w, int multiple) except -1 -cdef int scale_c_vector_modint(c_vector_modint* v, int_fast64_t scalar) except -1 \ No newline at end of file +cdef int scale_c_vector_modint(c_vector_modint* v, int_fast64_t scalar) except -1 diff --git a/src/sage/modules/vector_modn_sparse.pyx b/src/sage/modules/vector_modn_sparse.pyx index 3a166786bfe..5258c9a141a 100644 --- a/src/sage/modules/vector_modn_sparse.pyx +++ b/src/sage/modules/vector_modn_sparse.pyx @@ -123,6 +123,14 @@ cdef int_fast64_t get_entry(c_vector_modint* v, Py_ssize_t n) except -1: return 0 return v.entries[m] +cdef bint is_entry_zero_unsafe(c_vector_modint* v, Py_ssize_t n): + """ + Return if the ``n``-th entry of the sparse vector ``v`` is zero. + + This is meant for internal use only. If ``n`` is not valid, then + this might lead to a segfault. + """ + return binary_search0_modn(v.positions, v.num_nonzero, n) == -1 cdef object to_list(c_vector_modint* v): """ diff --git a/src/sage/modules/vector_rational_sparse.pxd b/src/sage/modules/vector_rational_sparse.pxd index fcd8115c29f..0888a8700fe 100644 --- a/src/sage/modules/vector_rational_sparse.pxd +++ b/src/sage/modules/vector_rational_sparse.pxd @@ -19,6 +19,7 @@ cdef void mpq_vector_clear(mpq_vector* v) cdef Py_ssize_t mpq_binary_search0(mpq_t* v, Py_ssize_t n, mpq_t x) cdef Py_ssize_t mpq_binary_search(mpq_t* v, Py_ssize_t n, mpq_t x, Py_ssize_t* ins) cdef int mpq_vector_get_entry(mpq_t ans, mpq_vector* v, Py_ssize_t n) except -1 +cdef bint mpq_vector_is_entry_zero_unsafe(mpq_vector* v, Py_ssize_t n) cdef object mpq_vector_to_list(mpq_vector* v) cdef int mpq_vector_set_entry(mpq_vector* v, Py_ssize_t n, mpq_t x) except -1 cdef int mpq_vector_set_entry_str(mpq_vector* v, Py_ssize_t n, char *x_str) except -1 diff --git a/src/sage/modules/vector_rational_sparse.pyx b/src/sage/modules/vector_rational_sparse.pyx index fec595aec78..8b204b40e4f 100644 --- a/src/sage/modules/vector_rational_sparse.pyx +++ b/src/sage/modules/vector_rational_sparse.pyx @@ -149,6 +149,15 @@ cdef int mpq_vector_get_entry(mpq_t ans, mpq_vector* v, Py_ssize_t n) except -1: mpq_set(ans, v.entries[m]) return 0 +cdef bint mpq_vector_is_entry_zero_unsafe(mpq_vector* v, Py_ssize_t n): + """ + Return if the ``n``-th entry of the sparse vector ``v`` is zero. + + This is meant for internal use only. If ``n`` is not valid, then + this might lead to a segfault. + """ + return binary_search0(v.positions, v.num_nonzero, n) == -1 + cdef object mpq_vector_to_list(mpq_vector* v): """ Returns a Python list of 2-tuples (i,x), where x=v[i] runs diff --git a/src/sage/modules/with_basis/morphism.py b/src/sage/modules/with_basis/morphism.py index 2978bf1f564..435fd68ee3c 100644 --- a/src/sage/modules/with_basis/morphism.py +++ b/src/sage/modules/with_basis/morphism.py @@ -107,7 +107,7 @@ from sage.categories.fields import Fields from sage.categories.modules import Modules -from sage.misc.misc import attrcall +from sage.misc.call import attrcall # The identity function would deserve a more canonical location from sage.misc.c3_controlled import identity from sage.categories.commutative_additive_semigroups import CommutativeAdditiveSemigroups diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 43d7a17cec1..8e2c7e65430 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -3022,7 +3022,7 @@ def list_plot(data, plotjoined=False, **kwargs): "and 'y' against each other, use 'list_plot(list(zip(x,y)))'.") if isinstance(data, dict): if plotjoined: - list_data = sorted(list(data.items())) + list_data = sorted(data.items()) else: list_data = list(data.items()) return list_plot(list_data, plotjoined=plotjoined, **kwargs) diff --git a/src/sage/rings/all.py b/src/sage/rings/all.py index a2b88d0fb8c..74a74d07845 100644 --- a/src/sage/rings/all.py +++ b/src/sage/rings/all.py @@ -1,14 +1,5 @@ """ Rings - -Test for deprecations of imports into global namespace:: - - sage: convergents - doctest:warning...: - DeprecationWarning: - Importing convergents from here is deprecated. If you need to use it, please import it directly from sage.rings.continued_fraction - See https://trac.sagemath.org/27066 for details. - """ # **************************************************************************** # Copyright (C) 2005 William Stein @@ -19,7 +10,6 @@ # (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** -from __future__ import absolute_import from sage.misc.lazy_import import lazy_import # Ring base classes @@ -168,12 +158,9 @@ # continued fractions from sage.rings.continued_fraction import (continued_fraction, continued_fraction_list) -lazy_import('sage.rings.continued_fraction', 'convergents', deprecation=27066) # asymptotic ring from .asymptotic.all import * # Register classes in numbers abc from . import numbers_abc - -del absolute_import diff --git a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py index 2c2a40092f7..8b9367ea1a6 100644 --- a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +++ b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py @@ -3599,7 +3599,7 @@ def sum(self): factors.extend([q for (q, e) in f.denominator_factored()]) # Eliminate repeats from factors and sort. - factors = sorted(list(set(factors))) + factors = sorted(set(factors)) # The irreducible factors of denom lie in factors. # Use this fact to build df. diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index e69157ca181..16c9d0f252c 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -106,6 +106,7 @@ cdef RR = RealField() from .real_double cimport RealDoubleElement, double_repr from .real_double import RDF from sage.rings.integer_ring import ZZ +from sage.structure.richcmp cimport rich_to_bool cimport gmpy2 gmpy2.import_gmpy2() @@ -806,7 +807,7 @@ cdef class ComplexDoubleElement(FieldElement): """ return hash(complex(self)) - cpdef int _cmp_(left, right) except -2: + cpdef _richcmp_(left, right, int op): """ We order the complex numbers in dictionary order by real parts then imaginary parts. @@ -845,14 +846,14 @@ cdef class ComplexDoubleElement(FieldElement): False """ if left._complex.real < (right)._complex.real: - return -1 + return rich_to_bool(op, -1) if left._complex.real > (right)._complex.real: - return 1 + return rich_to_bool(op, 1) if left._complex.imag < (right)._complex.imag: - return -1 + return rich_to_bool(op, -1) if left._complex.imag > (right)._complex.imag: - return 1 - return 0 + return rich_to_bool(op, 1) + return rich_to_bool(op, 0) def __getitem__(self, n): """ diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index 920d0cd5178..30b89561070 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -1607,22 +1607,6 @@ cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): return 1 return 0 - cpdef int _cmp_(self, other) except -2: - """ - Deprecated method (:trac:`23133`) - - EXAMPLES:: - - sage: a = CIF(RIF(0,1), RIF(0,1)) - sage: a._cmp_(a) - doctest:...: DeprecationWarning: for CIF elements, do not use cmp - See http://trac.sagemath.org/23133 for details. - 0 - """ - from sage.misc.superseded import deprecation - deprecation(23133, 'for CIF elements, do not use cmp') - return self.lexico_cmp(other) - ######################################################################## # Transcendental (and other) functions ######################################################################## diff --git a/src/sage/rings/complex_number.pyx b/src/sage/rings/complex_number.pyx index 526f88d2fd5..99ba7e265ea 100644 --- a/src/sage/rings/complex_number.pyx +++ b/src/sage/rings/complex_number.pyx @@ -17,20 +17,21 @@ AUTHORS: ComplexNumber constructor support gmpy2.mpc parameter. """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2006 William Stein # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** import math import operator from sage.libs.mpfr cimport * from sage.structure.element cimport FieldElement, RingElement, Element, ModuleElement +from sage.structure.richcmp cimport rich_to_bool from sage.categories.map cimport Map from .complex_double cimport ComplexDoubleElement @@ -1167,7 +1168,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): return complex(mpfr_get_d(self.__re, rnd), mpfr_get_d(self.__im, rnd)) - cpdef int _cmp_(left, right) except -2: + cpdef _richcmp_(left, right, int op): """ Compare ``left`` and ``right``. @@ -1182,20 +1183,20 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): a = mpfr_nan_p(left.__re) b = mpfr_nan_p((right).__re) if a != b: - return -1 + return rich_to_bool(op, -1) cdef int i i = mpfr_cmp(left.__re, (right).__re) if i < 0: - return -1 + return rich_to_bool(op, -1) elif i > 0: - return 1 + return rich_to_bool(op, 1) i = mpfr_cmp(left.__im, (right).__im) if i < 0: - return -1 + return rich_to_bool(op, -1) elif i > 0: - return 1 - return 0 + return rich_to_bool(op, 1) + return rich_to_bool(op, 0) def multiplicative_order(self): """ diff --git a/src/sage/rings/factorint.pyx b/src/sage/rings/factorint.pyx index 0d8957e84d5..e46fe9b052f 100644 --- a/src/sage/rings/factorint.pyx +++ b/src/sage/rings/factorint.pyx @@ -220,9 +220,9 @@ def factor_cunningham(m, proof=None): EXAMPLES:: sage: from sage.rings.factorint import factor_cunningham - sage: factor_cunningham(2^257-1) # optional - cunningham + sage: factor_cunningham(2^257-1) # optional - cunningham_tables 535006138814359 * 1155685395246619182673033 * 374550598501810936581776630096313181393 - sage: factor_cunningham((3^101+1)*(2^60).next_prime(),proof=False) # optional - cunningham + sage: factor_cunningham((3^101+1)*(2^60).next_prime(),proof=False) # optional - cunningham_tables 2^2 * 379963 * 1152921504606847009 * 1017291527198723292208309354658785077827527 """ diff --git a/src/sage/rings/finite_rings/element_base.pyx b/src/sage/rings/finite_rings/element_base.pyx index 97d4260a183..49dbd16fa45 100755 --- a/src/sage/rings/finite_rings/element_base.pyx +++ b/src/sage/rings/finite_rings/element_base.pyx @@ -42,7 +42,7 @@ cdef class FiniteRingElement(CommutativeRingElement): sage: a = Zmod(17)(13) sage: a._nth_root_common(4, True, "Johnston", False) [3, 5, 14, 12] - sage: a._nth_root_common(4, True, "Johnston", cunningham = True) # optional - cunningham + sage: a._nth_root_common(4, True, "Johnston", cunningham = True) # optional - cunningham_tables [3, 5, 14, 12] """ K = self.parent() diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 1db7fd83e63..2a4bd5ed9a2 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -1394,7 +1394,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): Check that the code path cunningham might be used:: sage: a = Mod(9,11) - sage: a.nth_root(2, False, True, 'Johnston', cunningham = True) # optional - cunningham + sage: a.nth_root(2, False, True, 'Johnston', cunningham = True) # optional - cunningham_tables [3, 8] ALGORITHMS: diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 0ecb3b48fcc..11b39ea5c1c 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -7379,7 +7379,7 @@ def lmfdb_page(self): """ import webbrowser from urllib.parse import quote - lmfdb_url = 'https://www.lmfdb.org/NumberField/?natural={}' + lmfdb_url = 'https://www.lmfdb.org/NumberField/?jump={}' poly = self.absolute_polynomial() f = poly.parent().change_var('x')(poly) poly = pari(f).polredabs() diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 02d1fba2290..6b2c045fac2 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -1184,7 +1184,7 @@ cdef class PowerSeries(AlgebraElement): def map_coefficients(self, f, new_base_ring=None): r""" - Returns the series obtained by applying ``f`` to the non-zero + Return the series obtained by applying ``f`` to the non-zero coefficients of ``self``. If ``f`` is a :class:`sage.categories.map.Map`, then the resulting @@ -1244,6 +1244,75 @@ cdef class PowerSeries(AlgebraElement): else: return self.parent()(res, self.prec()) + def jacobi_continued_fraction(self): + r""" + Return the Jacobi continued fraction of ``self``. + + The J-fraction or Jacobi continued fraction of a power series + is a continued fraction expansion with steps of size two. We use + the following convention + + .. MATH:: + + 1 / (1 + A_0 t + B_0 t^2 / (1 + A_1 t + B_1 t^2 / (1 + \cdots))) + + OUTPUT: + + tuple of pairs `(A_n, B_n)` for `n \geq 0` + + The expansion is done as long as possible given the precision. + Whenever the expansion is not well-defined, because it would + require to divide by zero, an exception is raised. + + See section 2.7 of [Kra1999det]_ for the close relationship + of this kind of expansion with Hankel determinants and + orthogonal polynomials. + + EXAMPLES:: + + sage: t = PowerSeriesRing(QQ, 't').gen() + sage: s = sum(factorial(k) * t**k for k in range(12)).O(12) + sage: s.jacobi_continued_fraction() + ((-1, -1), (-3, -4), (-5, -9), (-7, -16), (-9, -25)) + + Another example:: + + sage: (log(1+t)/t).jacobi_continued_fraction() + ((1/2, -1/12), + (1/2, -1/15), + (1/2, -9/140), + (1/2, -4/63), + (1/2, -25/396), + (1/2, -9/143), + (1/2, -49/780), + (1/2, -16/255), + (1/2, -81/1292)) + + TESTS:: + + sage: (t).jacobi_continued_fraction() + Traceback (most recent call last): + ... + ValueError: vanishing constant term, no expansion + sage: (1/(1+3*t)).jacobi_continued_fraction() + Traceback (most recent call last): + ... + ValueError: vanishing term, no further expansion + """ + t = self.parent().gen() + if self[0] == 0: + raise ValueError('vanishing constant term, no expansion') + serie = self / self[0] + resu = [] + while serie.prec() >= 3: + u = serie.inverse() + A, B = u[1], u[2] + resu.append((A, B)) + if B == 0: + raise ValueError('vanishing term, no further expansion') + serie = (u - 1 - A * t) / (B * t ** 2) + return tuple(resu) + def is_square(self): """ Return True if this function has a square root in this ring, e.g., @@ -2285,7 +2354,7 @@ cdef class PowerSeries(AlgebraElement): def egf_to_ogf(self): r""" - Returns the ordinary generating function power series, + Return the ordinary generating function power series, assuming self is an exponential generating function power series. This function is known as ``serlaplace`` in PARI/GP. @@ -2301,7 +2370,7 @@ cdef class PowerSeries(AlgebraElement): def ogf_to_egf(self): r""" - Returns the exponential generating function power series, + Return the exponential generating function power series, assuming self is an ordinary generating function power series. This can also be computed as ``serconvol(f,exp(t))`` in PARI/GP. diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py index 6fc7cfce66a..10478af669b 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_class.py +++ b/src/sage/schemes/elliptic_curves/isogeny_class.py @@ -1287,7 +1287,8 @@ def isogeny_degrees_cm(E, verbose=False): if verbose: print("Complete set of primes: %s" % L) - return sorted(list(L)) + return sorted(L) + def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, num_l=None, exact=True, verbose=False): diff --git a/src/sage/sets/cartesian_product.py b/src/sage/sets/cartesian_product.py index 5ea1ac9ccc9..edd658daf4e 100644 --- a/src/sage/sets/cartesian_product.py +++ b/src/sage/sets/cartesian_product.py @@ -17,7 +17,7 @@ import numbers -from sage.misc.misc import attrcall +from sage.misc.call import attrcall from sage.misc.cachefunc import cached_method from sage.categories.sets_cat import Sets diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index ed9b550a0b9..98004ccecfe 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -45,7 +45,7 @@ from sage.sets.finite_enumerated_set import FiniteEnumeratedSet from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer -from sage.misc.misc import AttrCallObject +from sage.misc.call import AttrCallObject lazy_import('sage.combinat.combinat', 'CombinatorialClass') def Family(indices, function=None, hidden_keys=[], hidden_function=None, lazy=False, name=None): diff --git a/src/sage/symbolic/constants.py b/src/sage/symbolic/constants.py index 8f882893092..760be00c864 100644 --- a/src/sage/symbolic/constants.py +++ b/src/sage/symbolic/constants.py @@ -685,6 +685,9 @@ def _sympy_(self): from sage.symbolic.constants_c import E e = E() +# Allow for backtranslation to this symbol from Mathematica (#29833). +register_symbol(e, {'mathematica': 'E'}) + class NotANumber(Constant): """ Not a Number diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py index 306793d1eb2..b9734be1c7f 100644 --- a/src/sage/symbolic/integration/integral.py +++ b/src/sage/symbolic/integration/integral.py @@ -63,6 +63,14 @@ def __init__(self): sage: Ex = (1-2*x^(1/3))^(3/4)/x sage: integrate(Ex, x, algorithm="giac") # long time 4*(-2*x^(1/3) + 1)^(3/4) + 6*arctan((-2*x^(1/3) + 1)^(1/4)) - 3*log((-2*x^(1/3) + 1)^(1/4) + 1) + 3*log(abs((-2*x^(1/3) + 1)^(1/4) - 1)) + + Check for :trac:`29833`:: + + sage: (x,a,b)=var('x a b') + sage: assume(b > 0) + sage: f = (exp((x-a)/b) + 1)**(-1) + sage: (f*f).integrate(x, algorithm="mathematica_free") # optional -- internet + -b*log(e^(-(a - x)/b) + 1) + x + b/(e^(-(a - x)/b) + 1) """ # The automatic evaluation routine will try these integrators # in the given order. This is an attribute of the class instead of @@ -939,6 +947,11 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): sage: (g.derivative() - f).full_simplify().full_simplify() 0 + + Test for :trac:`24117`:: + + sage: integrate(sqrt(1-4*sin(x)^2),x, algorithm='maxima') + integrate(sqrt(-4*sin(x)^2 + 1), x) """ expression, v, a, b = _normalize_integral_input(expression, v, a, b) if algorithm is not None: diff --git a/src/sage/tests/arxiv_0812_2725.py b/src/sage/tests/arxiv_0812_2725.py index db34c1db51e..a19795b9d6c 100644 --- a/src/sage/tests/arxiv_0812_2725.py +++ b/src/sage/tests/arxiv_0812_2725.py @@ -33,7 +33,7 @@ # the Free Software Foundation, either version 2 of the License, or (at # your option) any later version. # -# See http://www.gnu.org/licenses/. +# See https://www.gnu.org/licenses/. #***************************************************************************** from sage.combinat.set_partition import SetPartitions as SetPartitions @@ -204,7 +204,7 @@ def setp_to_edges(p): sage: sorted(setp_to_edges(Set(map(Set, [[1,5],[2,4,9],[3],[6,12],[7,10,11],[8]])))) [[1, 5], [2, 4], [4, 9], [6, 12], [7, 10], [10, 11]] """ - q = [sorted(list(b)) for b in p] + q = [sorted(b) for b in p] ans = [] for b in q: for n in range(len(b) - 1): diff --git a/src/sage/tests/finite_poset.py b/src/sage/tests/finite_poset.py index fca907d8681..edd651d501d 100644 --- a/src/sage/tests/finite_poset.py +++ b/src/sage/tests/finite_poset.py @@ -8,7 +8,7 @@ """ from sage.misc.prandom import randint -from sage.misc.misc import attrcall +from sage.misc.call import attrcall from functools import reduce implications = { @@ -156,7 +156,7 @@ def test_finite_lattice(L): from sage.misc.prandom import randint from sage.misc.flatten import flatten - from sage.misc.misc import attrcall + from sage.misc.call import attrcall from sage.misc.sageinspect import sage_getargspec @@ -460,7 +460,7 @@ def test_finite_poset(P): from sage.combinat.subset import Subsets from sage.misc.prandom import shuffle - from sage.misc.misc import attrcall + from sage.misc.call import attrcall e = P.random_element() P_one_less = P.subposet([x for x in P if x != e]) diff --git a/src/sage/version.py b/src/sage/version.py index 35eeafc5bf7..aa41d91aa87 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '9.2.beta2' -date = '2020-06-26' -banner = 'SageMath version 9.2.beta2, Release Date: 2020-06-26' +version = '9.2.beta3' +date = '2020-07-04' +banner = 'SageMath version 9.2.beta3, Release Date: 2020-07-04' diff --git a/src/sage_setup/autogen/interpreters/specs/cdf.py b/src/sage_setup/autogen/interpreters/specs/cdf.py index 4bf20c84557..1921c807c80 100644 --- a/src/sage_setup/autogen/interpreters/specs/cdf.py +++ b/src/sage_setup/autogen/interpreters/specs/cdf.py @@ -161,9 +161,6 @@ def __init__(self): import sage.rings.complex_double cdef object CDF = sage.rings.complex_double.CDF - cdef extern from "solaris_fixes.h": - pass - cdef extern from "complex.h": cdef double creal(double_complex) cdef double cimag(double_complex) diff --git a/src/sage_setup/command/sage_build_cython.py b/src/sage_setup/command/sage_build_cython.py index b177f1a8aac..413e727f268 100644 --- a/src/sage_setup/command/sage_build_cython.py +++ b/src/sage_setup/command/sage_build_cython.py @@ -271,8 +271,6 @@ def create_extension(self, template, kwds): - Add dependencies on header files for certain libraries - - Ensure that C++ extensions link with -lstdc++ - - Sort the libraries according to the library order - Add some default compile/link args and directories @@ -286,10 +284,8 @@ def create_extension(self, template, kwds): lang = kwds.get('language', 'c') cplusplus = (lang == "c++") - # Libraries: add stdc++ if needed and sort them + # Libraries: sort them libs = kwds.get('libraries', []) - if cplusplus: - libs = libs + ['stdc++'] kwds['libraries'] = sorted(set(libs), key=lambda lib: library_order.get(lib, 0)) diff --git a/src/sage_setup/library_order.py b/src/sage_setup/library_order.py index e0864995daa..c7bf73cb8c9 100644 --- a/src/sage_setup/library_order.py +++ b/src/sage_setup/library_order.py @@ -72,8 +72,7 @@ # manually reorder the libraries according to this list. The order is # important in particular for Cygwin. Any libraries which are not # listed here will be added at the end of the list (without changing -# their relative order). There is one exception: stdc++ is always put -# at the very end of the list. +# their relative order). from sage.env import cython_aliases aliases = cython_aliases() @@ -101,5 +100,3 @@ for i in range(n): lib = library_order_list[i] library_order[lib] = i-n - -library_order["stdc++"] = 1000 diff --git a/tox.ini b/tox.ini index dca633fb504..58bef71ae9a 100644 --- a/tox.ini +++ b/tox.ini @@ -191,6 +191,11 @@ setenv = centos-7: BASE_TAG=centos7 centos-8: BASE_TAG=centos8 # + # https://hub.docker.com/r/sheerluck/sage-on-gentoo-stage4/tags + # + gentoo: SYSTEM=gentoo + gentoo: BASE_IMAGE=sheerluck/sage-on-gentoo-stage4 + # # https://hub.docker.com/_/archlinux/ # archlinux: SYSTEM=arch