diff --git a/.gitignore b/.gitignore index 7808c3bbd61..5edef4a5619 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,9 @@ .\#* # Vim -*.s[a-w][a-z] +*.swp +*.swo +*.swn *.un~ .netrwhist diff --git a/Makefile b/Makefile index 254c36cb359..2e8ef6efb73 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,13 @@ doc: doc-html doc-html: build $(PIPE) "./sage --docbuild --no-pdf-links all html $(SAGE_DOCBUILD_OPTS) 2>&1" "tee -a logs/dochtml.log" +# 'doc-html-no-plot': build docs without building the graphics coming +# from the '.. plot' directive, in case you want to save a few +# megabytes of disk space. 'doc-clean' is a prerequisite because the +# presence of graphics is cached in src/doc/output. +doc-html-no-plot: build doc-clean + $(PIPE) "./sage --docbuild --no-pdf-links --no-plot all html $(SAGE_DOCBUILD_OPTS) 2>&1" "tee -a logs/dochtml.log" + doc-html-mathjax: build $(PIPE) "./sage --docbuild --no-pdf-links all html -j $(SAGE_DOCBUILD_OPTS) 2>&1" "tee -a logs/dochtml.log" diff --git a/VERSION.txt b/VERSION.txt index 0732fd26623..8cffa2607a9 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -Sage version 6.5.beta6, released 2015-01-24 +Sage version 6.6.beta0, released 2015-02-18 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 59a8aa369d0..dd0594bcee2 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=99eab7d6d7eabfb85e3efe2ce4b2096c836681ce -md5=9823a583c3663035cdb47fdb6f334173 -cksum=2606347674 +sha1=fc6a6e09db9e9ef7877296947cfcc0929b6d08bf +md5=ca43ab046439d42063bf4af39baecb18 +cksum=3453818239 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 900731ffd51..2bbd69c2e54 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -64 +70 diff --git a/build/pkgs/cython/checksums.ini b/build/pkgs/cython/checksums.ini index f23c4ef1cdd..1b08a8dbcc1 100644 --- a/build/pkgs/cython/checksums.ini +++ b/build/pkgs/cython/checksums.ini @@ -1,4 +1,4 @@ -tarball=cython-VERSION.tar.gz -sha1=02c6f25025923e5a5647e7876670a4cc7759371e -md5=c59163d7c72c0a0ee5eb84edd17935ed -cksum=3555036300 +tarball=cython-VERSION.tar.bz2 +sha1=89cf4f3d9a840e593da066a9f723b31a27d7c6a6 +md5=6fe7c9d93970ce602d60defd903188d8 +cksum=1851959595 diff --git a/build/pkgs/cython/package-version.txt b/build/pkgs/cython/package-version.txt index a67cebaf7ff..e3462940604 100644 --- a/build/pkgs/cython/package-version.txt +++ b/build/pkgs/cython/package-version.txt @@ -1 +1 @@ -0.21.1 +0.22 diff --git a/build/pkgs/gdb/patches/yosemite-setjmp.patch b/build/pkgs/gdb/patches/yosemite-setjmp.patch new file mode 100644 index 00000000000..c36ae80585c --- /dev/null +++ b/build/pkgs/gdb/patches/yosemite-setjmp.patch @@ -0,0 +1,13 @@ +Patch for building on OSX 10.10 taken from https://trac.macports.org/ticket/43973 + +--- gdb-7.7.1/gdb/darwin-nat.c.orig 2014-06-15 10:49:39.000000000 -0700 ++++ gdb-7.7.1/gdb/darwin-nat.c 2014-06-15 10:51:23.000000000 -0700 +@@ -42,7 +42,7 @@ + + #include + #include +-#include ++#include + #include + #include + #include diff --git a/build/pkgs/gdb/spkg-install b/build/pkgs/gdb/spkg-install index 01f8c15d332..d874fb79809 100755 --- a/build/pkgs/gdb/spkg-install +++ b/build/pkgs/gdb/spkg-install @@ -8,6 +8,16 @@ fi cd src +# Apply patches. +for patch in ../patches/*.patch; do + [ -r "$patch" ] || continue # Skip non-existing or non-readable patches + patch -p1 <"$patch" + if [ $? -ne 0 ]; then + echo >&2 "Error applying '$patch'" + exit 1 + fi +done + LDFLAGS="${LDFLAGS} -L${SAGE_LOCAL}/lib" export LDFLAGS diff --git a/build/pkgs/jmol/checksums.ini b/build/pkgs/jmol/checksums.ini index 5897f089a2b..db8d0c00392 100644 --- a/build/pkgs/jmol/checksums.ini +++ b/build/pkgs/jmol/checksums.ini @@ -1,4 +1,4 @@ tarball=jmol-VERSION.tar.bz2 -sha1=0496d92d75efb91c2b332f59be48c0ee6a12a314 -md5=acc6c39a4b7787f53657310e9252fbf9 -cksum=389669432 +sha1=3def57106c750286af364cbbf040ed7e568b866e +md5=8664c2b5c109c7dadcfcce9d4e30770b +cksum=211082989 diff --git a/build/pkgs/jmol/package-version.txt b/build/pkgs/jmol/package-version.txt index 886082647dc..d7d3ea76361 100644 --- a/build/pkgs/jmol/package-version.txt +++ b/build/pkgs/jmol/package-version.txt @@ -1 +1 @@ -14.2.4_2014.08.03 +14.2.11_2015.01.20 diff --git a/build/pkgs/maxima/package-version.txt b/build/pkgs/maxima/package-version.txt index fe820f1c0b5..85cd25266aa 100644 --- a/build/pkgs/maxima/package-version.txt +++ b/build/pkgs/maxima/package-version.txt @@ -1 +1 @@ -5.35.1.p1 +5.35.1.p2 diff --git a/build/pkgs/maxima/patches/stdin-illegal-seek.patch b/build/pkgs/maxima/patches/stdin-illegal-seek.patch new file mode 100644 index 00000000000..74a45aa4e31 --- /dev/null +++ b/build/pkgs/maxima/patches/stdin-illegal-seek.patch @@ -0,0 +1,32 @@ +#17667: Maxima parser fails on == + +There is no == operator in Maxima, but on invalid input it does bad +things to the C-level stream. On Linux (below) this is caught by +gilbc, on OSX the Maxima process hangs indefinitely. + +Patch taken from the upstream repo: + +commit f7c388a0f030b2701ac982ea66cce61ce8002bf8 +tree 948ebe84ce56a76090e2b86403b18d7bc262e67c +parent a57b4323587f6f4c1115a51915cfb096f4d820c2 +author Andrej Vodopivec 1423041512 +0100 +committer Andrej Vodopivec 1423041512 +0100 + + mread-synerr: don't report line/column for errors from user input. + +diff -ru src/src/nparse.lisp b/src/nparse.lisp +--- src/src/nparse.lisp 2014-11-19 06:00:09.000000000 +0100 ++++ b/src/nparse.lisp 2015-02-13 10:12:49.107785016 +0100 +@@ -37,8 +37,10 @@ + (defmvar $report_synerr_info t "If T, report the syntax error details from all sources; otherwise, only report details from standard-input.") + + (defun mread-synerr (format-string &rest l) +- (let ((fp (file-position *parse-stream*)) +- (file (cadr *current-line-info*))) ++ (let ((fp (and (not (eq *parse-stream* *standard-input*)) ++ (file-position *parse-stream*))) ++ (file (and (not (eq *parse-stream* *standard-input*)) ++ (cadr *current-line-info*)))) + (flet ((line-number () + ;; Fix me: Neither batch nor load track the line number + ;; correctly. batch, via dbm-read, does not track the diff --git a/build/pkgs/openssl/SPKG.txt b/build/pkgs/openssl/SPKG.txt index c2cb3baf813..0711b536f7b 100644 --- a/build/pkgs/openssl/SPKG.txt +++ b/build/pkgs/openssl/SPKG.txt @@ -12,13 +12,10 @@ library in a variety of computer languages are available. * Custom GPL-incompatible license -== Maintainers == - - * William Stein - == Upstream Contact == - * None yet + * http://openssl.org/ + * http://openssl.org/support/community.html === Patches === diff --git a/build/pkgs/openssl/checksums.ini b/build/pkgs/openssl/checksums.ini index 7ab811e3d70..e730dab4158 100644 --- a/build/pkgs/openssl/checksums.ini +++ b/build/pkgs/openssl/checksums.ini @@ -1,4 +1,4 @@ tarball=openssl-VERSION.tar.gz -sha1=cff86857507624f0ad42d922bb6f77c4f1c2b819 -md5=f7175c9cd3c39bb1907ac8bba9df8ed3 -cksum=490651201 +sha1=2f264f7f6bb973af444cd9fc6ee65c8588f610cc +md5=38373013fc85c790aabf8837969c5eba +cksum=3003646357 diff --git a/build/pkgs/openssl/package-version.txt b/build/pkgs/openssl/package-version.txt index 9753fcecf96..6d7de6e6abe 100644 --- a/build/pkgs/openssl/package-version.txt +++ b/build/pkgs/openssl/package-version.txt @@ -1 +1 @@ -1.0.1j +1.0.2 diff --git a/build/pkgs/pari/package-version.txt b/build/pkgs/pari/package-version.txt index 62660d0a34f..f703d460ddd 100644 --- a/build/pkgs/pari/package-version.txt +++ b/build/pkgs/pari/package-version.txt @@ -1 +1 @@ -2.7.1.p1 +2.7.1.p3 diff --git a/build/pkgs/pari/patches/cb_pari_err_handle.patch b/build/pkgs/pari/patches/cb_pari_err_handle.patch new file mode 100644 index 00000000000..b8dbee738a6 --- /dev/null +++ b/build/pkgs/pari/patches/cb_pari_err_handle.patch @@ -0,0 +1,105 @@ +Add cb_pari_err_handle() callback + +Backported from upstream commits +e9e659dc9ecb5ca6a8296c7922528a4ecbb89cb0 +26a7ae0f42918407febe9901ded41faf26ef43a6 + +diff -ru src/src/headers/paricom.h b/src/headers/paricom.h +--- src/src/headers/paricom.h 2014-03-25 09:59:21.000000000 +0100 ++++ b/src/headers/paricom.h 2015-01-13 19:41:47.430885048 +0100 +@@ -81,6 +81,7 @@ + extern int (*cb_pari_whatnow)(PariOUT *out, const char *, int); + extern void (*cb_pari_sigint)(void); + extern int (*cb_pari_handle_exception)(long); ++extern int (*cb_pari_err_handle)(GEN); + extern void (*cb_pari_pre_recover)(long); + extern void (*cb_pari_err_recover)(long); + extern const char *pari_library_path; +diff -ru src/src/language/init.c b/src/language/init.c +--- src/src/language/init.c 2015-01-13 19:40:30.643622993 +0100 ++++ b/src/language/init.c 2015-01-13 19:41:47.431884833 +0100 +@@ -87,6 +87,7 @@ + + void (*cb_pari_ask_confirm)(const char *); + int (*cb_pari_handle_exception)(long); ++int (*cb_pari_err_handle)(GEN); + int (*cb_pari_whatnow)(PariOUT *out, const char *, int); + void (*cb_pari_sigint)(void); + void (*cb_pari_pre_recover)(long); +@@ -732,6 +733,8 @@ + static void + dflt_err_recover(long errnum) { (void) errnum; pari_exit(); } + ++static int pari_err_display(GEN err); ++ + /* initialize PARI data. Initialize [new|old]fun to NULL for default set. */ + void + pari_init_opts(size_t parisize, ulong maxprime, ulong init_opts) +@@ -739,6 +742,8 @@ + ulong u; + + cb_pari_whatnow = NULL; ++ cb_pari_handle_exception = NULL; ++ cb_pari_err_handle = pari_err_display; + cb_pari_pre_recover = NULL; + cb_pari_sigint = dflt_sigint_fun; + if (init_opts&INIT_JMPm) cb_pari_err_recover = dflt_err_recover; +@@ -887,9 +892,6 @@ + evalstate_reset(); + killallfiles(); + pari_init_errcatch(); +- out_puts(pariErr, "\n"); +- pariErr->flush(); +- + cb_pari_err_recover(numerr); + } + +@@ -1266,21 +1268,22 @@ + return NULL; /*NOT REACHED*/ + } + +-static void ++static int + pari_err_display(GEN err) + { + long numerr=err_get_num(err); ++ err_init(); + if (numerr==e_SYNTAX) + { + const char *msg = GSTR(gel(err,2)); + const char *s = (const char *) gmael(err,3,1); + const char *entry = (const char *) gmael(err,3,2); + print_errcontext(pariErr, msg, s, entry); +- return; + } + else + { + char *s = pari_err2str(err); ++ closure_err(0); + err_init_msg(numerr, e_USER); + pariErr->puts(s); + if (numerr==e_NOTFUNC) +@@ -1295,6 +1298,8 @@ + } + pari_free(s); + } ++ out_term_color(pariErr, c_NONE); ++ pariErr->flush(); return 0; + } + + void +@@ -1315,12 +1320,9 @@ + global_err_data = E; + if (*iferr_env) longjmp(*iferr_env, numerr); + mt_err_recover(numerr); +- err_init(); +- if (numerr != e_SYNTAX) closure_err(0); +- pari_err_display(E); +- out_term_color(pariErr, c_NONE); + va_end(ap); +- pariErr->flush(); ++ if (cb_pari_err_handle && ++ cb_pari_err_handle(E)) return; + if (cb_pari_handle_exception && + cb_pari_handle_exception(numerr)) return; + err_recover(numerr); diff --git a/build/pkgs/pari/spkg-install b/build/pkgs/pari/spkg-install index fce58d3fb1a..67ccc8262a9 100755 --- a/build/pkgs/pari/spkg-install +++ b/build/pkgs/pari/spkg-install @@ -187,27 +187,15 @@ install() exit 1 fi - cd "$CUR" - - if [ "$UNAME" = "Darwin" ]; then - # The following is a hack to get the library installed correctly - # on Mac OS X: - echo "Applying Mac OS X hack -- deleting and reinstalling libpari.a ..." - rm -f Odarwin-ppc/*lib* - $MAKE install-lib-sta - if [ $? -ne 0 ]; then - echo >&2 "Error reinstalling PARI's static libraries (OS X trick)" - exit 1 - fi - - cd "`config/objdir`" && cp -f libpari* "$SAGE_LOCAL/lib" - if [ $? -ne 0 ]; then - echo >&2 "Error copying PARI's libraries (OS X trick)" - exit 1 - fi - cd "$CUR" + # Copy anal.h + cp -f "src/language/anal.h" "$SAGE_LOCAL/include/pari/anal.h" + if [ $? -ne 0 ]; then + echo >&2 "Error copying anal.h" + exit 1 fi + cd "$CUR" + # Copy gprc.expect to $SAGE_LOCAL/etc cp -f "$TOP/gprc.expect" "$SAGE_LOCAL/etc" if [ $? -ne 0 ]; then diff --git a/build/pkgs/sagenb/checksums.ini b/build/pkgs/sagenb/checksums.ini index 1d3873556e0..f35bb1b9033 100644 --- a/build/pkgs/sagenb/checksums.ini +++ b/build/pkgs/sagenb/checksums.ini @@ -1,4 +1,4 @@ tarball=sagenb-VERSION.tar -sha1=c9426b9a7a2827f30cc78d7d6968c45318d75bc9 -md5=5df4791218cbad45970b0a7ab0be533b -cksum=1503702642 +sha1=66593ecf18cbf77115279f6f1564854eb9b93df5 +md5=facdc06b94fcf0a85b76aa861c6e646f +cksum=2719820378 diff --git a/build/pkgs/sagenb/package-version.txt b/build/pkgs/sagenb/package-version.txt index bc859cbd6d9..35ad34429be 100644 --- a/build/pkgs/sagenb/package-version.txt +++ b/build/pkgs/sagenb/package-version.txt @@ -1 +1 @@ -0.11.2 +0.11.4 diff --git a/src/bin/math-readline b/src/bin/math-readline new file mode 100755 index 00000000000..49a58a1c363 --- /dev/null +++ b/src/bin/math-readline @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +# Cleverly run Mathematica with the benefit of readline, which +# is something the usual commercial mathematica doesn't provide! +# See +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/363500 + +import os, sys +f1 = os.popen('math ', 'w') +f1.flush() +try: + while True: + sys.stdout.write('') + try: + line = raw_input() + f1.writelines(line+'\n') + f1.flush() + except KeyboardInterrupt: + f1.close() + break +except EOFError: + pass +sys.stdout.write('\n') +sys.exit() diff --git a/src/bin/sage b/src/bin/sage index 2452a092c14..d7bf7354dbc 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -632,15 +632,14 @@ build_sage() { sage-build "$@" || exit $? } -if [[ "$1" =~ "--notebook="* || "$1" =~ "-n="* || "$1" =~ "-notebook="* ]]; then +if [[ "$1" =~ ^--notebook=.* || "$1" =~ ^-n=.* || "$1" =~ ^-notebook=.* ]] ; then sage-cleaner &>/dev/null & exec sage-notebook "$@" fi if [ "$1" = "-notebook" -o "$1" = '--notebook' -o "$1" = '-n' ]; then - shift sage-cleaner &>/dev/null & - exec sage-notebook --notebook=default "$@" + exec sage-notebook "$@" fi if [ "$1" = "-bn" -o "$1" = "--build-and-notebook" ]; then diff --git a/src/bin/sage-banner b/src/bin/sage-banner index 7d41bea77d1..5f46b3af2fd 100644 --- a/src/bin/sage-banner +++ b/src/bin/sage-banner @@ -1,5 +1,5 @@ ┌────────────────────────────────────────────────────────────────────┐ -│ Sage Version 6.5.beta6, Release Date: 2015-01-24 │ +│ Sage Version 6.6.beta0, Release Date: 2015-02-18 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ diff --git a/src/bin/sage-rst2sws b/src/bin/sage-rst2sws index 33e77217a12..8dd57180eb2 100755 --- a/src/bin/sage-rst2sws +++ b/src/bin/sage-rst2sws @@ -129,7 +129,7 @@ worksheet_txt = translator.process_doc_html(html) # create a Notebook object from sagenb.notebook.notebook import Notebook -from sage.misc.misc import tmp_dir +from sage.misc.all import tmp_dir nb = Notebook(tmp_dir()+'.sagenb') nb.user_manager().create_default_users('password') diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 24a4d7d336a..ff9bbcbce2a 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,4 +1,4 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='6.5.beta6' -SAGE_RELEASE_DATE='2015-01-24' +SAGE_VERSION='6.6.beta0' +SAGE_RELEASE_DATE='2015-02-18' diff --git a/src/doc/common/builder.py b/src/doc/common/builder.py index c817d8624c0..d6373aa2c7a 100644 --- a/src/doc/common/builder.py +++ b/src/doc/common/builder.py @@ -1302,7 +1302,7 @@ def get_formats(): tut_b = DocBuilder('en/tutorial') formats = tut_b._output_formats() formats.remove('html') - return ['html', 'pdf'] + formats + return ['html', 'html-no-pix', 'pdf'] + formats def help_formats(s=u""): """ @@ -1444,6 +1444,9 @@ def setup_parser(): standard.add_option("-j", "--mathjax", "--jsmath", dest="mathjax", action="store_true", help="render math using MathJax; FORMATs: html, json, pickle, web") + standard.add_option("--no-plot", dest="no_plot", + action="store_true", + help="do not include graphics auto-generated using the '.. plot' markup") standard.add_option("--no-pdf-links", dest="no_pdf_links", action="store_true", help="do not include PDF links in DOCUMENT 'website'; FORMATs: html, json, pickle, web") @@ -1602,6 +1605,8 @@ def fetch_inventory(self, app, uri, inv): WEBSITESPHINXOPTS = " -A hide_pdf_links=1 " if options.warn_links: ALLSPHINXOPTS += "-n " + if options.no_plot: + os.environ['SAGE_SKIP_PLOT_DIRECTIVE'] = 'yes' ABORT_ON_ERROR = not options.keep_going diff --git a/src/doc/common/conf.py b/src/doc/common/conf.py index cacecef5eed..ae46f55dce0 100644 --- a/src/doc/common/conf.py +++ b/src/doc/common/conf.py @@ -21,7 +21,31 @@ def get_doc_abspath(path): extensions = ['inventory_builder', 'multidocs', 'sage_autodoc', 'sphinx.ext.graphviz', 'sphinx.ext.inheritance_diagram', 'sphinx.ext.todo', - 'sphinx.ext.extlinks'] + 'sphinx.ext.extlinks', 'matplotlib.sphinxext.plot_directive'] + +# This code is executed before each ".. PLOT::" directive in the Sphinx +# documentation. It defines a 'sphinx_plot' function that displays a Sage object +# through mathplotlib, so that it will be displayed in the HTML doc +plot_html_show_source_link = False +plot_pre_code = """ +def sphinx_plot(plot): + import matplotlib.image as mpimg + from sage.misc.temporary_file import tmp_filename + import matplotlib.pyplot as plt + if os.environ.get('SAGE_SKIP_PLOT_DIRECTIVE', 'no') != 'yes': + fn = tmp_filename(ext=".png") + plot.plot().save(fn) + img = mpimg.imread(fn) + plt.imshow(img) + plt.margins(0) + plt.axis("off") + plt.tight_layout(pad=0) + +from sage.all_cmdline import * +""" + +plot_html_show_formats = False + # We do *not* fully initialize intersphinx since we call it by hand # in find_sage_dangling_links. #, 'sphinx.ext.intersphinx'] diff --git a/src/doc/de/tutorial/programming.rst b/src/doc/de/tutorial/programming.rst index c6fe615eb5a..ab8dd1a7009 100644 --- a/src/doc/de/tutorial/programming.rst +++ b/src/doc/de/tutorial/programming.rst @@ -547,11 +547,11 @@ nichtnegativen ganzen Zahlen bis :math:`10000000`. :: sage: v = (n^2 for n in xrange(10000000)) - sage: v.next() + sage: next(v) 0 - sage: v.next() + sage: next(v) 1 - sage: v.next() + sage: next(v) 4 Nun erzeugen wir einen Iterator über den Primzahlen der Form :math:`4p+1` @@ -562,11 +562,11 @@ wobei auch :math:`p` prim ist und schauen uns die ersten Werte an. sage: w = (4*p + 1 for p in Primes() if is_prime(4*p+1)) sage: w # in the next line, 0xb0853d6c is a random 0x number - sage: w.next() + sage: next(w) 13 - sage: w.next() + sage: next(w) 29 - sage: w.next() + sage: next(w) 53 Bestimmte Ringe, z. B. endliche Körper und die ganzen Zahlen, haben @@ -578,11 +578,11 @@ zugehörige Iteratoren: sage: [x for x in GF(7)] [0, 1, 2, 3, 4, 5, 6] sage: W = ((x,y) for x in ZZ for y in ZZ) - sage: W.next() + sage: next(W) (0, 0) - sage: W.next() + sage: next(W) (0, 1) - sage: W.next() + sage: next(W) (0, -1) Schleifen, Funktionen, Kontrollstrukturen und Vergleiche diff --git a/src/doc/en/developer/coding_basics.rst b/src/doc/en/developer/coding_basics.rst index 4b296124d02..9373e17f3b6 100644 --- a/src/doc/en/developer/coding_basics.rst +++ b/src/doc/en/developer/coding_basics.rst @@ -341,6 +341,16 @@ information. You can use the existing functions of Sage as templates. sage: have_fresh_beers('Bière de l\'Yvette', algorithm="BaBF") # not implemented Enjoy ! +- A **PLOT** block to illustrate with pictures the output of a function. + + Generate with Sage code an object ``g`` with a ``.plot`` method, then call + ``sphinx_plot(g)``:: + + .. PLOT:: + + g = graphs.PetersenGraph() + sphinx_plot(g) + - A **REFERENCES** block to list related books or papers (optional) It should cite the books/research papers relevant to the code, e.g. the source diff --git a/src/doc/en/developer/doctesting.rst b/src/doc/en/developer/doctesting.rst index c5dd7d5a079..60ae52a4dd1 100644 --- a/src/doc/en/developer/doctesting.rst +++ b/src/doc/en/developer/doctesting.rst @@ -150,7 +150,7 @@ Sage installation (if it exists): sage -t "src/sage/games/sudoku.py" ********************************************************************** File "/home/jdemeyer/sage/sage-6.0/src/sage/games/sudoku.py", line 515: - sage: h.solve(algorithm='backtrack').next() + sage: next(h.solve(algorithm='backtrack')) Exception raised: Traceback (most recent call last): File "/usr/local/sage/local/bin/ncadoctest.py", line 1231, in run_one_test @@ -160,8 +160,8 @@ Sage installation (if it exists): File "/usr/local/sage/local/bin/ncadoctest.py", line 1172, in run_one_example compileflags, 1) in test.globs File "", line 1, in - h.solve(algorithm='backtrack').next()###line 515: - sage: h.solve(algorithm='backtrack').next() + next(h.solve(algorithm='backtrack'))###line 515: + sage: next(h.solve(algorithm='backtrack')) File "/home/jdemeyer/.sage/tmp/sudoku.py", line 607, in solve for soln in gen: File "/home/jdemeyer/.sage/tmp/sudoku.py", line 719, in backtrack diff --git a/src/doc/en/developer/sage_manuals.rst b/src/doc/en/developer/sage_manuals.rst index d4742d6b8e1..a2e8af7f11e 100644 --- a/src/doc/en/developer/sage_manuals.rst +++ b/src/doc/en/developer/sage_manuals.rst @@ -4,329 +4,165 @@ The Sage Manuals ================ -This chapter describes how to modify the Sage manuals. Sage's manuals -are written in ReST, otherwise known as `reStructuredText`__. To edit -them, you just need to edit the appropriate file. The documentation -builder is called `Sphinx`__. +Sage's manuals are written in `ReST `_ +(reStructuredText), and generated with the software `Sphinx +`_: -__ http://docutils.sourceforge.net/rst.html +.. list-table:: + :widths: 4 12 + :header-rows: 1 -__ http://sphinx.pocoo.org + * - Name + - Files -Here is a list of the Sage manuals and the corresponding files to edit: + * - `Tutorial <../tutorial/index.html>`_ + - ``SAGE_ROOT/src/doc/en/tutorial`` -- The Sage tutorial: ``SAGE_ROOT/src/doc/en/tutorial`` + * - `Developer's guide <../developer/index.html>`_ + - ``SAGE_ROOT/src/doc/en/developer`` -- The Sage developer's guide: - ``SAGE_ROOT/src/doc/en/developer`` + * - `Constructions <../constructions/index.html>`_ + - ``SAGE_ROOT/src/doc/en/constructions`` -- Constructions in Sage: - ``SAGE_ROOT/src/doc/en/constructions`` + * - `Installation guide <../installation/index.html>`_ + - ``SAGE_ROOT/src/doc/en/installation`` -- The Sage installation guide: - ``SAGE_ROOT/src/doc/en/installation`` + * - `Reference manual <../reference/index.html>`_ + - ``SAGE_ROOT/src/doc/en/reference`` + (most of it is generated from the + source code) -- The Sage reference manual: some of this is contained in the file - ``SAGE_ROOT/src/doc/en/reference``, but most of it is - automatically generated from the Sage source code. +- Additionally, more specialized manuals can be found under + ``SAGE_ROOT/src/doc/en``. -- Additional, more specialized manuals can be found under - ``SAGE_ROOT/src/doc/en`` as well. +- Some documents have been **translated** into other languages. In order to + access them, change en/ into fr/,es/, de/... See :ref:`section-manuals-names`. -.. note:: +.. _section-manuals-edit: - You can edit manuals that have been translated into another language - by replacing the ``en/`` above with the appropriate two letter - language code. For example, the French tutorial is located in - ``SAGE_ROOT/src/doc/fr/tutorial`` +Editing the documentation +========================= +(*Do you want to convert a Sage worksheet into documentation?* `Click here +<../thematic_tutorials/sws2rst.html>`_) -Building the Manuals -==================== - -If, for example, you want to change the Sage tutorial, then you should -start by modifying the files in -``SAGE_ROOT/src/doc/en/tutorial/``. Then to build a PDF file -with your changes, type:: - - sage --docbuild tutorial pdf - -You will get a file ``tutorial.pdf`` in -``SAGE_ROOT/src/doc/output/pdf/en/tutorial`` which you should -inspect. You can build the HTML version of the tutorial by typing:: +After modifying some files in the Sage tutorial +(``SAGE_ROOT/src/doc/en/tutorial/``), you will want to visualize the result. In +order to build a **html** version of this document, type:: sage --docbuild tutorial html -Once you have done this, you can access the new HTML version from the -notebook interface to Sage by clicking the ``Help`` link, or you can -open the file -``SAGE_ROOT/src/doc/output/html/en/tutorial/index.html`` in -your web browser. For more detailed information about building the -documentation, see :ref:`section-building-manuals`. - -You should also run:: +You can now open ``SAGE_ROOT/src/doc/output/html/en/tutorial/index.html`` in +your web browser. - sage -tp SAGE_ROOT/src/doc/en/tutorial/ +- Do you want to **add a new file** to the documentation? :ref:`Click here + `. -to test all of the examples in the tutorial, see -:ref:`chapter-testing` for more details. +- For more detailed information on the ``--docbuild`` command, see + :ref:`section-building-manuals`. -As noted above, the reference manual is mostly autogenerated from Sage -source code. To build it, type:: +**Run doctests:** All files must pass tests. After modifying a document +(e.g. ``tutorial``), you can run tests with the following command (see +:ref:`chapter-testing`):: - sage -b - sage --docbuild reference + sage -tp SAGE_ROOT/src/doc/en/tutorial/ -where ```` is the name of the repository you are using, and -```` is ``html``, ``pdf``, or any other supported format (as listed -when you run ``sage --docbuild --formats``). +**Reference manual:** as this manual is mostly generated from Sage's source +code, you will need to build Sage in order to see the changes you made to some +function's documentation. Type:: + sage -b && sage --docbuild reference html .. _chapter-sage_manuals_links: Hyperlinks ========== -You can link to doctstings of modules, classes, methods. In addition, -you can link web pages like trac tickets and Wikipedia. For full -documentation, refer to `inline markup`__ in the Sphinx -documentation. Currently, there is no support for defining chapters -and labels in the autogenerated documentation. However, it is possible -to generate a link to the documentation for any module, class, method, -function, etc. The syntax is - -__ http://sphinx.pocoo.org/markup/inline.html - -:: - - :role:`title ` - -or - -:: - - :role:`target` - -where - -- ``role`` is the kind of thing you want to link to (i.e. ``mod`` for - module, ``class`` for classes, ``meth`` for methods, ``func`` for - functions, etc; +The documentation can contain links toward modules, classes, or methods, e.g.:: -- ``target`` is the Python name of the object (class, module, method, - etc.) which carries the documentation to be linked to; + :mod:`link to a module ` + :mod:`sage.module_name` (here the link's text is the module's name) -- ``title`` is the name of the link as shown in the browser. +For links toward classes, methods, or function, replace **:mod:** by +**:class:**, **:meth:** or **func:** respectively. See `Sphinx' documentation +`_. -If you do not provide any title then target will be used. For example, -to link to the ``dyck_word`` module, you would use -``:mod:`sage.combinat.dyck_word``` or if you prefer ``:mod:`Dyck -words```. Note that, in the first case, the -full qualified Python address is used which is usually too long. You -can prefix it with a ``"~"`` to get only the final name. For example, -in the huge link:: +**Short links:** the link ``:func:`~sage.mod1.mod2.mod3.func1``` is equivalent +to ``:func:`func1 ```: the function's name will be +used as the link name, instead of its full path. - :meth:`~sage.combinat.non_decreasing_parking_function.NonDecreasingParkingFunction.to_dyck_word` +**Local names:** links between methods of the same class do not need to be +absolute. If you are documenting ``method_one``, you can write +``:meth:`method_two```. -only ``".to_dyck_word()"`` will appear. Note that the parentheses in -the link are autogenerated. +**Global namespace:** if an object (e.g. ``integral``) is automatically imported +by Sage, you can link toward it without specifying its full path:: -Local names are handled. That is, for example, in the definition of a -class (and any of its members or methods), you can link to any member -or method of the same class by simply giving the name of it prepended -by a dot ``"."``. You do not need to give its full address. For -example:: + :func:`A link toward the integral function ` - :meth:`.to_dyck_word` +**Sage-specific roles:** Sage defines several specific *roles*: -sets up a link to the ``.to_dyck_word()`` method of the current class -if it exists. If not, the documentation builder searches by going up -in the class/module hierarchy of Python until it finds an object with -this name or reaches the top-level module without finding it. If the -name cannot be found, the title is typeset in boldface without any -link produced and also without any error or warning. Note that without -the prepended dot, the object is searched starting from the top-level -to the innermost module or class. +.. list-table:: + :widths: 4 4 4 + :header-rows: 0 -You can also link, without giving the full path, to objects imported -in a local module or imported by default in Sage. For example, the two -following are equivalent, as :class:`Parent` is imported by default in -Sage (using the ``all.py`` files):: + * - Trac server + - ``:trac:`17596``` + - :trac:`17596` - :class:`Parent` - :class:`~sage.structure.parent.Parent` + * - Wikipedia + - ``:wikipedia:`Sage_(mathematics_software)``` + - :wikipedia:`Sage_(mathematics_software)` -Sage adds a special role to link to trac ticket. The code -``:trac:`12490``` link to the :trac:`12490`. When fixing a bug, you -should add the link to the corresponding trac ticket in the ``TEST`` -section. Here is an example:: + * - Arxiv + - ``:arxiv:`1202.1506``` + - :arxiv:`1202.1506` - TEST: + * - On-Line Encyclopedia of Integer Sequences + - ``:oeis:`A000081``` + - :oeis:`A000081` - We check for :trac:`5534`:: + * - Digital Object Identifier + - ``:doi:`10.2752/175303708X390473``` + - :doi:`10.2752/175303708X390473` - sage: w = ["a", "b", "c", "d"]; ww = ["b", "d"] - sage: x = sage.combinat.subword.smallest_positions(w, ww); ww - ['b', 'd'] + * - MathSciNet + - ``:mathscinet:`MR0100971``` + - :mathscinet:`MR0100971` -In the same vein, you can also add external links of various kinds: +**http links:** copy/pasting a http link in the documentation works. If you want +a specific link name, use ```link name `_`` -- Wikipedia: ``:wikipedia:`Sage_(mathematics_software)``` adds the - link :wikipedia:`Sage_(mathematics_software)`. - -- Arxiv: ``:arxiv:`1202.1506``` adds the link :arxiv:`1202.1506`. - -- On-Line Encyclopedia of Integer Sequences: ``:oeis:`A000081``` adds - the link :oeis:`A000081`. - -- Digital Object Identifier: ``:doi:`10.2752/175303708X390473``` adds - the link :doi:`10.2752/175303708X390473`. - -- MathSciNet: ``:mathscinet:`MR0100971``` adds the link - :mathscinet:`MR0100971`. - -General http-links can be added in a couple of ways. The first method -is to simply copy and paste the link. ``http://www.sagemath.org`` creates -the link http://www.sagemath.org . And if you want to give the link a title -you can do this: ```title `_``, which creates the -link `title `_. - -The latter method in addition to being able to give the link an optional -title (just remove the word "title"), lets you put a comma or a period -directly after the link, instead of having to put a space between the -end of the link and any punctuation that is used after it. The sentence -above describing the first method was an example of this. - -.. note:: - - Finally, you can check that all links are properly resolved by - adding the argument ``--warn-links`` to the documentation build - command as in:: - - sage --docbuild --warn-links reference html - - In this case, when a link is not resolved Sphinx will issue a - warning. +**Broken links:** Sphinx can report broken links. See +:ref:`section-building-manuals`. .. _section-add-file: Adding a New File ================= -If you write a new file, say, ``sage/combinat/family.py``, and you -want your documentation to be added to the standard documentation, you -have to add your file to the relevant ``index.rst`` file usually -located in the tree:: - - SAGE_ROOT/src/doc/en/reference - -For this example, you would need to add to the file:: - - SAGE_ROOT/src/doc/en/reference/combinat/index.rst - -the following line:: - - Combinatorics - ============= +If you added a new file to Sage (e.g. ``sage/matroids/my_algorithm.py``) and you +want its content to appear in the reference manual, you have to add its name to +the file ``SAGE_ROOT/src/doc/en/reference/matroids/index.rst``. Replace +'matroids' with whatever fits your case. - .. toctree:: - :maxdepth: 2 +**The combinat/ folder:** if your new file belongs to a subdirectory of combinat/ the +procedure is different: - ../sage/combinat/combinat - [...] - ../sage/combinat/dyck_word - + ../sage/combinat/family - ../sage/combinat/finite_class - [...] - -.. _section-create-tutorial: - -Creating a Tutorial from a Worksheet -==================================== - -Sage has a number of thematic tutorials, especially those developed by the -`sage-combinat group `_. -Sage has everything needed to take a worksheet created in the -`Sage notebook `_ (sagenb) and then -create a tutorial. - -* Once you have created a worksheet and are satisfied with the text and - computations, download it to a directory. - -We will assume here that the worksheet is called ``Tutorial.sws`` -and the directory is called ``make_tutorial``. We also assume that -``sage`` is your Sage command; if it is not in your ``PATH`` then replace -this with the path to your Sage installation, such as -``/Applications/Sage-6.2.app/Contents/Resources/sage/sage`` if you are -using the Mac app and have placed it in your Applications directory. - -* Next, you will need an optional package to parse your worksheet. Use the - command:: - - sage -i beautifulsoup - - to install it (or, in the Mac app, use the ``Terminal Session`` advanced - menu with ``-i beautifulsoup``). - -* Then we will use the ``sws2rst`` script to turn the worksheet into - a document in the `ReStructuredText `_ - format. Be sure you are in the same directory as the worksheet:: - - sage --sws2rst Tutorial.sws - - This will create an ``.rst`` file along with a subdirectory of image - files (which may be empty if there are no images). - - You can find help for ``sws2rst`` with the command - ``sage --sws2rst -h`` once you have installed beautifulsoup. - -* In principle, such a file could be added directly to the documentation; - see :ref:`section-add-file`. If you add it to one of the manuals or - the list of thematic tutorials, be sure to edit the ``toctree`` file - as well, and put the line ``.. _tutorial-name:`` at the start of your - file with the same listing as in the ``index.rst`` file. - - However, you probably want to check whether it looks right first. So - next we will compile this file to html documentation. - - * Follow the instructions of ``sage --sws2rst --sphinxify``. First, - we will open a Sage shell session, where all appropriate Sage - references already work properly:: - - sage --sh - - From here, you should be able to just type:: - - sphinx-quickstart - - and then respond to prompts for turning your ``.rst`` file into - documentation. For most of them you can just hit enter/return to - accept the defaults. However, you will probably want to - - * Enter a name for the project - * Enter a name for you - * Type ``y`` for the question about using MathJax - - Keep note of the instructions; the main other thing to do is add - your file's name to ``index.rst``, and then just do:: - - make html - - and wait while magic happens. To see the results, open the file - ``make_tutorial/_build/html/Tutorial.html`` with a browser, or - use your graphical file system to navigate to the same place. - -* Now you can modify the ``.rst`` file more and repeat the steps - of compiling it until it is ready for inclusion, or just for distribution - among other Sage users as an HTML file. (Do ``make pdf`` for a PDF - version.) +* Add your file to the index stored in the ``__init__.py`` file located in the + directory that contains your file. +* Add your file to the index contained in + ``SAGE_ROOT/src/doc/en/reference/combinat/module_list.rst``. .. _section-building-manuals: Building the Manuals ==================== +*(Do you want to edit the documentation?* :ref:`Click here +`) + All of the Sage manuals are built using the ``sage --docbuild`` script. The content of the ``sage --docbuild`` script is defined in ``SAGE_ROOT/src/doc/common/builder.py``. It is a thin wrapper around @@ -337,19 +173,27 @@ is:: sage --docbuild -as explained below. For more information, there are two help commands -which give plenty of documentation for the ``sage --docbuild`` -script:: +For example:: - sage --docbuild --help + sage --docbuild reference html -(or ``-h``) gives a basic listing of options and further -help commands, while:: +Two **help** commands which give plenty of documentation for the ``sage +--docbuild`` script:: - sage --docbuild --help-all + sage --docbuild -h # short help message + sage --docbuild -H # a more comprehensive one -(or ``-H``) shows a somewhat more comprehensive help message. +**Output formats:** All output formats supported by Sphinx (e.g. pdf) can be +used in Sage. See ``_. +**Broken links:** in order to build the documentation while reporting the broken +links that it contains, use the ``--warn-links`` flag. Note that Sphinx will not +rebuild a document that has not been updated, and thus not report its broken +links:: + + sage --docbuild --warn-links reference html + +.. _section-manuals-names: Document Names -------------- @@ -371,23 +215,12 @@ To specify the French version of the tutorial, you would simply run:: sage --docbuild fr/tutorial html -Output Formats --------------- - -The Sage documentation build system currently supports all of the -output formats that Sphinx does. For more detailed information, see -the documentation on builders at ``_. - - Syntax Highlighting Cython Code =============================== -If you need to put :ref:`Cython ` code in a ReST file, -you can either precede the code block by ``.. code-block:: cython`` instead -of the usual ``::`` if you want to highlight one block of code in Cython, -or you can use ``.. highlight:: cython`` for a whole file. - -The following example was generated by ``.. code-block:: cython``: +If you want to write :ref:`Cython ` code in a ReST file, precede +the code block by ``.. code-block:: cython`` instead of the usual ``::``. Enable +syntax-highlighting in a whole file with ``.. highlight:: cython``. Example: .. code-block:: cython diff --git a/src/doc/en/faq/faq-usage.rst b/src/doc/en/faq/faq-usage.rst index 27f82010caa..0c4ad809161 100644 --- a/src/doc/en/faq/faq-usage.rst +++ b/src/doc/en/faq/faq-usage.rst @@ -623,7 +623,7 @@ libraries. Here is a small example:: # Show that x behaves like a finite field element: for i in range(1, x.multiplicative_order() + 1): print i, x**i - assert x*(1/x) == K.one_element() + assert x*(1/x) == K.one() To find out more, type :: @@ -632,7 +632,7 @@ To find out more, type :: at the Sage prompt and hit tab, then use ``??`` to get more information on each function. For example:: - sage.rings.finite_field_givaro.FiniteField_givaro.one_element?? + sage.rings.finite_field_givaro.FiniteField_givaro.one?? tells you more about the multiplicative unit element in the finite field. diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index 43b887a3d94..982e1c710bf 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -760,6 +760,20 @@ how it is built: requires that Sage be built first, so it will automatically run ``make build``. +- ``make doc-html-no-plot`` builds Sage's documentation in html format + but skips the inclusion of graphics auto-generated using the + ``.. PLOT`` markup and the ``sphinx_plot`` function. This is + primarily intended for use when producing certain binary + distributions of Sage, to lower the size of the distribution. As of + this writing (December 2014, Sage 6.5), there are only a few such + plots, adding about 4M to the :file:`src/doc/output/` directory. In + the future, this may grow, of course. Note: after using this, if you + want to build the documentation and include the pictures, you should + run ``make doc-clean``, because the presence, or lack, of pictures + is cached in the documentation output. + You can benefit from this no-plot feature with other make targets by doing + ``export SAGE_DOCBUILD_OPTS+=' --no-plot'`` + - ``make build-serial`` builds the components of Sage serially, rather than in parallel (parallel building is the default). Running ``make build-serial`` is equivalent to setting the environment @@ -777,6 +791,9 @@ how it is built: software, you can use ``make testall``, ``make ptestall``, ``make testalllong``, or ``make ptestalllong``. +- ``make doc-clean`` removes several directories which are produced + when building the documentation. + - ``make distclean`` restores the Sage directory to its state before doing any building: it is almost equivalent to deleting Sage's entire home directory and unpacking the source tarfile again, the only difference being that the @@ -941,9 +958,11 @@ Here are some of the more commonly used variables affecting the build process: Typically, building the documentation using LaTeX and dvipng takes longer and uses more memory and disk space than using MathJax. -- :envvar:`SAGE_DOCBUILD_OPTS` - the value of this variable is passed - as an argument to ``sage --docbuild all html`` or ``sage --docbuild - all pdf`` when you run ``make``, ``make doc``, or ``make doc-pdf``. +- :envvar:`SAGE_DOCBUILD_OPTS` - the value of this variable is passed as an + argument to ``sage --docbuild all html`` or ``sage --docbuild all pdf`` when + you run ``make``, ``make doc``, or ``make doc-pdf``. + For example, you can add ``--no-plot`` to this variable to avoid building + the graphics coming from the ``.. PLOT`` directive within the documentation. - :envvar:`SAGE_BUILD_DIR` - the default behavior is to build each spkg in a subdirectory of :file:`$SAGE_ROOT/local/var/tmp/sage/build/`; for @@ -1434,4 +1453,4 @@ would be appropriate if you have a Core i3/5/7 processor with AVX support. -**This page was last updated in November 2014 (Sage 6.5).** +**This page was last updated in December 2014 (Sage 6.5).** diff --git a/src/doc/en/reference/diophantine_approximation/conf.py b/src/doc/en/reference/diophantine_approximation/conf.py new file mode 120000 index 00000000000..2bdf7e68470 --- /dev/null +++ b/src/doc/en/reference/diophantine_approximation/conf.py @@ -0,0 +1 @@ +../conf_sub.py \ No newline at end of file diff --git a/src/doc/en/reference/diophantine_approximation/index.rst b/src/doc/en/reference/diophantine_approximation/index.rst new file mode 100644 index 00000000000..a1c49919f81 --- /dev/null +++ b/src/doc/en/reference/diophantine_approximation/index.rst @@ -0,0 +1,13 @@ +Diophantine approximation +========================= + +The diophantine approximation deals with the approximation of real numbers +(or real vectors) with rational numbers (or rational vectors). +See the article :wikipedia:`Diophantine_approximation` for more information. + +.. toctree:: + :maxdepth: 2 + + sage/rings/continued_fraction + +.. include:: ../footer.txt diff --git a/src/doc/en/reference/index.rst b/src/doc/en/reference/index.rst index 09490ccf2a7..607121fa1e7 100644 --- a/src/doc/en/reference/index.rst +++ b/src/doc/en/reference/index.rst @@ -74,6 +74,7 @@ Geometry and Topology Number Theory, Algebraic Geometry --------------------------------- +* :doc:`Diophantine approximation ` * :doc:`Quadratic Forms ` * :doc:`L-Functions ` * :doc:`Schemes ` diff --git a/src/doc/en/reference/misc/index.rst b/src/doc/en/reference/misc/index.rst index 4742f5cecb8..959aefcbca6 100644 --- a/src/doc/en/reference/misc/index.rst +++ b/src/doc/en/reference/misc/index.rst @@ -33,6 +33,7 @@ Miscellaneous sage/misc/unknown sage/misc/func_persist sage/misc/sage_eval + sage/misc/sage_input sage/misc/random_testing sage/misc/sageinspect sage/misc/sagedoc diff --git a/src/doc/en/reference/plot3d/index.rst b/src/doc/en/reference/plot3d/index.rst index 56830610e46..cb490a17478 100644 --- a/src/doc/en/reference/plot3d/index.rst +++ b/src/doc/en/reference/plot3d/index.rst @@ -17,5 +17,6 @@ sage/plot/plot3d/base sage/plot/plot3d/tachyon sage/plot/plot3d/texture + sage/plot/plot3d/index_face_set .. include:: ../footer.txt diff --git a/src/doc/en/thematic_tutorials/coding_theory.rst b/src/doc/en/thematic_tutorials/coding_theory.rst index 0866608b128..378f8c3036c 100644 --- a/src/doc/en/thematic_tutorials/coding_theory.rst +++ b/src/doc/en/thematic_tutorials/coding_theory.rst @@ -27,24 +27,23 @@ call GUAVA: :: - - Sage : MS = MatrixSpace(GF(2),4,7) - Sage : G = MS([[1,1,1,0,0,0,0], [1,0,0,1,1,0,0], - [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]]) - Sage : C = LinearCode(G) - Sage : C + sage: MS = MatrixSpace(GF(2),4,7) + sage: G = MS([[1,1,1,0,0,0,0], [1,0,0,1,1,0,0], + ....: [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]]) + sage: C = LinearCode(G) + sage: C Linear code of length 7, dimension 4 over Finite Field of size 2 - Sage : C.base_ring() + sage: C.base_ring() Finite Field of size 2 - Sage : C.dimension() + sage: C.dimension() 4 - Sage : C.length() + sage: C.length() 7 - Sage : C.minimum_distance() + sage: C.minimum_distance() 3 - Sage : C.spectrum() + sage: C.spectrum() [1, 0, 0, 7, 7, 0, 0, 1] - Sage : C.weight_distribution() + sage: C.weight_distribution() [1, 0, 0, 7, 7, 0, 0, 1] This function also enables you to create your own code functions. The @@ -59,8 +58,9 @@ call GUAVA: It is an extremal (Hermitian) self-dual Type IV code. EXAMPLES: - Sage : C = Hexacode() - Sage : C.minimum_distance() + + sage: C = Hexacode() # not tested (see trac #17617) + sage: C.minimum_distance() # not tested (see trac #17617) 4 """ @@ -81,13 +81,13 @@ call GUAVA: :: - Sage : C = HammingCode(3,GF(2)) - Sage : C.zeta_polynomial() + sage: C = codes.HammingCode(3,GF(2)) + sage: C.zeta_polynomial() 2/5*T^2 + 2/5*T + 1/5 - Sage : C = best_known_linear_code(6,3,GF(2)) - Sage : C.minimum_distance() + sage: C = best_known_linear_code(6,3,GF(2)) # not tested (see trac #17617) + sage: C.minimum_distance() # not tested (see trac #17617) 3 - Sage : C.zeta_polynomial() + sage: C.zeta_polynomial() # not tested (see trac #17617) 2/5*T^2 + 2/5*T + 1/5 #. ``gen_mat``, ``check_mat``, ``decode``, ``dual_code``, @@ -105,18 +105,18 @@ call GUAVA: :: - Sage : C = HammingCode(3,GF(2)) - Sage : C.binomial_moment(2) + sage: C = codes.HammingCode(3,GF(2)) + sage: C.binomial_moment(2) 0 - Sage : C.binomial_moment(3) # long time + sage: C.binomial_moment(3) # not tested (see trac #17617) 0 - Sage : C.binomial_moment(4) # long time + sage: C.binomial_moment(4) # long time 35 - Sage : C = HammingCode(3,GF(2)) - Sage : MS = MatrixSpace(GF(2),1,7) - Sage : F = GF(2); a = F.gen() - Sage : v1 = [a,a,F(0),a,a,F(0),a] - Sage : C.decode(v1) + sage: C = codes.HammingCode(3,GF(2)) + sage: MS = MatrixSpace(GF(2),1,7) + sage: F = GF(2); a = F.gen() + sage: v1 = [a,a,F(0),a,a,F(0),a] + sage: C.decode(v1) # not tested (see trac #17617) (1, 0, 0, 1, 1, 0, 1) Decoding, at the moment, merely uses syndrome decoding via GUAVA. @@ -135,34 +135,34 @@ call GUAVA: :: - Sage : C = HammingCode(3,GF(2)) - Sage : G = C.automorphism_group_binary_code(); G - Permutation Group with generators [(2,3)(5,7), (2,5)(3,7), + sage: C = codes.HammingCode(3,GF(2)) + sage: G = C.automorphism_group_binary_code(); G # not tested (see trac #17617) + Permutation Group with generators [(2,3)(5,7), (2,5)(3,7), (2,3,7,5)(4,6), (2,4)(6,7), (1,2)(3,4)] - Sage : G.order() + sage: G.order() # not tested (see trac #17617) 168 - Sage : C = HammingCode(3,GF(2)) - Sage : C.gen_mat() + sage: C = codes.HammingCode(3,GF(2)) + sage: C.gen_mat() # not tested (see trac #17617) [1 0 0 1 0 1 0] [0 1 0 1 0 1 1] [0 0 1 1 0 0 1] [0 0 0 0 1 1 1] - Sage : C.redundancy_matrix() + sage: C.redundancy_matrix() # not tested (see trac #17617) [1 1 0] [1 1 1] [1 0 1] [0 1 1] - Sage : C.standard_form()[0].gen_mat() + sage: C.standard_form()[0].gen_mat() # not tested (see trac #17617) [1 0 0 0 1 1 0] [0 1 0 0 1 1 1] [0 0 1 0 1 0 1] [0 0 0 1 0 1 1] - Sage : MS = MatrixSpace(GF(2),4,8) - Sage : G = MS([[1,0,0,0,1,1,1,0],[0,1,1,1,0,0,0,0], - [0,0,0,0,0,0,0,1],[0,0,0,0,0,1,0,0]]) - Sage : C = LinearCode(G) - Sage : gp = C.automorphism_group_binary_code() - Sage : C.module_composition_factors(gp) + sage: MS = MatrixSpace(GF(2),4,8) + sage: G = MS([[1,0,0,0,1,1,1,0],[0,1,1,1,0,0,0,0], # not tested (see trac #17617) + ....: [0,0,0,0,0,0,0,1],[0,0,0,0,0,1,0,0]]) # not tested (see trac #17617) + sage: C = codes.LinearCode(G) # not tested (see trac #17617) + sage: gp = C.automorphism_group_binary_code() # not tested (see trac #17617) + sage: C.module_composition_factors(gp) # not tested (see trac #17617) [ rec( field := GF(2), isMTXModule := true, @@ -299,8 +299,8 @@ call GUAVA: :: - Sage : C = ExtendedBinaryGolayCode() # example 1 - Sage : C.assmus_mattson_designs(5) + sage: C = codes.ExtendedBinaryGolayCode() # example 1 + sage: C.assmus_mattson_designs(5) ['weights from C: ', [8, 12, 16, 24], 'designs from C: ', @@ -309,13 +309,13 @@ call GUAVA: [8, 12, 16], 'designs from C*: ', [[5, (24, 8, 1)], [5, (24, 12, 48)], [5, (24, 16, 78)]]] - Sage : C.assmus_mattson_designs(6) - 0 - Sage : X = range(24)# example 2 - Sage : blocks = [c.support() for c in C if hamming_weight(c)==8] - Sage : len(blocks) + sage: C.assmus_mattson_designs(6) + 0 + sage: X = range(24)# example 2 + sage: blocks = [c.support() for c in C if hamming_weight(c)==8] # not tested (see trac #17617) + sage: len(blocks) # not tested (see trac #17617) 759 - + The method ``automorphism_group_binary_code`` is actually an interface to an extremely fast implementation written by the second author. It @@ -349,7 +349,7 @@ Python: :math:`n^{th}` root of unity in the splitting field :math:`GF(q^m)`, :math:`b` is an integer :math:`0\leq b\leq n-\delta+1` and :math:`m` is the multiplicative order of :math:`q` modulo :math:`n`. - + SEEALSO: :wikipedia:`BCH_code` EXAMPLES: @@ -357,23 +357,23 @@ Python: :: - Sage : FF. = GF(3^2,"a") - Sage : x = PolynomialRing(FF,"x").gen() - Sage : L = [b.minpoly() for b in [a,a^2,a^3]]; g = LCM(L) - Sage : f = x^(8)-1 - Sage : g.divides(f) + sage: FF. = GF(3^2,"a") + sage: x = PolynomialRing(FF,"x").gen() + sage: L = [b.minpoly() for b in [a,a^2,a^3]]; g = LCM(L) + sage: f = x^(8)-1 + sage: g.divides(f) True - Sage : C = CyclicCode(8,g); C + sage: C = codes.CyclicCode(8,g); C Linear code of length 8, dimension 4 over Finite Field of size 3 - Sage : C.minimum_distance() + sage: C.minimum_distance() 4 - Sage : C = BCHCode(8,3,GF(3),1); C + sage: C = codes.BCHCode(8,3,GF(3),1); C Linear code of length 8, dimension 4 over Finite Field of size 3 - Sage : C.minimum_distance() + sage: C.minimum_distance() 4 - Sage : C = BCHCode(8,3,GF(3)); C + sage: C = codes.BCHCode(8,5,GF(3)); C Linear code of length 8, dimension 3 over Finite Field of size 3 - Sage : C.minimum_distance() + sage: C.minimum_distance() 5 - ``BinaryGolayCode``, ``ExtendedBinaryGolayCode``, ``TernaryGolayCode``, - the @@ -384,17 +384,17 @@ Python: :: - Sage : C = ExtendedBinaryGolayCode() - Sage : C + sage: C = codes.ExtendedBinaryGolayCode() + sage: C Linear code of length 24, dimension 12 over Finite Field of size 2 - Sage : C.minimum_distance() + sage: C.minimum_distance() 8 - Sage : C.is_self_dual() + sage: C.is_self_dual() True - Sage : C = TernaryGolayCode() - Sage : C + sage: C = codes.TernaryGolayCode() + sage: C Linear code of length 11, dimension 6 over Finite Field of size 3 - Sage : C.minimum_distance() + sage: C.minimum_distance() 5 - Cyclic codes - ``CyclicCodeFromGeneratingPolynomial`` (= ``CyclicCode``), @@ -405,36 +405,36 @@ Python: :: - Sage : P. = PolynomialRing(GF(3),"x") - Sage : g = x-1 - Sage : C = CyclicCodeFromGeneratingPolynomial(4,g); C + sage: P. = PolynomialRing(GF(3),"x") + sage: g = x-1 + sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C Linear code of length 4, dimension 3 over Finite Field of size 3 - Sage : P. = PolynomialRing(GF(4,"a"),"x") - Sage : g = x^3+1 - Sage : C = CyclicCodeFromGeneratingPolynomial(9,g); C + sage: P. = PolynomialRing(GF(4,"a"),"x") + sage: g = x^3+1 + sage: C = codes.CyclicCodeFromGeneratingPolynomial(9,g); C Linear code of length 9, dimension 6 over Finite Field in a of size 2^2 - Sage : P. = PolynomialRing(GF(2),"x") - Sage : g = x^3+x+1 - Sage : C = CyclicCodeFromGeneratingPolynomial(7,g); C + sage: P. = PolynomialRing(GF(2),"x") + sage: g = x^3+x+1 + sage: C = codes.CyclicCodeFromGeneratingPolynomial(7,g); C Linear code of length 7, dimension 4 over Finite Field of size 2 - Sage : C.gen_mat() + sage: C.gen_mat() [1 1 0 1 0 0 0] [0 1 1 0 1 0 0] [0 0 1 1 0 1 0] [0 0 0 1 1 0 1] - Sage : g = x+1 - Sage : C = CyclicCodeFromGeneratingPolynomial(4,g); C + sage: g = x+1 + sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C Linear code of length 4, dimension 3 over Finite Field of size 2 - Sage : C.gen_mat() + sage: C.gen_mat() [1 1 0 0] [0 1 1 0] [0 0 1 1] - Sage : P. = PolynomialRing(GF(3),"x") - Sage : C = CyclicCodeFromCheckPolynomial(4,x + 1); C + sage: P. = PolynomialRing(GF(3),"x") + sage: C = codes.CyclicCodeFromCheckPolynomial(4,x + 1); C Linear code of length 4, dimension 1 over Finite Field of size 3 - Sage : C = CyclicCodeFromCheckPolynomial(4,x^3 + x^2 + x + 1); C + sage: C = codes.CyclicCodeFromCheckPolynomial(4,x^3 + x^2 + x + 1); C Linear code of length 4, dimension 3 over Finite Field of size 3 - Sage : C.gen_mat() + sage: C.gen_mat() [2 1 0 0] [0 2 1 0] [0 0 2 1] @@ -449,15 +449,15 @@ Python: :: - Sage : from Sage .coding.code_constructions import is_a_splitting - Sage : n = 11; q = 3 - Sage : C = cyclotomic_cosets(q,n); C + sage: from sage.coding.code_constructions import is_a_splitting + sage: n = 11; q = 3 + sage: C = Zmod(n).cyclotomic_cosets(q); C [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]] - Sage : S1 = C[1] - Sage : S2 = C[2] - Sage : is_a_splitting(S1,S2,11) - (True, 2) - Sage : DuadicCodeOddPair(GF(q),S1,S2) + sage: S1 = C[1] + sage: S2 = C[2] + sage: is_a_splitting(S1,S2,11) + True + sage: codes.DuadicCodeOddPair(GF(q),S1,S2) (Linear code of length 11, dimension 6 over Finite Field of size 3, Linear code of length 11, dimension 6 over Finite Field of size 3) @@ -472,7 +472,7 @@ Python: nonzero vectors of length r in its columns, modulo a scalar factor so no parallel columns arise. A Hamming code is a single error-correcting code. - + SEEALSO: :wikipedia:`Hamming_code` EXAMPLES: @@ -480,13 +480,13 @@ Python: :: - Sage : HammingCode(3,GF(2)) + sage: codes.HammingCode(3,GF(2)) Linear code of length 7, dimension 4 over Finite Field of size 2 - Sage : C = HammingCode(3,GF(3)); C + sage: C = codes.HammingCode(3,GF(3)); C Linear code of length 13, dimension 10 over Finite Field of size 3 - Sage : C.minimum_distance() + sage: C.minimum_distance() 3 - Sage : C = HammingCode(3,GF(4,'a')); C + sage: C = codes.HammingCode(3,GF(4,'a')); C Linear code of length 21, dimension 18 over Finite Field in a of size 2^2 - ``LinearCodeFromCheckMatrix`` - for specifing the code using the check @@ -498,7 +498,7 @@ Python: .. math:: - 0 \rightarrow + 0 \rightarrow {\mathbf{F}}^k \stackrel{G}{\rightarrow} {\mathbf{F}}^n \stackrel{H}{\rightarrow} {\mathbf{F}}^{n-k} \rightarrow @@ -514,22 +514,22 @@ Python: :: - Sage : C = HammingCode(3,GF(2)) - Sage : H = C.check_mat(); H + sage: C = codes.HammingCode(3,GF(2)) + sage: H = C.check_mat(); H # not tested (see trac #17617) [1 0 0 1 1 0 1] [0 1 0 1 0 1 1] [0 0 1 1 1 1 0] - Sage : LinearCodeFromCheckMatrix(H) == C + sage: codes.LinearCodeFromCheckMatrix(H) == C # not tested (see trac #17617) True - Sage : C = HammingCode(2,GF(3)) - Sage : H = C.check_mat(); H + sage: C = codes.HammingCode(2,GF(3)) + sage: H = C.check_mat(); H # not tested (see trac #17617) [1 0 2 2] [0 1 2 1] - Sage : LinearCodeFromCheckMatrix(H) == C + sage: codes.LinearCodeFromCheckMatrix(H) == C # not tested (see trac #17617) True - Sage : C = RandomLinearCode(10,5,GF(4,"a")) - Sage : H = C.check_mat() - Sage : LinearCodeFromCheckMatrix(H) == C + sage: C = codes.RandomLinearCode(10,5,GF(4,"a")) + sage: H = C.check_mat() + sage: codes.LinearCodeFromCheckMatrix(H) == C # not tested (see trac #17617) True - ``QuadraticResidueCodeEvenPair``, ``QuadraticResidueCodeOddPair``: Quadratic @@ -551,24 +551,24 @@ Python: :: - Sage : QuadraticResidueCodeEvenPair(17,GF(13)) + sage: codes.QuadraticResidueCodeEvenPair(17,GF(13)) (Linear code of length 17, dimension 8 over Finite Field of size 13, Linear code of length 17, dimension 8 over Finite Field of size 13) - Sage : QuadraticResidueCodeEvenPair(17,GF(2)) + sage: codes.QuadraticResidueCodeEvenPair(17,GF(2)) (Linear code of length 17, dimension 8 over Finite Field of size 2, Linear code of length 17, dimension 8 over Finite Field of size 2) - Sage : QuadraticResidueCodeEvenPair(13,GF(9,"z")) + sage: codes.QuadraticResidueCodeEvenPair(13,GF(9,"z")) (Linear code of length 13, dimension 6 over Finite Field in z of size 3^2, Linear code of length 13, dimension 6 over Finite Field in z of size 3^2) - Sage : C1 = QuadraticResidueCodeEvenPair(7,GF(2))[0] - Sage : C1.is_self_orthogonal() + sage: C1 = codes.QuadraticResidueCodeEvenPair(7,GF(2))[0] + sage: C1.is_self_orthogonal() True - Sage : C2 = QuadraticResidueCodeEvenPair(7,GF(2))[1] - Sage : C2.is_self_orthogonal() + sage: C2 = codes.QuadraticResidueCodeEvenPair(7,GF(2))[1] + sage: C2.is_self_orthogonal() True - Sage : C3 = QuadraticResidueCodeOddPair(17,GF(2))[0] - Sage : C4 = QuadraticResidueCodeEvenPair(17,GF(2))[1] - Sage : C3 == C4.dual_code() + sage: C3 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0] + sage: C4 = codes.QuadraticResidueCodeEvenPair(17,GF(2))[1] + sage: C3 == C4.dual_code() True This is consistent with Theorem 6.6.9 and Exercise 365 in [HP]_. @@ -589,7 +589,7 @@ Python: .. math:: - C = \left\{ \left( f(x_1), f(x_2), ..., f(x_n) \right)\ |\ f \in \mathbb{F}[x], + C = \left\{ \left( f(x_1), f(x_2), ..., f(x_n) \right)\ |\ f \in \mathbb{F}[x], {\rm deg}(f) = GF(3^2,"a") - Sage : pts = [0,1,a,a^2,2*a,2*a+1] - Sage : len(Set(pts)) == 6 # to make sure there are no duplicates + sage: F. = GF(3^2,"a") + sage: pts = [0,1,a,a^2,2*a,2*a+1] + sage: len(Set(pts)) == 6 # to make sure there are no duplicates True - Sage : C = ReedSolomonCode(6,4,F,pts); C + sage: C = codes.ReedSolomonCode(6,4,F,pts); C Linear code of length 6, dimension 4 over Finite Field in a of size 3^2 - Sage : C.minimum_distance() + sage: C.minimum_distance() 3 - ``ToricCode`` - Let :math:`P` denote a list of lattice points in @@ -639,14 +639,14 @@ Python: :: - Sage : C = ToricCode([[0,0],[1,0],[2,0],[0,1],[1,1]],GF(7)) - Sage : C + sage: C = codes.ToricCode([[0,0],[1,0],[2,0],[0,1],[1,1]],GF(7)) + sage: C Linear code of length 36, dimension 5 over Finite Field of size 7 - Sage : C.minimum_distance() + sage: C.minimum_distance() 24 - Sage : P = [ [0,0],[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[3,1],[3,2],[4,1]] - Sage : C = ToricCode(P, GF(8,"a")) - Sage : C + sage: P = [ [0,0],[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[3,1],[3,2],[4,1]] + sage: C = codes.ToricCode(P, GF(8,"a")) + sage: C Linear code of length 49, dimension 11 over Finite Field in a of size 2^3 This is in fact a :math:`[49,11,28]` code over :math:`GF(8)`. If you @@ -661,10 +661,10 @@ Python: :: - Sage : C = WalshCode(4); C + sage: C = codes.WalshCode(4); C Linear code of length 16, dimension 4 over Finite Field of size 2 - Sage : C.minimum_distance() - 8 + sage: C.minimum_distance() + 8 Bounds ====== @@ -686,19 +686,19 @@ Regarding bounds on coding theory parameters, this module implements: - ``F`` - finite field, whose field order must be in [2, 3, 4, 5, 7, 8, 9] - - ``verbose`` - bool (default=False), print verbose mesSage + - ``verbose`` - bool (default=False), print verbose mesSage EXAMPLES: :: - Sage : L = best_known_linear_code_www(72, 36, GF(2)) # requires internet - Sage : print L + sage: L = codes.best_known_linear_code_www(72, 36, GF(2)) # not tested (see trac #17617) + sage: print L # not tested (see trac #17617) Construction of a linear code [72,36,15] over GF(2): [1]: [73, 36, 16] Cyclic Linear Code over GF(2) - CyclicCode of length 73 with generating polynomial x^37 + x^36 - + x^34 + x^33 + x^32 + x^27 + x^25 + x^24 + x^22 + x^21 + x^19 + CyclicCode of length 73 with generating polynomial x^37 + x^36 + + x^34 + x^33 + x^32 + x^27 + x^25 + x^24 + x^22 + x^21 + x^19 + x^18 + x^15 + x^11 + x^10 + x^8 + x^7 + x^5 + x^3 + 1 [2]: [72, 36, 15] Linear Code over GF(2) Puncturing of [1] at 1 @@ -711,7 +711,7 @@ Regarding bounds on coding theory parameters, this module implements: :: - Sage : print bounds_minimum_distance(10,5,GF(2)) + sage: print bounds_minimum_distance(10,5,GF(2)) # not tested (see trac #17617) rec( n := 10, k := 5, @@ -723,16 +723,16 @@ Regarding bounds on coding theory parameters, this module implements: , [ [ , [ 8, 2 ] ] ] ], [ , - [ [ , - [ [ , [ 4, 2 ] ] ] ], + [ [ , + [ [ , [ 4, 2 ] ] ] ], [ , [ 4, 2 ] ] ] ] ] ], [ 1, 2, 3, 4, 5, 6 ] ] ], lowerBound := 4, lowerBoundExplanation := - [ "Lb(10,5)=4, by shortening of:", + [ "Lb(10,5)=4, by shortening of:", "Lb(16,11)=4, by the u|u+v construction applied to C1 [8,7,2] and C2 [8,4,4]: ", "Lb(8,7)=2, dual of the repetition code", - "Lb(8,4)=4, by the u|u+v construction applied to C1 [4,3,2] and C2 [4,1,4]: ", + "Lb(8,4)=4, by the u|u+v construction applied to C1 [4,3,2] and C2 [4,1,4]: ", "Lb(4,3)=2, dual of the repetition code", "Lb(4,1)=4, repetition code" ], upperBound := 4, @@ -747,7 +747,7 @@ Regarding bounds on coding theory parameters, this module implements: :: - Sage : codesize_upper_bound(10, 3, 2) + sage: codesize_upper_bound(10, 3, 2) # not tested (see trac #17617) 85 This means that there is a :math:`(10,85,3)` binary (non-linear) @@ -758,8 +758,8 @@ Regarding bounds on coding theory parameters, this module implements: :: - Sage : L = best_known_linear_code_www(10, 6, GF(2)) - Sage : print L + sage: L = best_known_linear_code_www(10, 6, GF(2)) # not tested (see trac #17617) + sage: print L # not tested (see trac #17617) Construction of a linear code [10,6,3] over GF(2): [1]: [4, 1, 4] Cyclic Linear Code over GF(2) @@ -792,7 +792,7 @@ Regarding bounds on coding theory parameters, this module implements: :: - Sage : dimension_upper_bound(10, 3, 2) + sage: dimension_upper_bound(10, 3, 2) 6 This was established in the example above. @@ -858,11 +858,11 @@ Regarding bounds on coding theory parameters, this module implements: .. math:: \begin{aligned} - R(C)+\delta(C) \geq + R(C)+\delta(C) \geq &1- \delta(C)\log_q({\frac{q-1}{q}})-\delta(C)\log_q(\delta(C))\\ &-(1-\delta(C))\log_q(1-\delta(C))-\epsilon.\\ \end{aligned} - + The curve :math:`(\delta, 1- \delta\log_q({\frac{q-1}{q}})-\delta\log_q(\delta)- (1-\delta)\log_q(1-\delta)))` is called the **Gilbert-Varshamov @@ -879,9 +879,9 @@ Regarding bounds on coding theory parameters, this module implements: .. figure:: media/gv-bound-asymp.png :align: center :scale: 50 % - + Figure 1: Plot of the Gilbert-Varshamov curve using Sage (i.e., ``y = gv_bound_asymp(x, 2)``). - + - ``plotkin_upper_bound(n,q,d)`` - ``plotkin_bound_asymp(delta,q)``, asymptotic analog of the Plotkin @@ -890,9 +890,9 @@ Regarding bounds on coding theory parameters, this module implements: .. figure:: media/plotkin-bound-asymp.png :align: center :scale: 50 % - + Figure 2: Plot using Sage of ``y = plotkin_bound_asymp(x, 2)``. - + - ``griesmer_upper_bound(n,q,d)``, the Griesmer upper bound. - ``elias_upper_bound(n,q,d)``, the Elias upper bound. @@ -903,7 +903,7 @@ Regarding bounds on coding theory parameters, this module implements: .. figure:: media/elias-bound-asymp.png :align: center :scale: 50 % - + Figure 3: Plot using Sage of ``y = elias_bound_asymp(x, 2)``. - ``hamming_upper_bound(n,q,d)``, the Hamming upper bound. @@ -914,7 +914,7 @@ Regarding bounds on coding theory parameters, this module implements: .. figure:: media/hamming-bound-asymp.png :align: center :scale: 50 % - + Figure 4: Plot using Sage of ``y = hamming_bound_asymp(x, 2)``. - ``singleton_upper_bound(n,q,d)``, the Singleton upper bound. @@ -925,7 +925,7 @@ Regarding bounds on coding theory parameters, this module implements: .. figure:: media/singleton-bound-asymp.png :align: center :scale: 50 % - + Figure 5: Plot using Sage of ``y = singleton_bound_asymp(x, 2)``. - ``mrrw1_bound_asymp(delta,q)``, "first" asymptotic @@ -934,32 +934,32 @@ Regarding bounds on coding theory parameters, this module implements: .. figure:: media/mrrw1-bound-asymp.png :align: center :scale: 50 % - + Figure 6: Plot using Sage of ``y = mrrw1_bound_asymp(x, 2)``. -Here are all the bounds together: +Here are all the bounds together: :: - Sage : f1 = lambda x: gv_bound_asymp(x,2) - Sage : P1 = plot(f1,0,1/2,linestyle=":") - Sage : f2 = lambda x: plotkin_bound_asymp(x,2) - Sage : P2 = plot(f2,0,1/2,linestyle="--") - Sage : f3 = lambda x: elias_bound_asymp(x,2) - Sage : P3 = plot(f3,0,1/2,rgbcolor=(1,0,0)) - Sage : f4 = lambda x: singleton_bound_asymp(x,2) - Sage : P4 = plot(f4,0,1/2,linestyle="-.") - Sage : f5 = lambda x: mrrw1_bound_asymp(x,2) - Sage : P5 = plot(f5,0,1/2,linestyle="steps") - Sage : f6 = lambda x: hamming_bound_asymp(x,2) - Sage : P6 = plot(f6,0,1/2,rgbcolor=(0,1,0)) - Sage : show(P1+P2+P3+P4+P5+P6) + sage: f1 = lambda x: gv_bound_asymp(x,2) + sage: P1 = plot(f1,0,1/2,linestyle=":") + sage: f2 = lambda x: plotkin_bound_asymp(x,2) + sage: P2 = plot(f2,0,1/2,linestyle="--") + sage: f3 = lambda x: elias_bound_asymp(x,2) + sage: P3 = plot(f3,0,1/2,rgbcolor=(1,0,0)) + sage: f4 = lambda x: singleton_bound_asymp(x,2) + sage: P4 = plot(f4,0,1/2,linestyle="-.") + sage: f5 = lambda x: mrrw1_bound_asymp(x,2) + sage: P5 = plot(f5,0,1/2,linestyle="steps") + sage: f6 = lambda x: hamming_bound_asymp(x,2) + sage: P6 = plot(f6,0,1/2,rgbcolor=(0,1,0)) + sage: show(P1+P2+P3+P4+P5+P6) .. figure:: media/all-bounds-asymp.png :align: center :scale: 100 % - + Figure 7: Plot of the Gilbert-Varshamov (dotted), Elias (red), Plotkin (dashed), Singleton (dash-dotted), Hamming (green), and MRRW (stepped) curves using Sage. @@ -1007,19 +1007,19 @@ EXAMPLES: :: - Sage : C = self_dual_codes_binary(10)["10"] - Sage : C["0"]["code"] == C["0"]["code"].dual_code() + sage: C = self_dual_codes_binary(10)["10"] + sage: C["0"]["code"] == C["0"]["code"].dual_code() True - Sage : C["1"]["code"] == C["1"]["code"].dual_code() + sage: C["1"]["code"] == C["1"]["code"].dual_code() True - Sage : len(C.keys()) # number of inequiv sd codes of length 10 + sage: len(C.keys()) # number of inequiv sd codes of length 10 2 - Sage : C = self_dual_codes_binary(12)["12"] - Sage : C["0"]["code"] == C["0"]["code"].dual_code() + sage: C = self_dual_codes_binary(12)["12"] + sage: C["0"]["code"] == C["0"]["code"].dual_code() True - Sage : C["1"]["code"] == C["1"]["code"].dual_code() + sage: C["1"]["code"] == C["1"]["code"].dual_code() True - Sage : C["2"]["code"] == C["2"]["code"].dual_code() + sage: C["2"]["code"] == C["2"]["code"].dual_code() True These Sage commands simply show that the two inequivalent self-dual diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index b82a6a91713..2a683de7d17 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -5,6 +5,10 @@ ================================================= How to implement new algebraic structures in Sage ================================================= + +.. contents:: + :depth: 3 + -------------------------------------- Sage's category and coercion framework -------------------------------------- @@ -15,13 +19,8 @@ Sage's category and coercion framework © 2011/2013 -.. toctree:: - :maxdepth: 2 - .. linkall - - The aim of this tutorial is to explain how one can benefit from Sage's category framework and coercion model when implementing new algebraic structures. It is based on a worksheet created in 2011. @@ -105,27 +104,84 @@ it makes sense to build on top of the base class This base class provides a lot more methods than a general parent:: sage: [p for p in dir(Field) if p not in dir(Parent)] - ['__div__', '__fraction_field', '__ideal_monoid', '__iter__', - '__pow__', '__rdiv__', '__rpow__', '__rxor__', '__xor__', - '_an_element', '_an_element_c', '_an_element_impl', '_coerce_', - '_coerce_c', '_coerce_impl', '_coerce_self', '_coerce_try', - '_default_category', '_gens', '_gens_dict', - '_has_coerce_map_from', '_ideal_class_', '_latex_names', '_list', - '_one_element', '_pseudo_fraction_field', - '_random_nonzero_element', '_richcmp', '_unit_ideal', - '_zero_element', '_zero_ideal', 'algebraic_closure', - 'base_extend', 'cardinality', 'class_group', 'coerce_map_from_c', - 'coerce_map_from_impl', 'content', 'divides', 'extension', - 'fraction_field', 'frobenius_endomorphism', 'gcd', 'gen', 'gens', - 'get_action_c', 'get_action_impl', 'has_coerce_map_from_c', - 'has_coerce_map_from_impl', 'ideal', 'ideal_monoid', - 'integral_closure', 'is_commutative', 'is_field', 'is_finite', - 'is_integral_domain', 'is_integrally_closed', 'is_noetherian', - 'is_prime_field', 'is_ring', 'is_subring', - 'krull_dimension', 'list', 'ngens', 'one', 'one_element', - 'order', 'prime_subfield', 'principal_ideal', 'quo', 'quotient', - 'quotient_ring', 'random_element', 'unit_ideal', 'zero', - 'zero_element', 'zero_ideal', 'zeta', 'zeta_order'] + ['__div__', + '__fraction_field', + '__ideal_monoid', + '__iter__', + '__pow__', + '__rdiv__', + '__rpow__', + '__rxor__', + '__xor__', + '_an_element', + '_an_element_c', + '_an_element_impl', + '_coerce_', + '_coerce_c', + '_coerce_impl', + '_coerce_self', + '_coerce_try', + '_default_category', + '_gens', + '_gens_dict', + '_has_coerce_map_from', + '_ideal_class_', + '_latex_names', + '_list', + '_one_element', + '_pseudo_fraction_field', + '_random_nonzero_element', + '_richcmp', + '_unit_ideal', + '_zero_element', + '_zero_ideal', + 'algebraic_closure', + 'base_extend', + 'cardinality', + 'class_group', + 'coerce_map_from_c', + 'coerce_map_from_impl', + 'content', + 'divides', + 'epsilon', + 'extension', + 'fraction_field', + 'frobenius_endomorphism', + 'gcd', + 'gen', + 'gens', + 'get_action_c', + 'get_action_impl', + 'has_coerce_map_from_c', + 'has_coerce_map_from_impl', + 'ideal', + 'ideal_monoid', + 'integral_closure', + 'is_commutative', + 'is_field', + 'is_finite', + 'is_integral_domain', + 'is_integrally_closed', + 'is_noetherian', + 'is_prime_field', + 'is_ring', + 'is_subring', + 'krull_dimension', + 'list', + 'ngens', + 'one', + 'order', + 'prime_subfield', + 'principal_ideal', + 'quo', + 'quotient', + 'quotient_ring', + 'random_element', + 'unit_ideal', + 'zero', + 'zero_ideal', + 'zeta', + 'zeta_order'] The following is a very basic implementation of fraction fields, that needs to be complemented later. @@ -282,7 +338,7 @@ This gives rise to the following code:: ....: def __init__(self, parent,n,d=None): ....: B = parent.base() ....: if d is None: - ....: d = B.one_element() + ....: d = B.one() ....: if n not in B or d not in B: ....: raise ValueError("Numerator and denominator must be elements of %s"%B) ....: # Numerator and denominator should not just be "in" B, @@ -551,7 +607,7 @@ does not work, yet:: .. end of output The reason is that the ``sum`` method starts with the return value of -``P.zero_element()``, which defaults to ``P(0)``\---but the conversion of +``P.zero()``, which defaults to ``P(0)``\---but the conversion of integers into ``P`` is not implemented, yet. Implementing the category framework for the elements @@ -584,9 +640,9 @@ This little change provides several benefits: sage: P(1), P(2,3) ((1):(1), (2):(3)) -- There is a method ``zero_element`` returning the expected result:: +- There is a method ``zero`` returning the expected result:: - sage: P.zero_element() + sage: P.zero() (0):(1) - The ``sum`` method mentioned above suddenly works:: @@ -637,9 +693,9 @@ In particular, these elements are instances of that new dynamic class:: them as instances of ``self.__class__`` in the arithmetic methods of ``MyElement``. -``P.zero_element()`` defaults to returning ``P(0)`` and thus returns an +``P.zero()`` defaults to returning ``P(0)`` and thus returns an instance of ``P.element_class``. Since ``P.sum([...])`` starts the summation with -``P.zero_element()`` and the class of the sum only depends on the first +``P.zero()`` and the class of the sum only depends on the first summand, by our implementation, we have:: sage: type(a) @@ -1487,6 +1543,7 @@ Here are the tests that form the test suite of quotient fields:: '_test_elements_eq_transitive', '_test_elements_neq', '_test_euclidean_degree', + '_test_gcd_vs_xgcd', '_test_one', '_test_prod', '_test_quo_rem', '_test_some_elements', @@ -1538,6 +1595,7 @@ Let us see what tests are actually performed:: running ._test_elements_neq() . . . pass running ._test_eq() . . . pass running ._test_euclidean_degree() . . . pass + running ._test_gcd_vs_xgcd() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_one() . . . pass running ._test_pickling() . . . pass @@ -1706,6 +1764,7 @@ interesting. running ._test_elements_neq() . . . pass running ._test_eq() . . . pass running ._test_euclidean_degree() . . . pass + running ._test_gcd_vs_xgcd() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_one() . . . pass running ._test_pickling() . . . pass @@ -1747,7 +1806,7 @@ Appendix: The complete code B = parent.base() if d is None: # The default denominator is one - d = B.one_element() + d = B.one() # verify that both numerator and denominator belong to the base if n not in B or d not in B: raise ValueError("Numerator and denominator must be elements of %s"%B) diff --git a/src/doc/en/bordeaux_2008/birch.png b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/birch.png similarity index 100% rename from src/doc/en/bordeaux_2008/birch.png rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/birch.png diff --git a/src/doc/en/bordeaux_2008/birds_eye_view.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/birds_eye_view.rst similarity index 100% rename from src/doc/en/bordeaux_2008/birds_eye_view.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/birds_eye_view.rst diff --git a/src/doc/en/bordeaux_2008/birds_other.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/birds_other.rst similarity index 100% rename from src/doc/en/bordeaux_2008/birds_other.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/birds_other.rst diff --git a/src/doc/en/bordeaux_2008/conf.py b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/conf.py similarity index 100% rename from src/doc/en/bordeaux_2008/conf.py rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/conf.py diff --git a/src/doc/en/bordeaux_2008/elliptic_curves.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/elliptic_curves.rst similarity index 100% rename from src/doc/en/bordeaux_2008/elliptic_curves.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/elliptic_curves.rst diff --git a/src/doc/en/bordeaux_2008/generators_for_rings.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/generators_for_rings.rst similarity index 100% rename from src/doc/en/bordeaux_2008/generators_for_rings.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/generators_for_rings.rst diff --git a/src/doc/en/bordeaux_2008/half_integral.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/half_integral.rst similarity index 100% rename from src/doc/en/bordeaux_2008/half_integral.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/half_integral.rst diff --git a/src/doc/en/bordeaux_2008/index.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/index.rst similarity index 93% rename from src/doc/en/bordeaux_2008/index.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/index.rst index ef6c3679d5e..a5f503c2cef 100644 --- a/src/doc/en/bordeaux_2008/index.rst +++ b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/index.rst @@ -1,3 +1,5 @@ +.. _explicit_methods_in_number_theory: + Three Lectures about Explicit Methods in Number Theory Using Sage ================================================================= diff --git a/src/doc/en/bordeaux_2008/integer_factorization.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/integer_factorization.rst similarity index 100% rename from src/doc/en/bordeaux_2008/integer_factorization.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/integer_factorization.rst diff --git a/src/doc/en/bordeaux_2008/introduction.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/introduction.rst similarity index 100% rename from src/doc/en/bordeaux_2008/introduction.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/introduction.rst diff --git a/src/doc/en/bordeaux_2008/l_series.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/l_series.rst similarity index 100% rename from src/doc/en/bordeaux_2008/l_series.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/l_series.rst diff --git a/src/doc/en/bordeaux_2008/level_one_forms.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst similarity index 100% rename from src/doc/en/bordeaux_2008/level_one_forms.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst diff --git a/src/doc/en/bordeaux_2008/method_of_graphs.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/method_of_graphs.rst similarity index 100% rename from src/doc/en/bordeaux_2008/method_of_graphs.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/method_of_graphs.rst diff --git a/src/doc/en/bordeaux_2008/modabvar.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modabvar.rst similarity index 100% rename from src/doc/en/bordeaux_2008/modabvar.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modabvar.rst diff --git a/src/doc/en/bordeaux_2008/modpcurve.png b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modpcurve.png similarity index 100% rename from src/doc/en/bordeaux_2008/modpcurve.png rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modpcurve.png diff --git a/src/doc/en/bordeaux_2008/modular_forms.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms.rst similarity index 100% rename from src/doc/en/bordeaux_2008/modular_forms.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms.rst diff --git a/src/doc/en/bordeaux_2008/modular_forms_and_hecke_operators.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst similarity index 100% rename from src/doc/en/bordeaux_2008/modular_forms_and_hecke_operators.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst diff --git a/src/doc/en/bordeaux_2008/modular_symbols.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_symbols.rst similarity index 100% rename from src/doc/en/bordeaux_2008/modular_symbols.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_symbols.rst diff --git a/src/doc/en/bordeaux_2008/nf_galois_groups.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/nf_galois_groups.rst similarity index 100% rename from src/doc/en/bordeaux_2008/nf_galois_groups.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/nf_galois_groups.rst diff --git a/src/doc/en/bordeaux_2008/nf_introduction.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/nf_introduction.rst similarity index 100% rename from src/doc/en/bordeaux_2008/nf_introduction.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/nf_introduction.rst diff --git a/src/doc/en/bordeaux_2008/nf_orders.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/nf_orders.rst similarity index 100% rename from src/doc/en/bordeaux_2008/nf_orders.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/nf_orders.rst diff --git a/src/doc/en/bordeaux_2008/number_fields.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/number_fields.rst similarity index 100% rename from src/doc/en/bordeaux_2008/number_fields.rst rename to src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/number_fields.rst diff --git a/src/doc/en/thematic_tutorials/group_theory.rst b/src/doc/en/thematic_tutorials/group_theory.rst index 28e53f96f04..4519187cd6c 100644 --- a/src/doc/en/thematic_tutorials/group_theory.rst +++ b/src/doc/en/thematic_tutorials/group_theory.rst @@ -7,17 +7,11 @@ Group Theory and Sage .. MODULEAUTHOR:: Robert A. Beezer, University of Puget Sound -Changelog: - -* 2009/01/30 Version 1.0, first complete release -* 2009/03/03 Version 1.1, added cyclic group size interact -* 2010/03/10 Version 1.3, dropped US on license, some edits. - This compilation collects Sage commands that are useful for a student in an introductory course on group theory. It is not intended to teach Sage or to teach group theory. (There are many introductory texts on group theory and more information on Sage can be found via -www.sagemath.org.) Rather, by presenting commands roughly in the +``_) Rather, by presenting commands roughly in the order a student would learn the corresponding mathematics they might be encouraged to experiment and learn more about mathematics and learn more about Sage. Not coincidentally, when Sage was the acronym SAGE, @@ -31,6 +25,14 @@ link below each cell, for a fully interactive experience. A PDF and Sage worksheet versions of this tutorial are available at http://abstract.ups.edu/sage-aata.html. +.. contents:: Table of contents + :depth: 2 + +Changelog: + +* 2009/01/30 Version 1.0, first complete release +* 2009/03/03 Version 1.1, added cyclic group size interact +* 2010/03/10 Version 1.3, dropped US on license, some edits. Basic properties of the integers ================================ diff --git a/src/doc/en/thematic_tutorials/index.rst b/src/doc/en/thematic_tutorials/index.rst index 0ace85efce9..5b3dc5fc757 100644 --- a/src/doc/en/thematic_tutorials/index.rst +++ b/src/doc/en/thematic_tutorials/index.rst @@ -5,9 +5,8 @@ Welcome to the Sage Thematic Tutorials! ======================================= -This is an index, grouped by theme, of Sage demonstrations, quick -reference cards, primers, and thematic tutorials, licensed under -a `Creative Commons Attribution-Share Alike 3.0 License `_. +Here you will find Sage demonstrations, quick reference cards, primers, and +thematic tutorials, .. To be reinstated once we have some of them in the Sage sources! .. - A *demonstration* is a short document giving a broad view of the @@ -23,29 +22,37 @@ a `Creative Commons Attribution-Share Alike 3.0 License `_. +This documentation is licensed under a `Creative Commons Attribution-Share Alike +3.0 License `_. Introduction to Sage -==================== +-------------------- * `Logging on to a Sage Server and Creating a Worksheet (PREP) <../prep/Logging-On.html>`_ * `Introductory Sage Tutorial (PREP) <../prep/Intro-Tutorial.html>`_ * :ref:`tutorial-notebook-and-help-long` * `Sage's main tutorial <../tutorial/>`_ +.. _programming_design: + +Introduction to Python +---------------------- -See also the :ref:`Python and Sage programming tutorials ` below. +* `Tutorial: Sage Introductory Programming (PREP) <../prep/Programming.html>`_ +* :ref:`tutorial-programming-python` +* :ref:`tutorial-comprehensions` +* :ref:`tutorial-objects-and-classes` +* :ref:`functional_programming` Calculus and plotting -===================== +--------------------- * `Tutorial: Symbolics and Plotting (PREP) <../prep/Symbolics-and-Basic-Plotting.html>`_ * `Tutorial: Calculus (PREP) <../prep/Calculus.html>`_ * `Tutorial: Advanced-2D Plotting (PREP) <../prep/Advanced-2DPlotting.html>`_ Algebra -======= +------- * :ref:`group_theory` * :ref:`lie` @@ -55,24 +62,21 @@ Number Theory * :ref:`numtheory_rsa` * :ref:`sage.rings.padics.tutorial` - -Coding Theory -------------- - -* :ref:`coding_theory` +* :ref:`explicit_methods_in_number_theory` .. Monoids, Groups, representation Theory .. -------------------------------------- Geometry -======== +-------- * :ref:`polytutorial` Combinatorics -============= +------------- * :ref:`sage.combinat.tutorial` +* :ref:`coding_theory` Algebraic Combinatorics ----------------------- @@ -83,40 +87,39 @@ Algebraic Combinatorics * :ref:`sage.combinat.root_system.plot` * :ref:`abelian_sandpile_model` +Parents/Elements, Categories and algebraic structures +----------------------------------------------------- + +* :ref:`coercion_and_categories` +* :ref:`sage.categories.primer` +* :ref:`sage.categories.tutorial` + + Numerical computations ---------------------- * :ref:`numerical_computing` * :ref:`linear_programming` +Advanced programming +-------------------- + +* :ref:`cython_interface` + .. Words .. ----- .. Dynamics .. -------- -.. _programming_design: +Documentation +============= -Programming and Design -====================== - -* `Tutorial: Sage Introductory Programming (PREP) <../prep/Programming.html>`_ -* :ref:`tutorial-programming-python` -* :ref:`tutorial-comprehensions` -* :ref:`tutorial-objects-and-classes` -* :ref:`functional_programming` -* :ref:`cython_interface` +* :ref:`sws2srt` .. Sage development .. ---------------- -Modeling Mathematics on a computer ----------------------------------- - -* :ref:`coercion_and_categories` -* :ref:`sage.categories.primer` -* :ref:`sage.categories.tutorial` - Indices and tables ================== diff --git a/src/doc/en/thematic_tutorials/lie.rst b/src/doc/en/thematic_tutorials/lie.rst index 9fccce5e4f1..49c00e32825 100644 --- a/src/doc/en/thematic_tutorials/lie.rst +++ b/src/doc/en/thematic_tutorials/lie.rst @@ -11,10 +11,6 @@ These notes explain how to use the mathematical software Sage for Lie group computations. Sage also contains many combinatorial algorithms. We will cover only some of these. -Preparation of this document was supported in part by NSF grants DMS-0652817, -DMS-1001079, OCI-1147463, DMS--0652641, DMS--0652652, DMS--1001256 and -and OCI–1147247. - .. toctree:: :maxdepth: 2 @@ -31,3 +27,6 @@ and OCI–1147247. lie/kazhdan_lusztig_polynomials lie/bibliography +Preparation of this document was supported in part by NSF grants DMS-0652817, +DMS-1001079, OCI-1147463, DMS--0652641, DMS--0652652, DMS--1001256 and +and OCI–1147247. diff --git a/src/doc/en/thematic_tutorials/linear_programming.rst b/src/doc/en/thematic_tutorials/linear_programming.rst index dd21778a494..78c6a16a476 100644 --- a/src/doc/en/thematic_tutorials/linear_programming.rst +++ b/src/doc/en/thematic_tutorials/linear_programming.rst @@ -1,6 +1,5 @@ .. _linear_programming: - Linear Programming (Mixed Integer) ================================== @@ -16,7 +15,6 @@ constraints. This is a translation of a chapter from the book `Calcul mathematique avec Sage `_. - Definition ---------- diff --git a/src/doc/en/thematic_tutorials/sws2rst.rst b/src/doc/en/thematic_tutorials/sws2rst.rst new file mode 100644 index 00000000000..451ebdf5c15 --- /dev/null +++ b/src/doc/en/thematic_tutorials/sws2rst.rst @@ -0,0 +1,76 @@ +.. _sws2srt: + +==================================== +Creating a Tutorial from a Worksheet +==================================== + +Sage has a number of `thematic tutorials `_ and contains everything +needed to turn a worksheet created in the `Sage notebook +`_ (sagenb) into a tutorial. + +* Once you have created a worksheet and are satisfied with the text and + computations, download it to a directory. + +We will assume here that the worksheet is called ``Tutorial.sws`` +and the directory is called ``make_tutorial``. We also assume that +``sage`` is your Sage command; if it is not in your ``PATH`` then replace +this with the path to your Sage installation, such as +``/Applications/Sage-6.2.app/Contents/Resources/sage/sage`` if you are +using the Mac app and have placed it in your Applications directory. + +* Next, you will need an optional package to parse your worksheet. Use the + command:: + + sage -i beautifulsoup + + to install it (or, in the Mac app, use the ``Terminal Session`` advanced + menu with ``-i beautifulsoup``). + +* Then we will use the ``sws2rst`` script to turn the worksheet into + a document in the `ReStructuredText `_ + format. Be sure you are in the same directory as the worksheet:: + + sage --sws2rst Tutorial.sws + + This will create an ``.rst`` file along with a subdirectory of image + files (which may be empty if there are no images). + + You can find help for ``sws2rst`` with the command + ``sage --sws2rst -h`` once you have installed beautifulsoup. + +* In principle, such a file could be added directly to Sage's documentation (see + the `developer's manual <../developer/index.html>`_). However, you probably + want to check whether it looks right first. So next we will compile this file + to html documentation. + + * Follow the instructions of ``sage --sws2rst --sphinxify``. First, + we will open a Sage shell session, where all appropriate Sage + references already work properly:: + + sage --sh + + From here, you should be able to just type:: + + sphinx-quickstart + + and then respond to prompts for turning your ``.rst`` file into + documentation. For most of them you can just hit enter/return to + accept the defaults. However, you will probably want to + + * Enter a name for the project + * Enter a name for you + * Type ``y`` for the question about using MathJax + + Keep note of the instructions; the main other thing to do is add + your file's name to ``index.rst``, and then just do:: + + make html + + and wait while magic happens. To see the results, open the file + ``make_tutorial/_build/html/Tutorial.html`` with a browser, or + use your graphical file system to navigate to the same place. + +* Now you can modify the ``.rst`` file more and repeat the steps + of compiling it until it is ready for inclusion, or just for distribution + among other Sage users as an HTML file. (Do ``make pdf`` for a PDF + version.) diff --git a/src/doc/en/thematic_tutorials/toctree.rst b/src/doc/en/thematic_tutorials/toctree.rst index 0ac611f4e9a..0a6b1816228 100644 --- a/src/doc/en/thematic_tutorials/toctree.rst +++ b/src/doc/en/thematic_tutorials/toctree.rst @@ -21,3 +21,5 @@ Thematic tutorial document tree coercion_and_categories cython_interface numerical_sage/index + explicit_methods_in_number_theory/index + sws2rst diff --git a/src/doc/en/thematic_tutorials/tutorial-comprehensions.rst b/src/doc/en/thematic_tutorials/tutorial-comprehensions.rst index baccb659776..cfd999b0bff 100644 --- a/src/doc/en/thematic_tutorials/tutorial-comprehensions.rst +++ b/src/doc/en/thematic_tutorials/tutorial-comprehensions.rst @@ -89,16 +89,16 @@ a device which runs through a bunch of objects, returning one at each call to the ``next`` method. Iterators are built using parentheses:: sage: it = (binomial(8, i) for i in range(9)) - sage: it.next() + sage: next(it) 1 :: - sage: it.next() + sage: next(it) 8 - sage: it.next() + sage: next(it) 28 - sage: it.next() + sage: next(it) 56 You can get the list of the results that are not yet *consumed*:: @@ -108,7 +108,7 @@ You can get the list of the results that are not yet *consumed*:: Asking for more elements triggers a ``StopIteration`` exception:: - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -189,7 +189,7 @@ should hold:: An alternative way to achieve this is:: sage: counter_examples = (p for p in range(1000) if is_prime(p) and not is_prime(mersenne(p))) - sage: counter_examples.next() + sage: next(counter_examples) 11 .. TOPIC:: Exercises @@ -373,5 +373,5 @@ Infinite loops can nevertheless be very useful:: sage: counter_examples = (p for p in Primes() if not is_prime(mersenne(p))) - sage: counter_examples.next() + sage: next(counter_examples) 11 \ No newline at end of file diff --git a/src/doc/en/thematic_tutorials/tutorial-programming-python.rst b/src/doc/en/thematic_tutorials/tutorial-programming-python.rst index b3835de9c4c..e5259027be5 100644 --- a/src/doc/en/thematic_tutorials/tutorial-programming-python.rst +++ b/src/doc/en/thematic_tutorials/tutorial-programming-python.rst @@ -1111,22 +1111,22 @@ How does this work? sage: it = iter(GF(5)); it - sage: it.next() + sage: next(it) 0 - sage: it.next() + sage: next(it) 1 - sage: it.next() + sage: next(it) 2 - sage: it.next() + sage: next(it) 3 - sage: it.next() + sage: next(it) 4 - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration diff --git a/src/doc/en/tutorial/programming.rst b/src/doc/en/tutorial/programming.rst index 5aae15d2703..bc510d02e42 100644 --- a/src/doc/en/tutorial/programming.rst +++ b/src/doc/en/tutorial/programming.rst @@ -527,11 +527,11 @@ nonnegative integers up to :math:`10000000`. :: sage: v = (n^2 for n in xrange(10000000)) - sage: v.next() + sage: next(v) 0 - sage: v.next() + sage: next(v) 1 - sage: v.next() + sage: next(v) 4 We create an iterate over the primes of the form :math:`4p+1` @@ -542,11 +542,11 @@ with :math:`p` also prime, and look at the first few values. sage: w = (4*p + 1 for p in Primes() if is_prime(4*p+1)) sage: w # in the next line, 0xb0853d6c is a random 0x number - sage: w.next() + sage: next(w) 13 - sage: w.next() + sage: next(w) 29 - sage: w.next() + sage: next(w) 53 Certain rings, e.g., finite fields and the integers have iterators @@ -557,11 +557,11 @@ associated to them: sage: [x for x in GF(7)] [0, 1, 2, 3, 4, 5, 6] sage: W = ((x,y) for x in ZZ for y in ZZ) - sage: W.next() + sage: next(W) (0, 0) - sage: W.next() + sage: next(W) (0, 1) - sage: W.next() + sage: next(W) (0, -1) Loops, Functions, Control Statements, and Comparisons diff --git a/src/doc/en/website/templates/index.html b/src/doc/en/website/templates/index.html index f3577e4d97c..4b94be6eb23 100644 --- a/src/doc/en/website/templates/index.html +++ b/src/doc/en/website/templates/index.html @@ -261,30 +261,6 @@

- - - - - - - - - {% endblock %} diff --git a/src/doc/fr/tutorial/programming.rst b/src/doc/fr/tutorial/programming.rst index 5ed6e8355c4..f4995b4ee29 100644 --- a/src/doc/fr/tutorial/programming.rst +++ b/src/doc/fr/tutorial/programming.rst @@ -543,11 +543,11 @@ d'entiers positifs jusqu'à :math:`10000000`. :: sage: v = (n^2 for n in xrange(10000000)) - sage: v.next() + sage: next(v) 0 - sage: v.next() + sage: next(v) 1 - sage: v.next() + sage: next(v) 4 Nous créons maintenant un itérateur sur les nombres premiers de la forme @@ -559,11 +559,11 @@ quelques premières valeurs qu'il prend. sage: w = (4*p + 1 for p in Primes() if is_prime(4*p+1)) sage: w at 0x...> - sage: w.next() + sage: next(w) 13 - sage: w.next() + sage: next(w) 29 - sage: w.next() + sage: next(w) 53 Certains anneaux, par exemple les corps finis et les entiers, disposent @@ -574,11 +574,11 @@ d'itérateurs associés : sage: [x for x in GF(7)] [0, 1, 2, 3, 4, 5, 6] sage: W = ((x,y) for x in ZZ for y in ZZ) - sage: W.next() + sage: next(W) (0, 0) - sage: W.next() + sage: next(W) (0, 1) - sage: W.next() + sage: next(W) (0, -1) Boucles, fonctions, structures de contrôle et comparaisons diff --git a/src/doc/ru/tutorial/programming.rst b/src/doc/ru/tutorial/programming.rst index c8dcea4de9a..6b831e3d9bc 100644 --- a/src/doc/ru/tutorial/programming.rst +++ b/src/doc/ru/tutorial/programming.rst @@ -511,11 +511,11 @@ http://docs.python.org/lib/typesmapping.html) произвольным объе :: sage: v = (n^2 for n in xrange(10000000)) - sage: v.next() + sage: next(v) 0 - sage: v.next() + sage: next(v) 1 - sage: v.next() + sage: next(v) 4 Следующий пример - создание итераторов из простых чисел вида :math:`4p+1` с @@ -526,11 +526,11 @@ http://docs.python.org/lib/typesmapping.html) произвольным объе sage: w = (4*p + 1 for p in Primes() if is_prime(4*p+1)) sage: w # random output на следующей строке 0xb0853d6c может быть другим шестнадцатиричным числом - sage: w.next() + sage: next(w) 13 - sage: w.next() + sage: next(w) 29 - sage: w.next() + sage: next(w) 53 Определенные кольца, как и конечные поля и целые числа, имеют итераторы: @@ -540,11 +540,11 @@ http://docs.python.org/lib/typesmapping.html) произвольным объе sage: [x for x in GF(7)] [0, 1, 2, 3, 4, 5, 6] sage: W = ((x,y) for x in ZZ for y in ZZ) - sage: W.next() + sage: next(W) (0, 0) - sage: W.next() + sage: next(W) (0, 1) - sage: W.next() + sage: next(W) (0, -1) Циклы, функции, управляющие конструкции и сравнения diff --git a/src/module_list.py b/src/module_list.py index cc1b3500c87..8215bac26e8 100755 --- a/src/module_list.py +++ b/src/module_list.py @@ -157,26 +157,7 @@ def uname_specific(name, value, alternative): ## ################################ - Extension('sage.categories.action', - sources = ['sage/categories/action.pyx']), - - Extension('sage.categories.category_cy_helper', - sources = ['sage/categories/category_cy_helper.pyx']), - - Extension('sage.categories.category_singleton', - sources = ['sage/categories/category_singleton.pyx']), - - Extension('sage.categories.functor', - sources = ['sage/categories/functor.pyx']), - - Extension('sage.categories.map', - sources = ['sage/categories/map.pyx']), - - Extension('sage.categories.morphism', - sources = ['sage/categories/morphism.pyx']), - - Extension('sage.categories.examples.semigroups_cython', - sources = ['sage/categories/examples/semigroups_cython.pyx']), + Extension('*', ['sage/categories/**/*.pyx']), ################################ ## @@ -184,18 +165,13 @@ def uname_specific(name, value, alternative): ## ################################ - Extension('sage.coding.binary_code', - sources = ['sage/coding/binary_code.pyx'], - libraries = ['gmp']), - Extension('sage.coding.codecan.codecan', sources = ['sage/coding/codecan/codecan.pyx'], libraries = ['gmp', 'flint'], include_dirs = ['sage/groups/perm_gps/partn_ref2/'], depends = flint_depends), - Extension('sage.coding.codecan.autgroup_can_label', - sources = ['sage/coding/codecan/autgroup_can_label.pyx']), + Extension('*', ['sage/coding/**/*.pyx']), ################################ ## @@ -299,25 +275,7 @@ def uname_specific(name, value, alternative): ## ################################ - Extension('sage.ext.c_lib', - sources = ['sage/ext/c_lib.pyx']), - - Extension('sage.ext.fast_callable', - sources = ['sage/ext/fast_callable.pyx']), - - Extension('sage.ext.fast_eval', - sources = ['sage/ext/fast_eval.pyx']), - - Extension('sage.ext.interactive_constructors_c', - sources = ['sage/ext/interactive_constructors_c.pyx']), - - Extension('sage.ext.multi_modular', - sources = ['sage/ext/multi_modular.pyx'], - extra_compile_args = ['-std=c99'], - libraries=['gmp']), - - Extension('sage.ext.pselect', - sources = ['sage/ext/pselect.pyx']), + Extension('*', ['sage/ext/*.pyx']), ################################ ## @@ -430,7 +388,8 @@ def uname_specific(name, value, alternative): libraries = ['gmp']), Extension('sage.graphs.base.static_dense_graph', - sources = ['sage/graphs/base/static_dense_graph.pyx']), + sources = ['sage/graphs/base/static_dense_graph.pyx'], + libraries = ['gmp']), Extension('sage.graphs.base.static_sparse_graph', sources = ['sage/graphs/base/static_sparse_graph.pyx'], @@ -1230,90 +1189,7 @@ def uname_specific(name, value, alternative): ## ################################ - Extension('sage.misc.allocator', - sources = ['sage/misc/allocator.pyx']), - - Extension('sage.misc.cachefunc', - sources = ['sage/misc/cachefunc.pyx']), - - Extension('sage.misc.citation', - sources = ['sage/misc/citation.pyx']), - - Extension('sage.misc.constant_function', - sources = ['sage/misc/constant_function.pyx']), - - Extension('sage.misc.cython_c', - sources = ['sage/misc/cython_c.pyx']), - - Extension('sage.misc.c3', - sources = ['sage/misc/c3.pyx']), - - Extension('sage.misc.c3_controlled', - sources = ['sage/misc/c3_controlled.pyx']), - - Extension('sage.misc.derivative', - sources = ['sage/misc/derivative.pyx']), - - Extension('sage.misc.fpickle', - sources = ['sage/misc/fpickle.pyx']), - - Extension('sage.misc.function_mangling', - sources = ['sage/misc/function_mangling.pyx']), - - Extension('sage.misc.lazy_attribute', - sources = ['sage/misc/lazy_attribute.pyx']), - - Extension('sage.misc.lazy_import', - sources = ['sage/misc/lazy_import.pyx']), - - Extension('sage.misc.lazy_list', - sources = ['sage/misc/lazy_list.pyx']), - - Extension('sage.misc.misc_c', - sources = ['sage/misc/misc_c.pyx']), - - Extension('sage.misc.nested_class', - sources = ['sage/misc/nested_class.pyx']), - - Extension('sage.misc.parser', - sources = ['sage/misc/parser.pyx']), - - Extension('sage.misc.pickle_old', - sources = ['sage/misc/pickle_old.pyx']), - - Extension('sage.misc.randstate', - sources = ['sage/misc/randstate.pyx'], - libraries = ['gmp']), - - Extension('sage.misc.refcount', - sources = ['sage/misc/refcount.pyx']), - - Extension('sage.misc.reset', - sources = ['sage/misc/reset.pyx']), - - Extension('sage.misc.sage_timeit_class', - sources = ['sage/misc/sage_timeit_class.pyx']), - - Extension('sage.misc.classcall_metaclass', - sources = ['sage/misc/classcall_metaclass.pyx']), - - Extension('sage.misc.fast_methods', - sources = ['sage/misc/fast_methods.pyx']), - - Extension('sage.misc.binary_tree', - sources = ['sage/misc/binary_tree.pyx']), - - Extension('sage.misc.search', - sources = ['sage/misc/search.pyx']), - - Extension('sage.misc.session', - sources = ['sage/misc/session.pyx']), - - Extension('sage.misc.stopgap', - sources = ['sage/misc/stopgap.pyx']), - - Extension('sage.misc.weak_dict', - sources = ['sage/misc/weak_dict.pyx']), + Extension('*', ['sage/misc/*.pyx']), ################################ ## @@ -2080,9 +1956,6 @@ def uname_specific(name, value, alternative): Extension('sage.structure.sage_object', sources = ['sage/structure/sage_object.pyx']), - Extension('sage.structure.wrapper_parent', - sources = ['sage/structure/wrapper_parent.pyx']), - ################################ ## ## sage.symbolic @@ -2109,11 +1982,6 @@ def uname_specific(name, value, alternative): Extension('sage.tests.interrupt', sources = ['sage/tests/interrupt.pyx', 'sage/tests/c_lib.c']), - Extension('sage.tests.parallel', - sources = ['sage/tests/parallel.pyx'], - extra_compile_args=["-fopenmp"], - extra_link_args=["-fopenmp"]), - Extension('sage.tests.stl_vector', sources = ['sage/tests/stl_vector.pyx'], libraries = ['gmp'], diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py index 3e9fab6156f..588677e80c9 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py @@ -230,7 +230,7 @@ def __iter__(self): """ if not self.is_finite(): raise NotImplementedError("object does not support iteration") - V = self.zero_element().vector().parent() + V = self.zero().vector().parent() for v in V: yield self(v) @@ -541,7 +541,7 @@ def random_element(self, *args, **kwargs): sage: B.random_element(num_bound=1000) # random 215/981*e0 + 709/953*e1 + 931/264*e2 """ - return self(self.zero_element().vector().parent().random_element(*args, **kwargs)) + return self(self.zero().vector().parent().random_element(*args, **kwargs)) def _is_valid_homomorphism_(self, other, im_gens): """ diff --git a/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx b/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx index 9951296cf2f..d27596372f5 100644 --- a/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx +++ b/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx @@ -710,7 +710,7 @@ cdef class FreeAlgebraElement_letterplace(AlgebraElement): cdef FreeAlgebra_letterplace P = self._parent if not isinstance(G,(list,tuple)): if G==P: - return P.zero_element() + return P.zero() if not (isinstance(G,MPolynomialIdeal) and G.ring()==P._current_ring): G = G.gens() C = P.current_ring() diff --git a/src/sage/algebras/letterplace/free_algebra_letterplace.pyx b/src/sage/algebras/letterplace/free_algebra_letterplace.pyx index be8de6aaa76..56efa2a52b4 100644 --- a/src/sage/algebras/letterplace/free_algebra_letterplace.pyx +++ b/src/sage/algebras/letterplace/free_algebra_letterplace.pyx @@ -830,7 +830,7 @@ cdef class FreeAlgebra_letterplace(Algebra): """ if not D: - return self.zero_element() + return self.zero() cdef int l for e in D.iterkeys(): l = len(e) diff --git a/src/sage/algebras/letterplace/letterplace_ideal.pyx b/src/sage/algebras/letterplace/letterplace_ideal.pyx index 7142924b1d4..86647776dfb 100644 --- a/src/sage/algebras/letterplace/letterplace_ideal.pyx +++ b/src/sage/algebras/letterplace/letterplace_ideal.pyx @@ -338,7 +338,7 @@ class LetterplaceIdeal(Ideal_nc): P = self.ring() if not isinstance(G,(list,tuple)): if G==P: - return P.ideal([P.zero_element()]) + return P.ideal([P.zero()]) if G in P: return G.normal_form(self) G = G.gens() diff --git a/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx b/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx index 124ffa4441b..3fad5a14cd3 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx +++ b/src/sage/algebras/quatalg/quaternion_algebra_cython.pyx @@ -215,7 +215,7 @@ def rational_quaternions_from_integral_matrix_and_denom(A, Matrix_integer_dense rng = range(H.nrows()) for i in rng: - x = PY_NEW(QuaternionAlgebraElement_rational_field) + x = QuaternionAlgebraElement_rational_field.__new__(QuaternionAlgebraElement_rational_field) x._parent = A mpz_set(x.a, a.value) mpz_set(x.b, b.value) diff --git a/src/sage/algebras/quatalg/quaternion_algebra_element.pyx b/src/sage/algebras/quatalg/quaternion_algebra_element.pyx index 93cc5ed1b13..dca972de9a7 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra_element.pyx +++ b/src/sage/algebras/quatalg/quaternion_algebra_element.pyx @@ -744,7 +744,7 @@ cdef class QuaternionAlgebraElement_generic(QuaternionAlgebraElement_abstract): """ cdef QuaternionAlgebraElement_generic right = _right - # TODO -- make this, etc. use PY_NEW + # TODO -- make this, etc. use __new__ return QuaternionAlgebraElement_generic(self._parent, (self.x + right.x, self.y + right.y, self.z + right.z, self.w + right.w), check=False) cpdef ModuleElement _sub_(self, ModuleElement _right): @@ -1112,7 +1112,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst # by the gcd of d3, x3, y3, z3, and w3 cdef QuaternionAlgebraElement_rational_field right = _right - cdef QuaternionAlgebraElement_rational_field result = PY_NEW(QuaternionAlgebraElement_rational_field) + cdef QuaternionAlgebraElement_rational_field result = QuaternionAlgebraElement_rational_field.__new__(QuaternionAlgebraElement_rational_field) result._parent = self._parent mpz_mul(U1, self.x, right.d) # U1 = x1 * d2 @@ -1150,7 +1150,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst 4/3 + 3/2*i """ cdef QuaternionAlgebraElement_rational_field right = _right - cdef QuaternionAlgebraElement_rational_field result = PY_NEW(QuaternionAlgebraElement_rational_field) + cdef QuaternionAlgebraElement_rational_field result = QuaternionAlgebraElement_rational_field.__new__(QuaternionAlgebraElement_rational_field) result._parent = self._parent # Implementation Note: To obtain _sub_, we simply replace every occurrence of @@ -1228,7 +1228,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst cdef QuaternionAlgebraElement_rational_field right = _right - cdef QuaternionAlgebraElement_rational_field result = PY_NEW(QuaternionAlgebraElement_rational_field) + cdef QuaternionAlgebraElement_rational_field result = QuaternionAlgebraElement_rational_field.__new__(QuaternionAlgebraElement_rational_field) result._parent = self._parent mpz_set(result.a, self.a) @@ -1329,7 +1329,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst mpz_mul(U2, self.d, self.d) - cdef Rational result = PY_NEW(Rational) + cdef Rational result = Rational.__new__(Rational) mpq_set_num(result.value, U1) mpq_set_den(result.value, U2) mpq_canonicalize(result.value) @@ -1353,7 +1353,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst 1 - 1/3*i - 1/5*j + 1/7*k """ - cdef QuaternionAlgebraElement_rational_field result = PY_NEW(QuaternionAlgebraElement_rational_field) + cdef QuaternionAlgebraElement_rational_field result = QuaternionAlgebraElement_rational_field.__new__(QuaternionAlgebraElement_rational_field) result._parent = self._parent mpz_set(result.a, self.a) @@ -1385,7 +1385,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst #return 2*self[0] mpz_mul_si(U1, self.x, 2) - cdef Rational result = PY_NEW(Rational) + cdef Rational result = Rational.__new__(Rational) mpq_set_num(result.value, U1) mpq_set_den(result.value, self.d) mpq_canonicalize(result.value) @@ -1550,7 +1550,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst sage: 5*a == a._multiply_by_integer(5) True """ - cdef QuaternionAlgebraElement_rational_field result = PY_NEW(QuaternionAlgebraElement_rational_field) + cdef QuaternionAlgebraElement_rational_field result = QuaternionAlgebraElement_rational_field.__new__(QuaternionAlgebraElement_rational_field) result._parent = self._parent mpz_set(result.a, self.a) @@ -1593,7 +1593,7 @@ cdef class QuaternionAlgebraElement_rational_field(QuaternionAlgebraElement_abst if mpz_sgn(n.value) == 0: raise ZeroDivisionError - cdef QuaternionAlgebraElement_rational_field result = PY_NEW(QuaternionAlgebraElement_rational_field) + cdef QuaternionAlgebraElement_rational_field result = QuaternionAlgebraElement_rational_field.__new__(QuaternionAlgebraElement_rational_field) result._parent = self._parent mpz_set(result.a, self.a) @@ -1788,7 +1788,7 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra # a modulus that is not monic. cdef QuaternionAlgebraElement_number_field right = _right - cdef QuaternionAlgebraElement_number_field result = PY_NEW(QuaternionAlgebraElement_number_field) + cdef QuaternionAlgebraElement_number_field result = QuaternionAlgebraElement_number_field.__new__(QuaternionAlgebraElement_number_field) fmpz_poly_set(result.a, self.a) fmpz_poly_set(result.b, self.b) @@ -1837,7 +1837,7 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra # currently be an issue because it is impossible to create a number field with # a modulus that is not monic. cdef QuaternionAlgebraElement_number_field right = _right - cdef QuaternionAlgebraElement_number_field result = PY_NEW(QuaternionAlgebraElement_number_field) + cdef QuaternionAlgebraElement_number_field result = QuaternionAlgebraElement_number_field.__new__(QuaternionAlgebraElement_number_field) fmpz_poly_set(result.a, self.a) @@ -1916,7 +1916,7 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra # There might be a way to optimize this formula further. cdef QuaternionAlgebraElement_number_field right = _right - cdef QuaternionAlgebraElement_number_field result = PY_NEW(QuaternionAlgebraElement_number_field) + cdef QuaternionAlgebraElement_number_field result = QuaternionAlgebraElement_number_field.__new__(QuaternionAlgebraElement_number_field) mpz_set_si(result.d, 1) diff --git a/src/sage/algebras/steenrod/steenrod_algebra_bases.py b/src/sage/algebras/steenrod/steenrod_algebra_bases.py index 34fabab5d41..3c18148dffc 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_bases.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_bases.py @@ -905,7 +905,7 @@ def sorting_pair(s,t,basis): # pair used for sorting the basis elif basis.find('revz') >= 0: return (s+t,s) - from sage.misc.misc import prod + from sage.misc.all import prod from sage.rings.infinity import Infinity profile = kwds.get("profile", None) trunc = kwds.get("truncation_type", None) @@ -1044,7 +1044,7 @@ def sorting_pair(s,t,basis): # pair used for sorting the basis return ((),) else: return (((), ()),) - from sage.misc.misc import prod + from sage.misc.all import prod from sage.rings.all import Integer from sage.rings.infinity import Infinity from sage.combinat.integer_vector_weighted import WeightedIntegerVectors diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index a85c0c91629..1c8705f77d9 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -17,7 +17,7 @@ from sage.misc.latex import latex from sage.structure.element import AlgebraElement, get_coercion_model from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent from copy import copy import operator from sage.categories.rings import Rings @@ -692,7 +692,7 @@ def basis(self): sage: W. = DifferentialWeylAlgebra(QQ) sage: B = W.basis() sage: it = iter(B) - sage: [it.next() for i in range(20)] + sage: [next(it) for i in range(20)] [1, x, y, dx, dy, x^2, x*y, x*dx, x*dy, y^2, y*dx, y*dy, dx^2, dx*dy, dy^2, x^3, x^2*y, x^2*dx, x^2*dy, x*y^2] """ diff --git a/src/sage/calculus/desolvers.py b/src/sage/calculus/desolvers.py index ac28e833249..44933d9384b 100644 --- a/src/sage/calculus/desolvers.py +++ b/src/sage/calculus/desolvers.py @@ -366,7 +366,7 @@ def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False) TESTS: - Trac #9961 fixed (allow assumptions on the dependent variable in desolve):: + :trac:`9961` fixed (allow assumptions on the dependent variable in desolve):: sage: y=function('y',x); assume(x>0); assume(y>0) sage: sage.calculus.calculus.maxima('domain:real') # needed since Maxima 5.26.0 to get the answer as below @@ -374,7 +374,7 @@ def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False) sage: desolve(x*diff(y,x)-x*sqrt(y^2+x^2)-y == 0, y, contrib_ode=True) [x - arcsinh(y(x)/x) == _C] - Trac #10682 updated Maxima to 5.26, and it started to show a different + :trac:`10682` updated Maxima to 5.26, and it started to show a different solution in the complex domain for the ODE above:: sage: sage.calculus.calculus.maxima('domain:complex') # back to the default complex domain @@ -385,7 +385,7 @@ def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False) log(4*(2*x^2*sqrt((x^2*y(x)^2 + y(x)^4)/x^2)*sqrt(x^(-2)) + x^2 + 2*y(x)^2)/x^2))/(x*sqrt(x^(-2))) == _C] - Trac #6479 fixed:: + :trac:`6479` fixed:: sage: x = var('x') sage: y = function('y', x) @@ -397,7 +397,7 @@ def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False) sage: desolve( diff(y,x,x) == 0, y, [0,1,1]) x + 1 - Trac #9835 fixed:: + :trac:`9835` fixed:: sage: x = var('x') sage: y = function('y', x) @@ -406,12 +406,19 @@ def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False) ... NotImplementedError: Unable to use initial condition for this equation (freeofx). - Trac #8931 fixed:: + :trac:`8931` fixed:: sage: x=var('x'); f=function('f',x); k=var('k'); assume(k>0) sage: desolve(diff(f,x,2)/f==k,f,ivar=x) _K1*e^(sqrt(k)*x) + _K2*e^(-sqrt(k)*x) + :trac:`15775` fixed:: + + sage: forget() + sage: y = function('y')(x) + sage: desolve(diff(y, x) == sqrt(abs(y)), dvar=y, ivar=x) + sqrt(-y(x))*(sgn(y(x)) - 1) + (sgn(y(x)) + 1)*sqrt(y(x)) == _C + x + AUTHORS: @@ -1603,7 +1610,6 @@ def desolve_mintides(f, ics, initial, final, delta, tolrel=1e-16, tolabs=1e-16) import subprocess if subprocess.call('command -v gcc', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE): raise RuntimeError('Unable to run because gcc cannot be found') - from sage.misc.misc import SAGE_ROOT from sage.interfaces.tides import genfiles_mintides from sage.misc.temporary_file import tmp_dir tempdir = tmp_dir() @@ -1710,7 +1716,6 @@ def desolve_tides_mpfr(f, ics, initial, final, delta, tolrel=1e-16, tolabs=1e-1 import subprocess if subprocess.call('command -v gcc', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE): raise RuntimeError('Unable to run because gcc cannot be found') - from sage.misc.misc import SAGE_ROOT from sage.interfaces.tides import genfiles_mpfr from sage.functions.other import ceil from sage.functions.log import log diff --git a/src/sage/calculus/wester.py b/src/sage/calculus/wester.py index cdc933566f9..fb1b4c13f07 100644 --- a/src/sage/calculus/wester.py +++ b/src/sage/calculus/wester.py @@ -53,7 +53,7 @@ sage: # (YES) Continued fraction of 3.1415926535 sage: a = 3.1415926535 sage: continued_fraction(a) - [3, 7, 15, 1, 292, 1, 1, 6, 2, 13, 4] + [3; 7, 15, 1, 292, 1, 1, 6, 2, 13, 4] :: @@ -582,7 +582,7 @@ sage: f = sin(y) + cos(y) sage: g = f.taylor(y, 0, 10) sage: h = g.power_series(QQ) - sage: k = (h - 1).reversion() + sage: k = (h - 1).reverse() sage: print k y + 1/2*y^2 + 2/3*y^3 + y^4 + 17/10*y^5 + 37/12*y^6 + 41/7*y^7 + 23/2*y^8 + 1667/72*y^9 + 3803/80*y^10 + O(y^11) diff --git a/src/sage/categories/additive_groups.py b/src/sage/categories/additive_groups.py index dbc7449f272..eaf538b67c6 100644 --- a/src/sage/categories/additive_groups.py +++ b/src/sage/categories/additive_groups.py @@ -11,7 +11,7 @@ from sage.misc.lazy_import import LazyImport from sage.categories.category_with_axiom import CategoryWithAxiom_singleton from sage.categories.additive_monoids import AdditiveMonoids -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent class AdditiveGroups(CategoryWithAxiom_singleton): r""" diff --git a/src/sage/categories/additive_magmas.py b/src/sage/categories/additive_magmas.py index d53224417cf..4ffbe1d7c81 100644 --- a/src/sage/categories/additive_magmas.py +++ b/src/sage/categories/additive_magmas.py @@ -18,7 +18,7 @@ from sage.categories.homsets import HomsetsCategory from sage.categories.with_realizations import WithRealizationsCategory from sage.categories.sets_cat import Sets -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent class AdditiveMagmas(Category_singleton): """ @@ -746,10 +746,15 @@ def zero_element(self): TESTS:: - sage: S = CommutativeAdditiveMonoids().example() - sage: S.zero_element() - 0 + sage: from sage.geometry.polyhedron.parent import Polyhedra + sage: P = Polyhedra(QQ, 3) + sage: P.zero_element() + doctest:...: DeprecationWarning: .zero_element() is deprecated. Use .zero() instead + See http://trac.sagemath.org/17694 for details. + A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex """ + from sage.misc.superseded import deprecation + deprecation(17694, ".zero_element() is deprecated. Use .zero() instead") return self.zero() class ElementMethods: diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 2c6b1b65438..97aef5cf271 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -18,7 +18,7 @@ from sage.categories.groups import Groups from sage.categories.enumerated_sets import EnumeratedSets from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent from sage.misc.flatten import flatten from copy import copy @@ -199,15 +199,15 @@ def __iter__(self): sage: W = WeylGroup(["A",2,1]) sage: g = iter(W) - sage: g.next() + sage: next(g) [1 0 0] [0 1 0] [0 0 1] - sage: g.next() + sage: next(g) [-1 1 1] [ 0 1 0] [ 0 0 1] - sage: g.next() + sage: next(g) [ 0 -1 2] [ 1 -1 1] [ 0 0 1] diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index f30f8ec72fd..8786ac5cb5d 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -223,15 +223,15 @@ def __iter__(self, index_set=None, max_depth=float('inf')): sage: C.__iter__.__module__ 'sage.categories.crystals' sage: g = C.__iter__() - sage: g.next() + sage: next(g) (-Lambda[0] + Lambda[2],) - sage: g.next() + sage: next(g) (Lambda[0] - Lambda[1] + delta,) - sage: g.next() + sage: next(g) (Lambda[1] - Lambda[2] + delta,) - sage: g.next() + sage: next(g) (-Lambda[0] + Lambda[2] + delta,) - sage: g.next() + sage: next(g) (Lambda[1] - Lambda[2],) sage: sorted(C.__iter__(index_set=[1,2]), key=str) diff --git a/src/sage/categories/enumerated_sets.py b/src/sage/categories/enumerated_sets.py index 3dce16c694a..b946290f929 100644 --- a/src/sage/categories/enumerated_sets.py +++ b/src/sage/categories/enumerated_sets.py @@ -176,7 +176,7 @@ def __iter__(self): ... def __init__(self): ... Parent.__init__(self, category = EnumeratedSets()) ... - sage: it = iter(broken()); [it.next(), it.next(), it.next()] + sage: it = iter(broken()); [next(it), next(it), next(it)] Traceback (most recent call last): ... NotImplementedError: iterator called but not implemented @@ -191,7 +191,7 @@ def __iter__(self): ... def next(self, elt): ... return elt+1 ... - sage: it = iter(set_first_next()); [it.next(), it.next(), it.next()] + sage: it = iter(set_first_next()); [next(it), next(it), next(it)] [0, 1, 2] Let us try with ``unrank``:: @@ -202,7 +202,7 @@ def __iter__(self): ... def unrank(self, i): ... return i + 5 ... - sage: it = iter(set_unrank()); [it.next(), it.next(), it.next()] + sage: it = iter(set_unrank()); [next(it), next(it), next(it)] [5, 6, 7] Let us finally try with ``list``:: @@ -213,7 +213,7 @@ def __iter__(self): ... def list(self): ... return [5, 6, 7] ... - sage: it = iter(set_list()); [it.next(), it.next(), it.next()] + sage: it = iter(set_list()); [next(it), next(it), next(it)] [5, 6, 7] """ @@ -265,7 +265,7 @@ def _first_from_iterator(self): 1 """ it = self.__iter__() - return it.next() + return next(it) first = _first_from_iterator def _next_from_iterator(self, obj): @@ -290,10 +290,10 @@ def _next_from_iterator(self, obj): TODO: specify the behavior when ``obj`` is not in ``self``. """ it = iter(self) - el = it.next() + el = next(it) while el != obj: - el = it.next() - return it.next() + el = next(it) + return next(it) next = _next_from_iterator @@ -374,7 +374,7 @@ def _iterator_from_list(self): sage: C = FiniteEnumeratedSets().example() sage: it = C._iterator_from_list() - sage: [it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it)] [1, 2, 3] """ for x in self.list(): @@ -393,7 +393,7 @@ def _iterator_from_next(self): sage: C = InfiniteEnumeratedSets().example() sage: it = C._iterator_from_next() - sage: [it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it)] [0, 1, 2, 3, 4] """ f = self.first() @@ -422,7 +422,7 @@ def _iterator_from_unrank(self): sage: C = InfiniteEnumeratedSets().example() sage: it = C._iterator_from_unrank() - sage: [it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it)] [0, 1, 2, 3, 4] """ r = 0 @@ -478,7 +478,7 @@ def _an_element_from_iterator(self): """ it = self.__iter__() try: - return it.next() + return next(it) except StopIteration: raise EmptySetError diff --git a/src/sage/categories/examples/infinite_enumerated_sets.py b/src/sage/categories/examples/infinite_enumerated_sets.py index c3c15f17cec..0978ceda935 100644 --- a/src/sage/categories/examples/infinite_enumerated_sets.py +++ b/src/sage/categories/examples/infinite_enumerated_sets.py @@ -33,9 +33,9 @@ class NonNegativeIntegers(UniqueRepresentation, Parent): sage: NN.element_class sage: it = iter(NN) - sage: [it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it)] [0, 1, 2, 3, 4] - sage: x = it.next(); type(x) + sage: x = next(it); type(x) sage: x.parent() Integer Ring @@ -113,7 +113,7 @@ def __iter__(self): sage: NN = InfiniteEnumeratedSets().example() sage: g = iter(NN) - sage: g.next(), g.next(), g.next(), g.next() + sage: next(g), next(g), next(g), next(g) (0, 1, 2, 3) """ i = Integer(0) diff --git a/src/sage/categories/examples/sets_cat.py b/src/sage/categories/examples/sets_cat.py index ef9fdd6d180..10503d68e4b 100644 --- a/src/sage/categories/examples/sets_cat.py +++ b/src/sage/categories/examples/sets_cat.py @@ -285,7 +285,7 @@ def next(self): EXAMPLES:: sage: P = Sets().example("inherits") - sage: P.an_element().next() + sage: next(P.an_element()) 53 """ return self.parent().next(self) @@ -613,9 +613,9 @@ class PrimeNumbers_Facade(PrimeNumbers_Abstract): whereas:: - sage: pw.next() + sage: next(pw) 53 - sage: pi.next() + sage: next(pi) 53 TESTS:: diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 9532786d196..522bcc0de50 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -424,72 +424,74 @@ def is_unit( self ): # Fields are unique factorization domains, so, there is gcd and lcm # Of course, in general gcd and lcm in a field are not very interesting. # However, they should be implemented! + @coerce_binop def gcd(self,other): """ Greatest common divisor. - NOTE: + .. NOTE:: - Since we are in a field and the greatest common divisor is - only determined up to a unit, it is correct to either return - zero or one. Note that fraction fields of unique factorization - domains provide a more sophisticated gcd. + Since we are in a field and the greatest common divisor is only + determined up to a unit, it is correct to either return zero or + one. Note that fraction fields of unique factorization domains + provide a more sophisticated gcd. EXAMPLES:: - sage: GF(5)(1).gcd(GF(5)(1)) - 1 - sage: GF(5)(1).gcd(GF(5)(0)) + sage: K = GF(5) + sage: K(2).gcd(K(1)) 1 - sage: GF(5)(0).gcd(GF(5)(0)) + sage: K(0).gcd(K(0)) 0 + sage: all(x.gcd(y) == (0 if x == 0 and y == 0 else 1) for x in K for y in K) + True - For fields of characteristic zero (i.e., containing the - integers as a sub-ring), evaluation in the integer ring is - attempted. This is for backwards compatibility:: + For field of characteristic zero, the gcd of integers is considered + as if they were elements of the integer ring:: - sage: gcd(6.0,8); gcd(6.0,8).parent() - 2 - Integer Ring + sage: gcd(15.0,12.0) + 3.00000000000000 - If this fails, we resort to the default we see above:: + But for others floating point numbers, the gcd is just `0.0` or `1.0`:: - sage: gcd(6.0*CC.0,8*CC.0); gcd(6.0*CC.0,8*CC.0).parent() + sage: gcd(3.2, 2.18) 1.00000000000000 - Complex Field with 53 bits of precision - AUTHOR: + sage: gcd(0.0, 0.0) + 0.000000000000000 - - Simon King (2011-02): Trac ticket #10771 + AUTHOR: + - Simon King (2011-02) -- :trac:`10771` + - Vincent Delecroix (2015) -- :trac:`17671` """ P = self.parent() try: - other = P(other) - except (TypeError, ValueError): - raise ArithmeticError("The second argument can not be interpreted in the parent of the first argument. Can't compute the gcd") - from sage.rings.integer_ring import ZZ - if ZZ.is_subring(P): + has_zero_char = P.characteristic() == 0 + except (AttributeError, NotImplementedError): + has_zero_char = False + if has_zero_char: + from sage.rings.integer_ring import ZZ try: - return ZZ(self).gcd(ZZ(other)) + return P(ZZ(self).gcd(ZZ(other))) except TypeError: pass - # there is no custom gcd, so, we resort to something that always exists - # (that's new behaviour) - if self==0 and other==0: + + if self == P.zero() and other == P.zero(): return P.zero() return P.one() - def lcm(self,other): + @coerce_binop + def lcm(self, other): """ Least common multiple. - NOTE: + .. NOTE:: - Since we are in a field and the least common multiple is - only determined up to a unit, it is correct to either return - zero or one. Note that fraction fields of unique factorization - domains provide a more sophisticated lcm. + Since we are in a field and the least common multiple is only + determined up to a unit, it is correct to either return zero or + one. Note that fraction fields of unique factorization domains + provide a more sophisticated lcm. EXAMPLES:: @@ -498,39 +500,38 @@ def lcm(self,other): sage: GF(2)(1).lcm(GF(2)(1)) 1 - If the field contains the integer ring, it is first - attempted to compute the gcd there:: + For field of characteristic zero, the lcm of integers is considered + as if they were elements of the integer ring:: - sage: lcm(15.0,12.0); lcm(15.0,12.0).parent() - 60 - Integer Ring + sage: lcm(15.0,12.0) + 60.0000000000000 - If this fails, we resort to the default we see above:: + But for others floating point numbers, it is just `0.0` or `1.0`:: - sage: lcm(6.0*CC.0,8*CC.0); lcm(6.0*CC.0,8*CC.0).parent() - 1.00000000000000 - Complex Field with 53 bits of precision - sage: lcm(15.2,12.0) + sage: lcm(3.2, 2.18) 1.00000000000000 - AUTHOR: + sage: lcm(0.0, 0.0) + 0.000000000000000 - - Simon King (2011-02): Trac ticket #10771 + AUTHOR: + - Simon King (2011-02) -- :trac:`10771` + - Vincent Delecroix (2015) -- :trac:`17671` """ P = self.parent() try: - other = P(other) - except (TypeError, ValueError): - raise ArithmeticError("The second argument can not be interpreted in the parent of the first argument. Can't compute the lcm") - from sage.rings.integer_ring import ZZ - if ZZ.is_subring(P): + has_zero_char = P.characteristic() == 0 + except (AttributeError, NotImplementedError): + has_zero_char = False + if has_zero_char: + from sage.rings.integer_ring import ZZ try: - return ZZ(self).lcm(ZZ(other)) + return P(ZZ(self).lcm(ZZ(other))) except TypeError: pass - # there is no custom lcm, so, we resort to something that always exists - if self==0 or other==0: + + if self.is_zero() or other.is_zero(): return P.zero() return P.one() @@ -557,18 +558,45 @@ def xgcd(self, other): EXAMPLES:: - sage: (1/2).xgcd(2) - (1, 2, 0) - sage: (0/2).xgcd(2) - (1, 0, 1/2) - sage: (0/2).xgcd(0) + sage: K = GF(5) + sage: K(2).xgcd(K(1)) + (1, 3, 0) + sage: K(0).xgcd(K(4)) + (1, 0, 4) + sage: K(1).xgcd(K(1)) + (1, 1, 0) + sage: GF(5)(0).xgcd(GF(5)(0)) (0, 0, 0) + + The xgcd of non-zero floating point numbers will be a triple of + floating points. But if the input are two integral floating points + the result is a floating point version of the standard gcd on + `\ZZ`:: + + sage: xgcd(12.0, 8.0) + (4.00000000000000, 1.00000000000000, -1.00000000000000) + + sage: xgcd(3.1, 2.98714) + (1.00000000000000, 0.322580645161290, 0.000000000000000) + + sage: xgcd(0.0, 1.1) + (1.00000000000000, 0.000000000000000, 0.909090909090909) """ - R = self.parent() + P = self.parent() + try: + has_zero_char = P.characteristic() == 0 + except (AttributeError, NotImplementedError): + has_zero_char = False + if has_zero_char: + from sage.rings.integer_ring import ZZ + try: + return tuple(P(x) for x in ZZ(self).xgcd(ZZ(other))) + except TypeError: + pass + if not self.is_zero(): - return (R.one(), ~self, R.zero()) + return (P.one(), ~self, P.zero()) if not other.is_zero(): - return (R.one(), R.zero(), ~other) + return (P.one(), P.zero(), ~other) # else both are 0 - return (R.zero(), R.zero(), R.zero()) - + return (P.zero(), P.zero(), P.zero()) diff --git a/src/sage/categories/finite_enumerated_sets.py b/src/sage/categories/finite_enumerated_sets.py index 21bdd444808..b154fba2d51 100644 --- a/src/sage/categories/finite_enumerated_sets.py +++ b/src/sage/categories/finite_enumerated_sets.py @@ -503,16 +503,16 @@ def __iter__(self): # visualize an odometer, with "wheels" displaying "digits"...: factors = list(self.cartesian_factors()) wheels = map(iter, factors) - digits = [it.next() for it in wheels] + digits = [next(it) for it in wheels] while True: yield self._cartesian_product_of_elements(digits) for i in range(len(digits)-1, -1, -1): try: - digits[i] = wheels[i].next() + digits[i] = next(wheels[i]) break except StopIteration: wheels[i] = iter(factors[i]) - digits[i] = wheels[i].next() + digits[i] = next(wheels[i]) else: break diff --git a/src/sage/categories/finite_posets.py b/src/sage/categories/finite_posets.py index 81d2f0a2e43..c8b5b70576d 100644 --- a/src/sage/categories/finite_posets.py +++ b/src/sage/categories/finite_posets.py @@ -449,8 +449,8 @@ def birational_free_labelling(self, linear_extension=None, `\widehat{P}` denote the poset obtained from `P` by adding a new element `1` which is greater than all existing elements of `P`, and a new element `0` which is smaller than all - existing elements of `P` and `1`. Now, a *`\mathbf{K}`-labelling - of `P`* will mean any function from `\widehat{P}` to `\mathbf{K}`. + existing elements of `P` and `1`. Now, a `\mathbf{K}`-*labelling + of* `P` will mean any function from `\widehat{P}` to `\mathbf{K}`. The image of an element `v` of `\widehat{P}` under this labelling will be called the *label* of this labelling at `v`. The set of all `\mathbf{K}`-labellings of `P` is clearly @@ -473,7 +473,7 @@ def birational_free_labelling(self, linear_extension=None, respectively given conditions). Here, `\lessdot` and `\gtrdot` mean (respectively) "covered by" and "covers", interpreted with respect to the poset `\widehat{P}`. This rational map `T_v` - is an involution and is called the *(birational) `v`-toggle*; see + is an involution and is called the *(birational)* `v`-*toggle*; see :meth:`birational_toggle` for its implementation. Now, *birational rowmotion* is defined as the composition @@ -1444,13 +1444,13 @@ def panyushev_orbit_iter(self, antichain, element_constructor=set, stop=True, ch sage: P = Poset({ 1: [2, 3], 2: [4], 3: [4], 4: [] }) sage: Piter = P.panyushev_orbit_iter([2], stop=False) - sage: Piter.next() + sage: next(Piter) {2} - sage: Piter.next() + sage: next(Piter) {3} - sage: Piter.next() + sage: next(Piter) {2} - sage: Piter.next() + sage: next(Piter) {3} """ # TODO: implement a generic function taking a set and @@ -1533,15 +1533,15 @@ def rowmotion_orbit_iter(self, oideal, element_constructor=set, stop=True, check sage: P = Poset({ 1: [2, 3], 2: [4], 3: [4], 4: [] }) sage: Piter = P.rowmotion_orbit_iter([1, 2, 3], stop=False) - sage: Piter.next() + sage: next(Piter) {1, 2, 3} - sage: Piter.next() + sage: next(Piter) {1, 2, 3, 4} - sage: Piter.next() + sage: next(Piter) set() - sage: Piter.next() + sage: next(Piter) {1} - sage: Piter.next() + sage: next(Piter) {1, 2, 3} sage: P = Poset({ 1: [4], 2: [4, 5], 3: [5] }) @@ -1646,15 +1646,15 @@ def toggling_orbit_iter(self, vs, oideal, element_constructor=set, stop=True, ch sage: P = Poset({ 1: [2, 3], 2: [4], 3: [4], 4: [] }) sage: Piter = P.toggling_orbit_iter([1, 2, 4, 3], [1, 2, 3], stop=False) - sage: Piter.next() + sage: next(Piter) {1, 2, 3} - sage: Piter.next() + sage: next(Piter) {1} - sage: Piter.next() + sage: next(Piter) set() - sage: Piter.next() + sage: next(Piter) {1, 2, 3} - sage: Piter.next() + sage: next(Piter) {1} """ # TODO: implement a generic function taking a set and diff --git a/src/sage/categories/highest_weight_crystals.py b/src/sage/categories/highest_weight_crystals.py index 969e11bbcd5..1165d70569a 100644 --- a/src/sage/categories/highest_weight_crystals.py +++ b/src/sage/categories/highest_weight_crystals.py @@ -461,7 +461,7 @@ def highest_weight_vectors(self): ret = [] while it: try: - x = it[-1].next() + x = next(it[-1]) except StopIteration: it.pop() if path: diff --git a/src/sage/categories/magmas.py b/src/sage/categories/magmas.py index 8692bbbf100..9cedafad877 100644 --- a/src/sage/categories/magmas.py +++ b/src/sage/categories/magmas.py @@ -18,7 +18,7 @@ from sage.categories.category_singleton import Category_singleton from sage.categories.sets_cat import Sets from sage.categories.realizations import RealizationsCategory -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent class Magmas(Category_singleton): """ diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 4ed59b2b908..d1636da4c0c 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -29,15 +29,7 @@ import weakref from sage.structure.parent cimport Set_PythonType from sage.misc.constant_function import ConstantFunction from sage.misc.superseded import deprecated_function_alias -# copied from sage.structure.parent -cdef inline parent_c(x): - if PY_TYPE_CHECK(x, Element): - return (x)._parent - else: - try: - return x.parent() - except AttributeError: - return PY_TYPE(x) +from sage.structure.element cimport parent_c def unpickle_map(_class, parent, _dict, _slots): """ diff --git a/src/sage/categories/monoids.py b/src/sage/categories/monoids.py index c080cdfd7ff..edb6f181247 100644 --- a/src/sage/categories/monoids.py +++ b/src/sage/categories/monoids.py @@ -118,9 +118,12 @@ def one_element(self): sage: S = Monoids().example() sage: S.one_element() + doctest:...: DeprecationWarning: .one_element() is deprecated. Please use .one() instead. + See http://trac.sagemath.org/17694 for details. '' - """ + from sage.misc.superseded import deprecation + deprecation(17694, ".one_element() is deprecated. Please use .one() instead.") return self.one() def semigroup_generators(self): @@ -274,7 +277,7 @@ def powers(self, n): raise ValueError("negative number of powers requested") elif n == 0: return [] - x = self.parent().one_element() + x = self.parent().one() l = [x] for i in xrange(n - 1): x = x * self diff --git a/src/sage/categories/polyhedra.py b/src/sage/categories/polyhedra.py index 40001c50305..7fae8ec433d 100644 --- a/src/sage/categories/polyhedra.py +++ b/src/sage/categories/polyhedra.py @@ -31,7 +31,11 @@ class PolyhedralSets(Category_over_base_ring): sage: P.parent().category().element_class.mro() [, + , , + , + , + , , , , @@ -56,10 +60,11 @@ def super_categories(self): EXAMPLES:: sage: PolyhedralSets(QQ).super_categories() - [Category of magmas, Category of additive magmas] + [Category of commutative magmas, Category of additive monoids] """ - from sage.categories.all import Magmas, AdditiveMagmas - return [Magmas(), AdditiveMagmas()] + from sage.categories.magmas import Magmas + from sage.categories.additive_monoids import AdditiveMonoids + return [Magmas().Commutative(), AdditiveMonoids()] diff --git a/src/sage/categories/posets.py b/src/sage/categories/posets.py index d764d027317..5dc0113ada8 100644 --- a/src/sage/categories/posets.py +++ b/src/sage/categories/posets.py @@ -132,7 +132,7 @@ def __iter__(self): sage: P = Posets() sage: it = iter(P) - sage: for _ in range(10): print it.next(); + sage: for _ in range(10): print next(it); Finite poset containing 0 elements Finite poset containing 1 elements Finite poset containing 2 elements diff --git a/src/sage/categories/primer.py b/src/sage/categories/primer.py index 79f734f6a82..c4325388a89 100644 --- a/src/sage/categories/primer.py +++ b/src/sage/categories/primer.py @@ -1,6 +1,9 @@ r""" Elements, parents, and categories in Sage: a (draft of) primer +.. contents:: + :depth: 2 + Abstract ======== diff --git a/src/sage/categories/principal_ideal_domains.py b/src/sage/categories/principal_ideal_domains.py index 6d6aa01aa48..0a26d79af82 100644 --- a/src/sage/categories/principal_ideal_domains.py +++ b/src/sage/categories/principal_ideal_domains.py @@ -59,7 +59,67 @@ def additional_structure(self): return None class ParentMethods: - pass + def _test_gcd_vs_xgcd(self, **options): + r""" + Check that gcd and xgcd are compatible if implemented. + + This test will prevent things like :trac:`17671` to happen again. + + TESTS:: + + sage: ZZ._test_gcd_vs_xgcd() + sage: QQ._test_gcd_vs_xgcd() + sage: QQ['x']._test_gcd_vs_xgcd() + sage: QQbar['x']._test_gcd_vs_xgcd() + sage: RR._test_gcd_vs_xgcd() + sage: RR['x']._test_gcd_vs_xgcd() + + A slightly more involved example of polynomial ring with a non UFD + base ring:: + + sage: K = QuadraticField(5) + sage: O = K.maximal_order() + sage: O in UniqueFactorizationDomains() + False + sage: R = PolynomialRing(O, 'x') + sage: F = R.fraction_field() + sage: F in PrincipalIdealDomains() + True + sage: F._test_gcd_vs_xgcd() + """ + tester = self._tester(**options) + elts = list(tester.some_elements()) + + # there are some strange things in Sage doctests... so it is better + # to cut the list in order to avoid lists of size 531441. + elts = elts[:10] + pairs = [(x,y) for x in elts for y in elts] + + try: + xgcds = [x.xgcd(y) for x,y in pairs] + except (AttributeError,NotImplementedError): + return + + has_gcd = True + try: + gcds = [x.gcd(y) for x,y in pairs] + except (AttributeError,NotImplementedError): + has_gcd = False + + tester.assertTrue(has_gcd, + "The ring {} provides a xgcd but no gcd".format(self)) + for (x,y),gcd,xgcd in zip(pairs,gcds,xgcds): + tester.assertTrue(gcd.parent()==self, + "The parent of the gcd is {} for element of {}".format( + gcd.parent(), self)) + tester.assertTrue(xgcd[0].parent()==self and + xgcd[1].parent()==self and xgcd[2].parent()==self, + "The parent of output in xgcd is different from " + "the parent of input for elements in {}".format(self)) + tester.assertTrue(gcd==xgcd[0], + "The methods gcd and xgcd disagree on {}:\n" + " gcd({},{}) = {}\n" + " xgcd({},{}) = {}\n".format(self,x,y,gcd,x,y,xgcd)) class ElementMethods: pass diff --git a/src/sage/categories/quotient_fields.py b/src/sage/categories/quotient_fields.py index f90d5c4c627..a98b548ab8d 100644 --- a/src/sage/categories/quotient_fields.py +++ b/src/sage/categories/quotient_fields.py @@ -12,6 +12,8 @@ from sage.misc.abstract_method import abstract_method from sage.categories.fields import Fields +from sage.structure.element import coerce_binop + class QuotientFields(Category_singleton): """ The category of quotient fields over an integral domain @@ -50,26 +52,27 @@ def numerator(self): def denominator(self): pass - def gcd(self,other): + @coerce_binop + def gcd(self, other): """ Greatest common divisor - NOTE: + .. NOTE:: - In a field, the greatest common divisor is not very - informative, as it is only determined up to a unit. But in - the fraction field of an integral domain that provides - both gcd and lcm, it is possible to be a bit more specific - and define the gcd uniquely up to a unit of the base ring - (rather than in the fraction field). + In a field, the greatest common divisor is not very informative, + as it is only determined up to a unit. But in the fraction field + of an integral domain that provides both gcd and lcm, it is + possible to be a bit more specific and define the gcd uniquely + up to a unit of the base ring (rather than in the fraction + field). AUTHOR: - - Simon King (2011-02): See trac ticket #10771 + - Simon King (2011-02): See trac ticket :trac:`10771` EXAMPLES:: - sage: R.=QQ[] + sage: R. = QQ['x'] sage: p = (1+x)^3*(1+2*x^2)/(1-x^5) sage: q = (1+x)^2*(1+3*x^2)/(1-x^4) sage: factor(p) @@ -106,12 +109,8 @@ def gcd(self,other): 1 sage: gcd(R.zero(),0) 0 - """ - try: - other = self.parent()(other) - except (TypeError, ValueError): - raise ArithmeticError("The second argument can not be interpreted in the parent of the first argument. Can't compute the gcd") + P = self.parent() try: selfN = self.numerator() selfD = self.denominator() @@ -123,30 +122,32 @@ def gcd(self,other): selfD = selfD // selfGCD otherN = otherN // otherGCD otherD = otherD // otherGCD - return selfN.gcd(otherN)/selfD.lcm(otherD) + tmp = P(selfN.gcd(otherN))/P(selfD.lcm(otherD)) + return tmp except (AttributeError, NotImplementedError, TypeError, ValueError): - if self==0 and other==0: - return self.parent().zero() - return self.parent().one() + zero = P.zero() + if self == zero and other == zero: + return zero + return P.one() + @coerce_binop def lcm(self,other): """ Least common multiple - NOTE: + .. NOTE:: - In a field, the least common multiple is not very - informative, as it is only determined up to a unit. But in - the fraction field of an integral domain that provides - both gcd and lcm, it is reasonable to be a bit more - specific and to define the least common multiple so that - it restricts to the usual least common multiple in the - base ring and is unique up to a unit of the base ring - (rather than up to a unit of the fraction field). + In a field, the least common multiple is not very informative, + as it is only determined up to a unit. But in the fraction field + of an integral domain that provides both gcd and lcm, it is + reasonable to be a bit more specific and to define the least + common multiple so that it restricts to the usual least common + multiple in the base ring and is unique up to a unit of the base + ring (rather than up to a unit of the fraction field). AUTHOR: - - Simon King (2011-02): See trac ticket #10771 + - Simon King (2011-02): See trac ticket :trac:`10771` EXAMPLES:: @@ -185,28 +186,112 @@ def lcm(self,other): 0 sage: lcm(R.zero(),0) 0 - """ + P = self.parent() try: - other = self.parent()(other) - except (TypeError, ValueError): - raise ArithmeticError("The second argument can not be interpreted in the parent of the first argument. Can't compute the lcm") + selfN = self.numerator() + selfD = self.denominator() + selfGCD = selfN.gcd(selfD) + otherN = other.numerator() + otherD = other.denominator() + otherGCD = otherN.gcd(otherD) + selfN = selfN // selfGCD + selfD = selfD // selfGCD + otherN = otherN // otherGCD + otherD = otherD // otherGCD + return P(selfN.lcm(otherN))/P(selfD.gcd(otherD)) + except (AttributeError, NotImplementedError, TypeError, ValueError): + zero = P.zero() + if self == zero or other == zero: + return zero + return P.one() + + @coerce_binop + def xgcd(self, other): + """ + Return a triple ``(g,s,t)`` of elements of that field such that + ``g`` is the greatest common divisor of ``self`` and ``other`` and + ``g = s*self + t*other``. + + .. NOTE:: + + In a field, the greatest common divisor is not very informative, + as it is only determined up to a unit. But in the fraction field + of an integral domain that provides both xgcd and lcm, it is + possible to be a bit more specific and define the gcd uniquely + up to a unit of the base ring (rather than in the fraction + field). + + EXAMPLES:: + + sage: QQ(3).xgcd(QQ(2)) + (1, 1, -1) + sage: QQ(3).xgcd(QQ(1/2)) + (1/2, 0, 1) + sage: QQ(1/3).xgcd(QQ(2)) + (1/3, 1, 0) + sage: QQ(3/2).xgcd(QQ(5/2)) + (1/2, 2, -1) + + sage: R. = QQ['x'] + sage: p = (1+x)^3*(1+2*x^2)/(1-x^5) + sage: q = (1+x)^2*(1+3*x^2)/(1-x^4) + sage: factor(p) + (-2) * (x - 1)^-1 * (x + 1)^3 * (x^2 + 1/2) * (x^4 + x^3 + x^2 + x + 1)^-1 + sage: factor(q) + (-3) * (x - 1)^-1 * (x + 1) * (x^2 + 1)^-1 * (x^2 + 1/3) + sage: g,s,t = xgcd(p,q) + sage: g + (x + 1)/(x^7 + x^5 - x^2 - 1) + sage: g == s*p + t*q + True + + An example without a well defined gcd or xgcd on its base ring:: + + sage: K = QuadraticField(5) + sage: O = K.maximal_order() + sage: R = PolynomialRing(O, 'x') + sage: F = R.fraction_field() + sage: x = F.gen(0) + sage: x.gcd(x+1) + 1 + sage: x.xgcd(x+1) + (1, 1/x, 0) + sage: zero = F.zero() + sage: zero.gcd(x) + 1 + sage: zero.xgcd(x) + (1, 0, 1/x) + sage: zero.xgcd(zero) + (0, 0, 0) + """ + P = self.parent() try: selfN = self.numerator() selfD = self.denominator() selfGCD = selfN.gcd(selfD) + otherN = other.numerator() otherD = other.denominator() otherGCD = otherN.gcd(otherD) + selfN = selfN // selfGCD selfD = selfD // selfGCD otherN = otherN // otherGCD otherD = otherD // otherGCD - return selfN.lcm(otherN)/selfD.gcd(otherD) + + lcmD = selfD.lcm(otherD) + g,s,t = selfN.xgcd(otherN) + return (P(g)/P(lcmD), P(s*selfD)/P(lcmD),P(t*otherD)/P(lcmD)) except (AttributeError, NotImplementedError, TypeError, ValueError): - if self==0 or other==0: - return self.parent().zero() - return self.parent().one() + zero = self.parent().zero() + one = self.parent().one() + if self != zero: + return (one, ~self, zero) + elif other != zero: + return (one, zero, ~other) + else: + return (zero, zero, zero) def factor(self, *args, **kwds): """ @@ -558,7 +643,7 @@ def _derivative(self, var=None): den = self.denominator() if (num.is_zero()): - return R.zero_element() + return R.zero() if R.is_exact(): try: @@ -572,7 +657,7 @@ def _derivative(self, var=None): if not tden.is_one() and tden.is_unit(): try: tnum = tnum * tden.inverse_of_unit() - tden = R.ring().one_element() + tden = R.ring().one() except AttributeError: pass except NotImplementedError: diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py index 0231901b8c4..0748ca7fe18 100644 --- a/src/sage/categories/rings.py +++ b/src/sage/categories/rings.py @@ -153,7 +153,7 @@ def is_zero(self): sage: R.quo(x^2+1).is_zero() False """ - return self.one_element() == self.zero_element() + return self.one() == self.zero() def bracket(self, x, y): """ @@ -923,7 +923,7 @@ def _gen_names(elts): from sage.structure.parent_gens import _certify_names from sage.combinat.words.words import Words it = iter(Words("abcdefghijklmnopqrstuvwxyz", infinite=False)) - it.next() # skip empty word + next(it) # skip empty word for x in elts: name = str(x) m = re.match('^sqrt\((\d+)\)$', name) @@ -932,5 +932,5 @@ def _gen_names(elts): try: _certify_names([name]) except ValueError: - name = it.next().string_rep() + name = next(it).string_rep() yield name diff --git a/src/sage/coding/binary_code.pxd b/src/sage/coding/binary_code.pxd index e448500b34f..84b55966825 100644 --- a/src/sage/coding/binary_code.pxd +++ b/src/sage/coding/binary_code.pxd @@ -98,13 +98,19 @@ cdef class BinaryCodeClassifier: cdef unsigned int *Omega cdef unsigned int *W cdef int radix - cdef int *Lambda1, *Lambda2, *Lambda3 - cdef int *w_gamma, *c_gamma + cdef int *Lambda1 + cdef int *Lambda2 + cdef int *Lambda3 + cdef int *w_gamma + cdef int *c_gamma cdef int w_gamma_size cdef int *alpha cdef int alpha_size - cdef int *v, *e - cdef int *aut_gp_gens, *labeling, *base + cdef int *v + cdef int *e + cdef int *aut_gp_gens + cdef int *labeling + cdef int *base cdef int aut_gp_index, aut_gens_size, base_size cdef object aut_gp_size @@ -113,5 +119,3 @@ cdef class BinaryCodeClassifier: cdef void record_automorphism(self, int *, int) cdef void aut_gp_and_can_label(self, BinaryCode, int) - - diff --git a/src/sage/coding/binary_code.pyx b/src/sage/coding/binary_code.pyx index f760295b201..6186a485b7a 100644 --- a/src/sage/coding/binary_code.pyx +++ b/src/sage/coding/binary_code.pyx @@ -179,10 +179,13 @@ def test_word_perms(t_limit=5.0): sage: test_word_perms() # long time (5s on sage.math, 2011) """ - cdef WordPermutation *g, *h, *i + cdef WordPermutation *g + cdef WordPermutation *h + cdef WordPermutation *i cdef codeword cw1, cw2, cw3 cdef int n = sizeof(codeword) << 3 - cdef int j, *arr = sage_malloc(n * sizeof(int)) + cdef int j + cdef int *arr = sage_malloc(n * sizeof(int)) if arr is NULL: raise MemoryError("Error allocating memory.") from sage.misc.prandom import randint @@ -267,7 +270,8 @@ cdef WordPermutation *create_word_perm(object list_perm): $i \mapsto L[i]$. """ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1 - cdef codeword *images_i, image + cdef codeword *images_i + cdef codeword image cdef WordPermutation *word_perm = sage_malloc( sizeof(WordPermutation) ) if word_perm is NULL: raise RuntimeError("Error allocating memory.") @@ -316,7 +320,8 @@ cdef WordPermutation *create_array_word_perm(int *array, int start, int degree): Create a word permutation of a given degree from a C array, starting at start. """ cdef int i, j, cslim, parity, comb, words_per_chunk, num_chunks = 1 - cdef codeword *images_i, image + cdef codeword *images_i + cdef codeword image cdef WordPermutation *word_perm = sage_malloc( sizeof(WordPermutation) ) if word_perm is NULL: raise RuntimeError("Error allocating memory.") @@ -364,7 +369,8 @@ cdef WordPermutation *create_id_word_perm(int degree): Create the identity word permutation of degree degree. """ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1 - cdef codeword *images_i, image + cdef codeword *images_i + cdef codeword image cdef WordPermutation *word_perm = sage_malloc( sizeof(WordPermutation) ) if word_perm is NULL: raise RuntimeError("Error allocating memory.") @@ -411,7 +417,8 @@ cdef WordPermutation *create_comp_word_perm(WordPermutation *g, WordPermutation Create the composition of word permutations $g \circ h$. """ cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1 - cdef codeword *images_i, image + cdef codeword *images_i + cdef codeword image cdef WordPermutation *word_perm = sage_malloc( sizeof(WordPermutation) ) if word_perm is NULL: raise RuntimeError("Error allocating memory.") @@ -460,7 +467,8 @@ cdef WordPermutation *create_inv_word_perm(WordPermutation *g): r""" Create the inverse $g^{-1}$ of the word permutation of $g$. """ - cdef int i, j, *array = sage_malloc( g.degree * sizeof(int) ) + cdef int i, j + cdef int *array = sage_malloc( g.degree * sizeof(int) ) cdef codeword temp cdef WordPermutation *w for i from 0 <= i < g.degree: @@ -560,7 +568,8 @@ cdef codeword *expand_to_ortho_basis(BinaryCode B, int n): that all the vectors in the span of the output have even weight). """ # assumes B is already in standard form - cdef codeword *basis, word = 0, temp, new, pivots = 0, combo, parity + cdef codeword *basis + cdef codeword word = 0, temp, new, pivots = 0, combo, parity cdef codeword n_gate = (~0) >> ( (sizeof(codeword)<<3) - n) cdef int i, j, m, k = B.nrows, dead, d cdef WordPermutation *wp @@ -711,7 +720,9 @@ cdef class BinaryCode: cdef int nwords, other_nwords, parity, combination cdef codeword word, glue_word cdef BinaryCode other - cdef codeword *self_words, *self_basis, *other_basis + cdef codeword *self_words + cdef codeword *self_basis + cdef codeword *other_basis self.radix = sizeof(int) << 3 @@ -1518,8 +1529,16 @@ cdef class PartitionStack: def __cinit__(self, arg1, arg2=None): cdef int k, nwords, ncols, sizeof_int cdef PartitionStack other = None - cdef int *wd_ents, *wd_lvls, *col_ents, *col_lvls - cdef int *col_degs, *col_counts, *col_output, *wd_degs, *wd_counts, *wd_output + cdef int *wd_ents + cdef int *wd_lvls + cdef int *col_ents + cdef int *col_lvls + cdef int *col_degs + cdef int *col_counts + cdef int *col_output + cdef int *wd_degs + cdef int *wd_counts + cdef int *wd_output sizeof_int = sizeof(int) try: @@ -1961,8 +1980,10 @@ cdef class PartitionStack: # cdef void new_min_cell_reps(self, int k, unsigned int *Omega, int start): cdef int i, j - cdef int *self_col_lvls = self.col_lvls, *self_wd_lvls = self.wd_lvls - cdef int *self_col_ents = self.col_ents, *self_wd_ents = self.wd_ents + cdef int *self_col_lvls = self.col_lvls + cdef int *self_wd_lvls = self.wd_lvls + cdef int *self_col_ents = self.col_ents + cdef int *self_wd_ents = self.wd_ents cdef int reps = (1 << self_col_ents[0]), length, word cdef int radix = self.radix, nwords = self.nwords, ncols = self.ncols length = 1 + nwords/radix @@ -2019,8 +2040,10 @@ cdef class PartitionStack: cdef void fixed_vertices(self, int k, unsigned int *Phi, unsigned int *Omega, int start): cdef int i, j, length, ell, fixed = 0 cdef int radix = self.radix, nwords = self.nwords, ncols = self.ncols - cdef int *self_col_lvls = self.col_lvls, *self_wd_lvls = self.wd_lvls - cdef int *self_col_ents = self.col_ents, *self_wd_ents = self.wd_ents + cdef int *self_col_lvls = self.col_lvls + cdef int *self_wd_lvls = self.wd_lvls + cdef int *self_col_ents = self.col_ents + cdef int *self_wd_ents = self.wd_ents for i from 0 <= i < ncols: fixed += ((self_col_lvls[i] <= k) << self_col_ents[i]) Phi[start] = fixed & Omega[start] @@ -2093,8 +2116,10 @@ cdef class PartitionStack: cdef int ell cdef int i = 0, j = 0, location = 0, min = self.ncols, nwords = self.nwords cdef int min_is_col = 1, radix = self.radix - cdef int *self_col_lvls = self.col_lvls, *self_wd_lvls = self.wd_lvls - cdef int *self_col_ents = self.col_ents, *self_wd_ents = self.wd_ents + cdef int *self_col_lvls = self.col_lvls + cdef int *self_wd_lvls = self.wd_lvls + cdef int *self_col_ents = self.col_ents + cdef int *self_wd_ents = self.wd_ents while True: if self_col_lvls[i] <= k: if i != j and min > i - j + 1: @@ -2394,7 +2419,8 @@ cdef class PartitionStack: cdef int col_degree(self, BinaryCode CG, int col, int wd_ptr, int k): cdef int i = 0 - cdef int *self_wd_lvls = self.wd_lvls, *self_wd_ents = self.wd_ents + cdef int *self_wd_lvls = self.wd_lvls + cdef int *self_wd_ents = self.wd_ents while True: if CG.is_one(self_wd_ents[wd_ptr], col): i += 1 if self_wd_lvls[wd_ptr] > k: wd_ptr += 1 @@ -2436,7 +2462,8 @@ cdef class PartitionStack: cdef int wd_degree(self, BinaryCode CG, int wd, int col_ptr, int k, int *ham_wts): - cdef int *self_col_lvls = self.col_lvls, *self_col_ents = self.col_ents + cdef int *self_col_lvls = self.col_lvls + cdef int *self_col_ents = self.col_ents cdef int mask = (1 << self_col_ents[col_ptr]) while self_col_lvls[col_ptr] > k: col_ptr += 1 @@ -2647,8 +2674,12 @@ cdef class PartitionStack: cdef int refine(self, int k, int *alpha, int alpha_length, BinaryCode CG, int *ham_wts): cdef int q, r, s, t, flag = self.flag, self_ncols = self.ncols cdef int t_w, self_nwords = self.nwords, invariant = 0, i, j, m = 0 - cdef int *self_wd_degs = self.wd_degs, *self_wd_lvls = self.wd_lvls, *self_wd_ents = self.wd_ents - cdef int *self_col_degs = self.col_degs, *self_col_lvls = self.col_lvls, *self_col_ents = self.col_ents + cdef int *self_wd_degs = self.wd_degs + cdef int *self_wd_lvls = self.wd_lvls + cdef int *self_wd_ents = self.wd_ents + cdef int *self_col_degs = self.col_degs + cdef int *self_col_lvls = self.col_lvls + cdef int *self_col_ents = self.col_ents while not self.is_discrete(k) and m < alpha_length: # print "m:", m # print "alpha:", ','.join(['w'+str(alpha[i]^flag) if alpha[i]&flag else 'c'+str(alpha[i]) for i from 0 <= i < alpha_length]) @@ -2757,7 +2788,8 @@ cdef class PartitionStack: cdef void clear(self, int k): cdef int i, j = 0, nwords = self.nwords, ncols = self.ncols - cdef int *wd_lvls = self.wd_lvls, *col_lvls = self.col_lvls + cdef int *wd_lvls = self.wd_lvls + cdef int *col_lvls = self.col_lvls for i from 0 <= i < nwords: if wd_lvls[i] >= k: wd_lvls[i] += 1 @@ -2965,8 +2997,10 @@ cdef class PartitionStack: cdef void get_permutation(self, PartitionStack other, int *word_gamma, int *col_gamma): cdef int i - cdef int *self_wd_ents = self.wd_ents, *other_wd_ents = other.wd_ents - cdef int *self_col_ents = self.col_ents, *other_col_ents = other.col_ents + cdef int *self_wd_ents = self.wd_ents + cdef int *other_wd_ents = other.wd_ents + cdef int *self_col_ents = self.col_ents + cdef int *other_col_ents = other.col_ents # word_gamma[i] := image of the ith row as linear comb of rows for i from 0 <= i < self.nwords: word_gamma[other_wd_ents[i]] = self_wd_ents[i] @@ -3259,7 +3293,8 @@ cdef class BinaryCodeClassifier: cdef int hzf__h_zeta # the max height for which Lambda and zf agree cdef int hzb__h_rho = -1 # the max height for which Lambda and zb agree - cdef int *word_gamma, *col_gamma = self.c_gamma # used for storing permutations + cdef int *word_gamma + cdef int *col_gamma = self.c_gamma # used for storing permutations cdef int nwords = C.nwords, ncols = C.ncols, nrows = C.nrows cdef int *ham_wts = self.ham_wts cdef int state # keeps track of position in algorithm - see sage/graphs/graph_isom.pyx, search for "STATE DIAGRAM" @@ -3905,16 +3940,26 @@ cdef class BinaryCodeClassifier: """ cdef BinaryCode m - cdef codeword *ortho_basis, *B_can_lab, current, swap + cdef codeword *ortho_basis + cdef codeword *B_can_lab + cdef codeword current, swap cdef codeword word, temp, gate, nonzero_gate, orbit, bwd, k_gate - cdef codeword *temp_basis, *orbit_checks, orb_chx_size, orb_chx_shift, radix_gate - cdef WordPermutation *gwp, *hwp, *can_lab, *can_lab_inv + cdef codeword *temp_basis + cdef codeword *orbit_checks + cdef codeword orb_chx_size, orb_chx_shift, radix_gate + cdef WordPermutation *gwp + cdef WordPermutation *hwp + cdef WordPermutation *can_lab + cdef WordPermutation *can_lab_inv cdef WordPermutation **parent_generators cdef BinaryCode B_aug cdef int i, ii, j, jj, ij, k = 0, parity, combo, num_gens cdef int base_size, *multimod2_index, row cdef int *ham_wts = self.ham_wts - cdef int *num_inner_gens, *num_outer_gens, *v, log_2_radix + cdef int *num_inner_gens + cdef int *num_outer_gens + cdef int *v + cdef int log_2_radix cdef bint bingo, bingo2, bingo3 B.put_in_std_form() diff --git a/src/sage/coding/code_constructions.py b/src/sage/coding/code_constructions.py index d4b81b28f41..e04591497fb 100644 --- a/src/sage/coding/code_constructions.py +++ b/src/sage/coding/code_constructions.py @@ -149,7 +149,7 @@ from sage.matrix.constructor import matrix from sage.rings.finite_rings.constructor import FiniteField as GF from sage.groups.perm_gps.permgroup_named import SymmetricGroup -from sage.misc.misc import prod +from sage.misc.all import prod from linear_code import LinearCodeFromVectorSpace, LinearCode from sage.modules.free_module import span from sage.schemes.projective.projective_space import ProjectiveSpace diff --git a/src/sage/coding/codecan/codecan.pyx b/src/sage/coding/codecan/codecan.pyx index b785d39ae1d..d793c775cb8 100644 --- a/src/sage/coding/codecan/codecan.pyx +++ b/src/sage/coding/codecan/codecan.pyx @@ -973,7 +973,8 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic): self._part.depth += 1 PS_clear(self._part) - cdef bitset_t * nonsingletons, scratch + cdef bitset_t *nonsingletons + cdef bitset_t scratch bitset_init(scratch, self._hyp_part.degree) nonsingletons = < bitset_t *> sage_malloc(0) cdef int nr_cells = PS_all_new_cells(self._hyp_part, & nonsingletons) @@ -1017,7 +1018,8 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic): self._hyp_part.depth += 1 PS_clear(self._hyp_part) - cdef bitset_t * nonsingletons, scratch + cdef bitset_t *nonsingletons + cdef bitset_t scratch bitset_init(scratch, self._part.degree) nonsingletons = < bitset_t *> sage_malloc(0) cdef int nr_cells = PS_all_new_cells(self._part, & nonsingletons) diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index 44a6113aeab..41a6dac846f 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -224,7 +224,7 @@ from sage.modules.free_module_element import vector from sage.rings.arith import GCD, rising_factorial, binomial from sage.groups.all import SymmetricGroup -from sage.misc.misc import prod +from sage.misc.all import prod from sage.misc.functional import log, is_even from sage.rings.rational_field import QQ from sage.structure.parent import Parent @@ -273,7 +273,7 @@ def code2leon(C): sage: f.close() """ - from sage.misc.misc import tmp_filename + from sage.misc.temporary_file import tmp_filename F = C.base_ring() p = F.order() # must be prime and <11 s = "LIBRARY code;\n"+"code=seq(%s,%s,%s,seq(\n"%(p,C.dimension(),C.length()) @@ -2889,7 +2889,7 @@ def spectrum(self, algorithm=None): guava_bin_dir = gap.eval('DirectoriesPackagePrograms("guava")[1]') guava_bin_dir = guava_bin_dir[guava_bin_dir.index('"') + 1:guava_bin_dir.rindex('"')] input = code2leon(self) - from sage.misc.misc import tmp_filename + from sage.misc.temporary_file import tmp_filename output = tmp_filename() import os status = os.system(os.path.join(guava_bin_dir, 'wtdist') @@ -3041,16 +3041,13 @@ def zero(self): EXAMPLES:: sage: C = codes.HammingCode(3, GF(2)) - sage: C.zero_element() + sage: C.zero() (0, 0, 0, 0, 0, 0, 0) sage: C.sum(()) # indirect doctest (0, 0, 0, 0, 0, 0, 0) sage: C.sum((C.gens())) # indirect doctest (1, 1, 1, 1, 1, 1, 1) """ - # Note that self.sum() calls self.zero_element(), which in turn - # calls self.zero(). So, only this method needs to be implemented - # for the other two to work. v = 0*self.__gens[0] v.set_immutable() return v diff --git a/src/sage/combinat/alternating_sign_matrix.py b/src/sage/combinat/alternating_sign_matrix.py index c5651f8ec7e..53fe9f379e6 100644 --- a/src/sage/combinat/alternating_sign_matrix.py +++ b/src/sage/combinat/alternating_sign_matrix.py @@ -32,7 +32,7 @@ import copy from sage.misc.classcall_metaclass import ClasscallMetaclass from sage.misc.flatten import flatten -from sage.misc.misc import prod +from sage.misc.all import prod from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.structure.element import Element diff --git a/src/sage/combinat/backtrack.py b/src/sage/combinat/backtrack.py index fdfaf9dccc8..8deaab2798e 100644 --- a/src/sage/combinat/backtrack.py +++ b/src/sage/combinat/backtrack.py @@ -118,7 +118,7 @@ def __iter__(self): while not done: #Try to get the next object in this level try: - obj, state, yld = stack[-1].next() + obj, state, yld = next(stack[-1]) except StopIteration: #If there are no more, go back up the tree #We also need to check if we've exhausted all @@ -174,7 +174,7 @@ def search_forest_iterator(roots, children, algorithm='depth'): This allows for iterating trough trees of infinite depth:: sage: it = search_forest_iterator([[]], lambda l: [l+[0], l+[1]], algorithm='breadth') - sage: [ it.next() for i in range(16) ] + sage: [ next(it) for i in range(16) ] [[], [0], [1], [0, 0], [0, 1], [1, 0], [1, 1], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], @@ -211,7 +211,7 @@ def search_forest_iterator(roots, children, algorithm='depth'): stack = [iter(roots)] while len(stack) > 0: try: - node = stack[position].next() + node = next(stack[position]) except StopIteration: # If there are no more, go back up the tree # We also need to check if we've exhausted all @@ -305,14 +305,14 @@ class SearchForest(Parent): are generated:: sage: depth_search = I.depth_first_search_iterator() - sage: [depth_search.next() for i in range(7)] + sage: [next(depth_search) for i in range(7)] [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)] Using instead breadth first search gives the usual anti-diagonal iterator:: sage: breadth_search = I.breadth_first_search_iterator() - sage: [breadth_search.next() for i in range(15)] + sage: [next(breadth_search) for i in range(15)] [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), @@ -350,7 +350,7 @@ class SearchForest(Parent): sage: MyForest.category() Category of infinite enumerated sets sage: p = iter(MyForest) - sage: [p.next() for i in range(30)] + sage: [next(p) for i in range(30)] [1, 2, 3, 4, 6, 5, 7, 8, 12, 10, 14, 9, 13, 11, 16, 24, 20, 28, 18, 26, 22, 17, 25, 21, 19, 32, 48, 40, 56, 36] An alternative approach is to implement ``roots`` and ``children`` @@ -386,7 +386,7 @@ class SearchForest(Parent): sage: MyForest.category() Category of infinite enumerated sets sage: p = iter(MyForest) - sage: [p.next() for i in range(30)] + sage: [next(p) for i in range(30)] [1, 2, 3, 4, 6, 5, 7, 8, 12, 10, 14, 9, 13, 11, 16, 24, 20, 28, 18, 26, 22, 17, 25, 21, 19, 32, 48, 40, 56, 36] .. warning:: @@ -502,11 +502,11 @@ def __iter__(self): available in that way anymore. Use RecursivelyEnumeratedSet instead. See http://trac.sagemath.org/6637 for details. sage: f = C.__iter__() - sage: f.next() + sage: next(f) [] - sage: f.next() + sage: next(f) [0] - sage: f.next() + sage: next(f) [0, 0] """ iter = search_forest_iterator(self.roots(), @@ -552,7 +552,7 @@ def breadth_first_search_iterator(self): available in that way anymore. Use RecursivelyEnumeratedSet instead. See http://trac.sagemath.org/6637 for details. sage: p = S.breadth_first_search_iterator() - sage: [p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)] [(5, 3), (7, 5), (13, 11), (19, 17), (31, 29), (43, 41), (61, 59)] """ iter = search_forest_iterator(self.roots(), self.children, algorithm='breadth') @@ -611,7 +611,7 @@ def elements_of_depth_iterator(self, depth=0): available in that way anymore. Use RecursivelyEnumeratedSet instead. See http://trac.sagemath.org/6637 for details. sage: p = S.elements_of_depth_iterator(8) - sage: p.next() + sage: next(p) (5, 3) sage: S = SearchForest(NN, lambda x : [], ....: lambda x: x^2 if x.is_prime() else None) @@ -619,7 +619,7 @@ def elements_of_depth_iterator(self, depth=0): available in that way anymore. Use RecursivelyEnumeratedSet instead. See http://trac.sagemath.org/6637 for details. sage: p = S.elements_of_depth_iterator(0) - sage: [p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p)] [4, 9, 25, 49, 121] """ iter = self._elements_of_depth_iterator_rec(depth) @@ -672,10 +672,10 @@ def __contains__(self, elt): available in that way anymore. Use RecursivelyEnumeratedSet instead. See http://trac.sagemath.org/6637 for details. sage: p = S.depth_first_search_iterator() - sage: [p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)] [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)] sage: p = S.breadth_first_search_iterator() - sage: [p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)] [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)] sage: (0,0) in S True @@ -694,10 +694,10 @@ def __contains__(self, elt): sage: S = SearchForest(Family(NN, lambda x : (x, 0)) , lambda x : [(x[0], x[1]+1)]) sage: p = S.depth_first_search_iterator() - sage: [p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)] [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)] sage: p = S.breadth_first_search_iterator() - sage: [p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)] [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)] sage: (0,0) in S True @@ -712,7 +712,7 @@ def __contains__(self, elt): while len(stack) > 0: position = randint(0,len(stack)-1) try: - node = stack[position].next() + node = next(stack[position]) except StopIteration: stack.pop(position) continue @@ -859,7 +859,7 @@ class TransitiveIdeal(RecursivelyEnumeratedSet_generic): sage: C = TransitiveIdeal(lambda x: [x-1, x+1], (-10, 0, 10)) sage: f = C.__iter__() - sage: [ f.next() for i in range(6) ] + sage: [ next(f) for i in range(6) ] [0, 1, 2, 3, 4, 5] We compute all the permutations of 3:: @@ -968,17 +968,17 @@ class TransitiveIdealGraded(RecursivelyEnumeratedSet_generic): The elements at distance 0 from the generators:: - sage: sorted([ f.next() for i in range(3) ]) + sage: sorted([ next(f) for i in range(3) ]) [-10, 0, 10] The elements at distance 1 from the generators:: - sage: sorted([ f.next() for i in range(6) ]) + sage: sorted([ next(f) for i in range(6) ]) [-11, -9, -1, 1, 9, 11] The elements at distance 2 from the generators:: - sage: sorted([ f.next() for i in range(6) ]) + sage: sorted([ next(f) for i in range(6) ]) [-12, -8, -2, 2, 8, 12] The enumeration order between elements at the same distance is not specified. diff --git a/src/sage/combinat/binary_tree.py b/src/sage/combinat/binary_tree.py index 6ff6fa22bf6..2bdcca72b8f 100644 --- a/src/sage/combinat/binary_tree.py +++ b/src/sage/combinat/binary_tree.py @@ -2967,9 +2967,9 @@ def __init__(self): +Infinity sage: it = iter(B) - sage: (it.next(), it.next(), it.next(), it.next(), it.next()) + sage: (next(it), next(it), next(it), next(it), next(it)) (., [., .], [., [., .]], [[., .], .], [., [., [., .]]]) - sage: it.next().parent() + sage: next(it).parent() Binary trees sage: B([]) [., .] diff --git a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py index 43d8bd75da3..61d46b27e7f 100644 --- a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py +++ b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py @@ -1299,13 +1299,13 @@ def mutation_class_iter( self, depth=infinity, show_depth=False, return_paths=Fa sage: S = ClusterSeed(['A',[1,1],1]) sage: it = S.mutation_class_iter() - sage: it.next() + sage: next(it) A seed for a cluster algebra of rank 2 of type ['A', [1, 1], 1] - sage: it.next() + sage: next(it) A seed for a cluster algebra of rank 2 of type ['A', [1, 1], 1] - sage: it.next() + sage: next(it) A seed for a cluster algebra of rank 2 of type ['A', [1, 1], 1] - sage: it.next() + sage: next(it) A seed for a cluster algebra of rank 2 of type ['A', [1, 1], 1] sage: it = S.mutation_class_iter(depth=3, return_paths=True) @@ -1488,15 +1488,15 @@ def cluster_class_iter(self, depth=infinity, show_depth=False, up_to_equivalence sage: S = ClusterSeed(['A',[1,1],1]) sage: it = S.cluster_class_iter() - sage: it.next() + sage: next(it) [x0, x1] - sage: it.next() + sage: next(it) [x0, (x0^2 + 1)/x1] - sage: it.next() + sage: next(it) [(x1^2 + 1)/x0, x1] - sage: it.next() + sage: next(it) [(x0^4 + 2*x0^2 + x1^2 + 1)/(x0*x1^2), (x0^2 + 1)/x1] - sage: it.next() + sage: next(it) [(x1^2 + 1)/x0, (x1^4 + x0^2 + 2*x1^2 + 1)/(x0^2*x1)] sage: it = S.cluster_class_iter(depth=3) diff --git a/src/sage/combinat/cluster_algebra_quiver/mutation_class.py b/src/sage/combinat/cluster_algebra_quiver/mutation_class.py index ff252f172a8..5b9583b2e27 100644 --- a/src/sage/combinat/cluster_algebra_quiver/mutation_class.py +++ b/src/sage/combinat/cluster_algebra_quiver/mutation_class.py @@ -175,8 +175,8 @@ def _dg_canonical_form( dg, n, m ): for v in iso.keys(): if v >= n+m: del iso[v] - v1,v2,label1 = dg._backend.iterator_in_edges([v],True).next() - w1,w2,label2 = dg._backend.iterator_out_edges([v],True).next() + v1,v2,label1 = next(dg._backend.iterator_in_edges([v],True)) + w1,w2,label2 = next(dg._backend.iterator_out_edges([v],True)) dg._backend.del_edge(v1,v2,label1,True) dg._backend.del_edge(w1,w2,label2,True) dg._backend.del_vertex(v) @@ -210,9 +210,9 @@ def _mutation_class_iter( dg, n, m, depth=infinity, return_dig6=False, show_dept sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver sage: dg = ClusterQuiver(['A',[1,2],1]).digraph() sage: itt = _mutation_class_iter(dg, 3,0) - sage: itt.next()[0].edges() + sage: next(itt)[0].edges() [(0, 1, (1, -1)), (0, 2, (1, -1)), (1, 2, (1, -1))] - sage: itt.next()[0].edges() + sage: next(itt)[0].edges() [(0, 2, (1, -1)), (1, 0, (2, -2)), (2, 1, (1, -1))] """ timer = time.time() diff --git a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py index a322a630f40..92e248be773 100644 --- a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py +++ b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py @@ -138,13 +138,13 @@ def _all_induced_cycles_iter( dg ): sage: from sage.combinat.cluster_algebra_quiver.mutation_type import _all_induced_cycles_iter sage: Q = ClusterQuiver(['A',[6,0],1]); Q Quiver on 6 vertices of type ['D', 6] - sage: _all_induced_cycles_iter(Q.digraph()).next() + sage: next(_all_induced_cycles_iter(Q.digraph())) ([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0)], True) sage: Q.mutate(0) - sage: _all_induced_cycles_iter(Q.digraph()).next() + sage: next(_all_induced_cycles_iter(Q.digraph())) ([(1, 2), (2, 3), (3, 4), (4, 5), (5, 1)], True) sage: Q2 = ClusterQuiver(['A',[2,3],1]) - sage: _all_induced_cycles_iter(Q2.digraph()).next() + sage: next(_all_induced_cycles_iter(Q2.digraph())) ([(1, 0), (1, 2), (3, 2), (3, 4), (4, 0)], False) """ dg_new = DiGraph(dg) @@ -657,7 +657,7 @@ def _connected_mutation_type(dg): dg.remove_multiple_edges() dg = DiGraph( dg ) _reset_dg( dg, vertices, dict_in_out, [v] ) - if dict_in_out[v1][0] == dict_in_out[v1][1] == dict_in_out[v2][0] == dict_in_out[v2][1] == 1 and dg.neighbor_out_iterator(v1).next() == dg.neighbor_in_iterator(v2).next(): + if dict_in_out[v1][0] == dict_in_out[v1][1] == dict_in_out[v2][0] == dict_in_out[v2][1] == 1 and next(dg.neighbor_out_iterator(v1)) == next(dg.neighbor_in_iterator(v2)): if label1 == (2,-1) and label2 == (1,-2): return _check_special_BC_cases( dg, n, ['CD'],[1],['A'] ) elif label1 == (1,-2) and label2 == (2,-1): @@ -1227,7 +1227,7 @@ def load_data(n): """ import os.path import cPickle - from sage.misc.misc import DOT_SAGE, SAGE_SHARE + from sage.env import DOT_SAGE, SAGE_SHARE relative_filename = 'cluster_algebra_quiver/mutation_classes_%s.dig6'%n getfilename = lambda path: os.path.join(path,relative_filename) # we check diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver.py b/src/sage/combinat/cluster_algebra_quiver/quiver.py index f0f3a948b79..22416a4cec6 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver.py @@ -1356,7 +1356,7 @@ def mutation_class_iter( self, depth=infinity, show_depth=False, return_paths=Fa sage: Q = ClusterQuiver(['A',3]) sage: it = Q.mutation_class_iter(return_paths=True,data_type='matrix') - sage: it.next() + sage: next(it) ( [ 0 0 1] [ 0 0 1] diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py b/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py index dfa3551469f..b4daeb3f04e 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py @@ -2247,7 +2247,8 @@ def _save_data_dig6(n, types='ClassicalExceptional', verbose=False): if types in possible_types[1:]: data.update(_construct_exceptional_mutation_classes(n)) - from sage.misc.misc import DOT_SAGE, sage_makedirs + from sage.env import DOT_SAGE + from sage.misc.misc import sage_makedirs types_path = os.path.join(DOT_SAGE, 'cluster_algebra_quiver') types_file = os.path.join(types_path,'mutation_classes_%s.dig6'%n) sage_makedirs(types_path) diff --git a/src/sage/combinat/combinat.py b/src/sage/combinat/combinat.py index ca5200cedd3..9973cb39524 100644 --- a/src/sage/combinat/combinat.py +++ b/src/sage/combinat/combinat.py @@ -153,7 +153,7 @@ from sage.rings.polynomial.polynomial_element import Polynomial from sage.libs.all import pari from sage.misc.prandom import randint -from sage.misc.misc import prod +from sage.misc.all import prod from sage.structure.sage_object import SageObject from sage.structure.parent import Parent from sage.misc.lazy_attribute import lazy_attribute @@ -1104,7 +1104,7 @@ def __nonzero__(self): sage: not b Traceback (most recent call last): ... - AttributeError: 'NoneType' object has no attribute 'zero_element' + AttributeError: 'NoneType' object has no attribute 'zero' """ return bool(self._list) @@ -1438,7 +1438,7 @@ def __iterator_from_next(self): sage: C.first = lambda: 0 sage: C.next = lambda c: c+1 sage: it = iter(C) # indirect doctest - sage: [it.next() for _ in range(4)] + sage: [next(it) for _ in range(4)] [0, 1, 2, 3] """ f = self.first() @@ -1473,7 +1473,7 @@ def __iterator_from_previous(self): ... sage: C.previous = prev sage: it = iter(C) # indirect doctest - sage: [it.next() for _ in range(4)] + sage: [next(it) for _ in range(4)] [1, 2, 3, 4] """ l = self.last() @@ -2169,15 +2169,15 @@ def __iter__(self): EXAMPLES: sage: R = InfiniteAbstractCombinatorialClass() - sage: iter(R).next() + sage: next(iter(R)) Traceback (most recent call last): ... NotImplementedError sage: c = iter(Compositions()) # indirect doctest - sage: c.next(), c.next(), c.next(), c.next(), c.next(), c.next() + sage: next(c), next(c), next(c), next(c), next(c), next(c) ([], [1], [1, 1], [2], [1, 1, 1], [1, 2]) - sage: c.next(), c.next(), c.next(), c.next(), c.next(), c.next() + sage: next(c), next(c), next(c), next(c), next(c), next(c) ([2, 1], [3], [1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3]) """ try: diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py index 3c577ecf73a..bfa1aa19bbf 100644 --- a/src/sage/combinat/composition.py +++ b/src/sage/combinat/composition.py @@ -476,7 +476,7 @@ def ribbon_decomposition(self, other, check=True): while True: if i == 0: try: - i = I_iter.next() + i = next(I_iter) except StopIteration: factors.append(Compositions()(current_factor)) return (tuple(factors), tuple(signs)) @@ -608,7 +608,7 @@ def join(self, other, check=True): while True: if i == 0: try: - i = I_iter.next() + i = next(I_iter) except StopIteration: return Compositions()(factors) if current_factor_size + i <= j: @@ -728,7 +728,7 @@ def meet(self, other, check=True): while True: if i == 0: try: - i = I_iter.next() + i = next(I_iter) except StopIteration: factors.append(current_part) return Compositions()(factors) @@ -1838,7 +1838,7 @@ def __iter__(self): sage: C = Compositions() sage: it = C.__iter__() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [[], [1], [1, 1], [2], [1, 1, 1], [1, 2], [2, 1], [3], [1, 1, 1, 1], [1, 1, 2]] """ n = 0 diff --git a/src/sage/combinat/crystals/generalized_young_walls.py b/src/sage/combinat/crystals/generalized_young_walls.py index ee541503369..05119653dcf 100644 --- a/src/sage/combinat/crystals/generalized_young_walls.py +++ b/src/sage/combinat/crystals/generalized_young_walls.py @@ -965,7 +965,7 @@ def __iter__(self): sage: y = crystals.infinity.GeneralizedYoungWalls(3)([[0],[1,0,3,2],[2,1],[3,2,1,0,3,2],[0],[],[2]]) sage: x = y.__iter__() - sage: x.next() + sage: next(x) [0] """ for c in self.subcrystal(direction='lower'): diff --git a/src/sage/combinat/derangements.py b/src/sage/combinat/derangements.py index 548923ad370..e13d8b6e3a1 100644 --- a/src/sage/combinat/derangements.py +++ b/src/sage/combinat/derangements.py @@ -27,7 +27,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element import Element from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.misc.misc import prod +from sage.misc.all import prod from sage.misc.prandom import random, randint from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.all import ZZ, QQ diff --git a/src/sage/combinat/designs/all.py b/src/sage/combinat/designs/all.py index 41c7346a56f..b65ea8667f0 100644 --- a/src/sage/combinat/designs/all.py +++ b/src/sage/combinat/designs/all.py @@ -16,29 +16,6 @@ import design_catalog as designs -from sage.misc.superseded import deprecated_callable_import -deprecated_callable_import(14499, - 'sage.combinat.designs.block_design', - globals(), - locals(), - ["ProjectiveGeometryDesign", - "AffineGeometryDesign", - "WittDesign", - "HadamardDesign"], - ("This method soon will not be available in that " - "way anymore. To use it, you can now call it by " - "typing designs.%(name)s")) -deprecated_callable_import(14499, - 'sage.combinat.designs.covering_design', - globals(), - locals(), - ["best_known_covering_design_www"], - ("This method soon will not be available in that " - "way anymore. To use it, you can now call it by " - "typing designs.best_known_covering_design_from_LJCR")) - -del deprecated_callable_import - import sage.combinat.designs.steiner_quadruple_systems import sage.combinat.designs.orthogonal_arrays import sage.combinat.designs.latin_squares diff --git a/src/sage/combinat/designs/difference_family.py b/src/sage/combinat/designs/difference_family.py index 20cfeb9a932..9aedc08e06c 100644 --- a/src/sage/combinat/designs/difference_family.py +++ b/src/sage/combinat/designs/difference_family.py @@ -596,7 +596,7 @@ def wilson_1972_difference_family(K, k, existence=False, check=True): sage: it4 = ppap(4*3,1) sage: for _ in range(7): - ....: v = it4.next() + ....: v = next(it4) ....: existence = wilson_1972_difference_family(GF(v,'a'), 4, existence=True) ....: print "v = {}: {}".format(v, existence) v = 13: True @@ -609,7 +609,7 @@ def wilson_1972_difference_family(K, k, existence=False, check=True): sage: it5 = ppap(5*4,1) sage: for _ in range(7): - ....: v = it5.next() + ....: v = next(it5) ....: existence = wilson_1972_difference_family(GF(v,'a'), 5, existence=True) ....: print "v = {:3}: {}".format(v, existence) v = 41: True @@ -622,7 +622,7 @@ def wilson_1972_difference_family(K, k, existence=False, check=True): sage: it6 = ppap(6*5,1) sage: for _ in range(7): - ....: v = it6.next() + ....: v = next(it6) ....: existence = wilson_1972_difference_family(GF(v,'a'), 6, existence=True) ....: print "v = {:3}: {}".format(v, existence) v = 31: False @@ -635,7 +635,7 @@ def wilson_1972_difference_family(K, k, existence=False, check=True): sage: it7 = ppap(7*6,1) sage: for _ in range(7): - ....: v = it7.next() + ....: v = next(it7) ....: existence = wilson_1972_difference_family(GF(v,'a'), 7, existence=True) ....: print "v = {:3}: {}".format(v, existence) v = 43: False @@ -1064,7 +1064,7 @@ def difference_family(v, k, l=1, existence=False, explain_construction=False, ch elif explain_construction: return "The database contains a ({},{},{})-difference family".format(v,k,l) - vv, blocks = DF[v,k,l].iteritems().next() + vv, blocks = next(DF[v,k,l].iteritems()) # Build the group from sage.rings.finite_rings.integer_mod_ring import Zmod diff --git a/src/sage/combinat/designs/ext_rep.py b/src/sage/combinat/designs/ext_rep.py index 05c030d4757..956b419289b 100644 --- a/src/sage/combinat/designs/ext_rep.py +++ b/src/sage/combinat/designs/ext_rep.py @@ -45,7 +45,7 @@ import os.path import gzip import bz2 -from sage.misc.misc import tmp_filename +from sage.misc.all import tmp_filename import urllib2 import sys diff --git a/src/sage/combinat/designs/incidence_structures.py b/src/sage/combinat/designs/incidence_structures.py index 5659da1a31e..545ef0e47a4 100644 --- a/src/sage/combinat/designs/incidence_structures.py +++ b/src/sage/combinat/designs/incidence_structures.py @@ -303,9 +303,9 @@ def __iter__(self): sage: b = designs.IncidenceStructure('ab', ['a','ab']) sage: it = iter(b) - sage: it.next() + sage: next(it) ['a'] - sage: it.next() + sage: next(it) ['a', 'b'] """ if self._point_to_index is None: diff --git a/src/sage/combinat/designs/latin_squares.py b/src/sage/combinat/designs/latin_squares.py index a196b2b9e8e..b32390975b7 100644 --- a/src/sage/combinat/designs/latin_squares.py +++ b/src/sage/combinat/designs/latin_squares.py @@ -541,7 +541,7 @@ def MOLS_table(start,stop=None,compare=False,width=None): return if compare: - from sage.misc.misc import SAGE_SHARE + from sage.env import SAGE_SHARE handbook_file = open(SAGE_SHARE+"/combinatorial_designs/MOLS_table.txt",'r') hb = map(int,handbook_file.readlines()[9].split(',')) handbook_file.close() diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index 6e6b7d3acda..c9d828640fe 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -1186,11 +1186,11 @@ def incomplete_orthogonal_array(k,n,holes,resolvable=False, existence=False): 10 holes of size 9 through the product construction:: - sage: iOA = designs.incomplete_orthogonal_array(10,153,[9]*10) # long time - sage: OA9 = designs.orthogonal_arrays.build(10,9) - sage: for i in range(10): - ....: iOA.extend([[153-9*(i+1)+x for x in B] for B in OA9]) - sage: is_orthogonal_array(iOA,10,153) + sage: iOA = designs.incomplete_orthogonal_array(10,153,[9]*10) # long time + sage: OA9 = designs.orthogonal_arrays.build(10,9) # long time + sage: for i in range(10): # long time + ....: iOA.extend([[153-9*(i+1)+x for x in B] for B in OA9]) # long time + sage: is_orthogonal_array(iOA,10,153) # long time True An `OA(9,82)-OA(9,9)-OA(9,1)`:: diff --git a/src/sage/combinat/designs/resolvable_bibd.py b/src/sage/combinat/designs/resolvable_bibd.py index f4147ac54fe..fb277b5fb25 100644 --- a/src/sage/combinat/designs/resolvable_bibd.py +++ b/src/sage/combinat/designs/resolvable_bibd.py @@ -553,7 +553,7 @@ def PBD_4_7(v,check=True, existence=False): # On these groups a (15+7,{4,7})-PBD is pasted, in such a way that the 7 # new points are a set of the final PBD PBD22 = PBD_4_7(15+7) - S = (SS for SS in PBD22 if len(SS) == 7).next() # a set of size 7 + S = next(SS for SS in PBD22 if len(SS) == 7) # a set of size 7 PBD22.relabel({v:i for i,v in enumerate([i for i in range(15+7) if i not in S] + S)}) for B in PBD22: diff --git a/src/sage/combinat/dlx.py b/src/sage/combinat/dlx.py index e8fafc89212..65b2ef2e7f2 100644 --- a/src/sage/combinat/dlx.py +++ b/src/sage/combinat/dlx.py @@ -405,7 +405,7 @@ def next(self): sage: M = DLXMatrix([[1,[1,2]],[2,[2,3]],[3,[1,3]]]) sage: while 1: ... try: - ... C = M.next() + ... C = next(M) ... except StopIteration: ... print "StopIteration" ... break diff --git a/src/sage/combinat/dyck_word.py b/src/sage/combinat/dyck_word.py index 97f285cb5c3..cc041ca7f9c 100644 --- a/src/sage/combinat/dyck_word.py +++ b/src/sage/combinat/dyck_word.py @@ -903,7 +903,7 @@ def _latex_(self): if diagonal: res += " \\draw (0,0) -- %s;\n" % str((self.number_of_open_symbols(), self.number_of_open_symbols())) res += " \\draw[rounded corners=1, color=%s, line width=%s] (0, 0)" % (latex_options['color'], str(latex_options['line width'])) - ht.next() + next(ht) for i, j in ht: res += " -- (%s, %s)" % (i, j) res += ";\n" @@ -3392,7 +3392,7 @@ def __iter__(self): EXAMPLES:: sage: it = DyckWords(complete=False).__iter__() - sage: [it.next() for x in range(10)] + sage: [next(it) for x in range(10)] [[], [1], [1, 0], @@ -3779,7 +3779,7 @@ def __iter__(self): EXAMPLES:: sage: it = DyckWords().__iter__() - sage: [it.next() for x in range(10)] + sage: [next(it) for x in range(10)] [[], [1, 0], [1, 0, 1, 0], diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index e927fad685b..d5443ab4e90 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -719,13 +719,13 @@ def __iter__(self): sage: x = [Face((0,0,0),t) for t in [1,2,3]] sage: P = Patch(x) sage: it = iter(P) - sage: type(it.next()) + sage: type(next(it)) - sage: type(it.next()) + sage: type(next(it)) - sage: type(it.next()) + sage: type(next(it)) - sage: type(it.next()) + sage: type(next(it)) Traceback (most recent call last): ... StopIteration diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index af8df92cca9..cb12d1f12a6 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -6885,25 +6885,24 @@ def composition(self, other, algorithm=None, - ``direct`` -- The composition is calculated directly. There can be arbitrarily many initial and final states, - but the input and output labels must have length 1. + but the input and output labels must have length `1`. - WARNING: The output of other is fed into self. + .. WARNING:: - - ``explorative`` -- An explorative algorithm is used. + The output of ``other`` is fed into ``self``. - At least the following restrictions apply, but are not - checked: - - both self and other have exactly one initial state - - all input labels of transitions have length exactly 1 + - ``explorative`` -- An explorative algorithm is used. The input alphabet of self has to be specified. - This is a very limited implementation of composition. + .. WARNING:: - WARNING: The output of ``other`` is fed into ``self``. + The output of ``other`` is fed into ``self``. If algorithm is ``None``, then the algorithm is chosen - automatically (at the moment always ``direct``). + automatically (at the moment always ``direct``, except when + there are output words of ``other`` or input words of ``self`` + of length greater than `1`). OUTPUT: @@ -6931,6 +6930,20 @@ def composition(self, other, algorithm=None, Transition from (1, 'A') to (2, 'B'): 0|0, Transition from (2, 'B') to (2, 'A'): 0|1, Transition from (2, 'A') to (2, 'B'): 1|0] + sage: He = F.composition(G, algorithm='explorative') + sage: He.initial_states() + [(1, 'A'), (1, 'B')] + sage: He.transitions() + [Transition from (1, 'A') to (2, 'B'): 0|0, + Transition from (1, 'B') to (1, 'A'): 1|1, + Transition from (2, 'B') to (2, 'A'): 0|1, + Transition from (2, 'A') to (2, 'B'): 1|0] + sage: Hd == He + True + + The following example has output of length `> 1`, so the + explorative algorithm has to be used (and is selected + automatically). :: @@ -6947,9 +6960,11 @@ def composition(self, other, algorithm=None, Transition from ('B', 2) to ('B', 1): 1|1, Transition from ('B', 1) to ('B', 1): 0|0, Transition from ('B', 1) to ('B', 2): 1|0] + sage: Ha = G.composition(F) + sage: Ha == He + True - Also final output words are considered if ``algorithm='direct'`` or - ``None``:: + Final output words are also considered:: sage: F = Transducer([('A', 'B', 1, 0), ('B', 'A', 0, 1)], ....: initial_states=['A', 'B'], @@ -6963,6 +6978,9 @@ def composition(self, other, algorithm=None, sage: Hd = F.composition(G, algorithm='direct') sage: Hd.final_states() [(2, 'B')] + sage: He = F.composition(G, algorithm='explorative') + sage: He.final_states() + [(2, 'B')] Note that ``(2, 'A')`` is not final, as the final output `0` of state `2` of `G` cannot be processed in state ``'A'`` of @@ -6972,6 +6990,30 @@ def composition(self, other, algorithm=None, sage: [s.final_word_out for s in Hd.final_states()] [[1, 0]] + sage: [s.final_word_out for s in He.final_states()] + [[1, 0]] + sage: Hd == He + True + + Here is a non-deterministic example with intermediate output + length `>1`. + + :: + + sage: F = Transducer([(1, 1, 1, ['a', 'a']), (1, 2, 1, 'b'), + ....: (2, 1, 2, 'a'), (2, 2, 2, 'b')], + ....: initial_states=[1, 2]) + sage: G = Transducer([('A', 'A', 'a', 'i'), + ....: ('A', 'B', 'a', 'l'), + ....: ('B', 'B', 'b', 'e')], + ....: initial_states=['A', 'B']) + sage: G(F).transitions() + [Transition from (1, 'A') to (1, 'A'): 1|'i','i', + Transition from (1, 'A') to (1, 'B'): 1|'i','l', + Transition from (1, 'B') to (2, 'B'): 1|'e', + Transition from (2, 'A') to (1, 'A'): 2|'i', + Transition from (2, 'A') to (1, 'B'): 2|'l', + Transition from (2, 'B') to (2, 'B'): 2|'e'] Be aware that after composition, different transitions may share the same output label (same python object):: @@ -6988,57 +7030,33 @@ def composition(self, other, algorithm=None, sage: H.transitions()[0].word_out is H.transitions()[1].word_out True + TESTS: + In the explorative algorithm, transducers with non-empty final - output words are currently not implemented:: + output words are implemented in :trac:`16548`:: sage: A = transducers.GrayCode() sage: B = transducers.abs([0, 1]) - sage: A.composition(B, algorithm='explorative') - Traceback (most recent call last): - ... - NotImplementedError: Explorative composition is not - implemented for transducers with non-empty final output - words. Try the direct algorithm instead. - - Similarly, the explorative algorithm cannot handle - non-deterministic finite state machines:: - - sage: A = Transducer([(0, 0, 0, 0), (0, 1, 0, 0)]) + sage: A.composition(B, algorithm='explorative').transitions() + [Transition from (0, 0) to (0, 1): 0|-, + Transition from (0, 0) to (0, 2): 1|-, + Transition from (0, 1) to (0, 1): 0|0, + Transition from (0, 1) to (0, 2): 1|1, + Transition from (0, 2) to (0, 1): 0|1, + Transition from (0, 2) to (0, 2): 1|0] + + Similarly, the explorative algorithm can handle + non-deterministic finite state machines as of :trac:`16548`:: + + sage: A = Transducer([(0, 0, 0, 0), (0, 1, 0, 0)], + ....: initial_states=[0]) sage: B = transducers.Identity([0]) - sage: A.composition(B, algorithm='explorative') - Traceback (most recent call last): - ... - NotImplementedError: Explorative composition is currently - not implemented for non-deterministic transducers. - sage: B.composition(A, algorithm='explorative') - Traceback (most recent call last): - ... - NotImplementedError: Explorative composition is currently - not implemented for non-deterministic transducers. - - TESTS: - - Due to the limitations of the two algorithms the following - (examples from above, but different algorithm used) does not - give a full answer or does not work. - - In the following, ``algorithm='explorative'`` is inadequate, - as ``F`` has more than one initial state:: - - sage: F = Transducer([('A', 'B', 1, 0), ('B', 'A', 0, 1)], - ....: initial_states=['A', 'B'], final_states=['B'], - ....: determine_alphabets=True) - sage: G = Transducer([(1, 1, 1, 0), (1, 2, 0, 1), - ....: (2, 2, 1, 1), (2, 2, 0, 0)], - ....: initial_states=[1], final_states=[2], - ....: determine_alphabets=True) - sage: He = F.composition(G, algorithm='explorative') - sage: He.initial_states() - [(1, 'A')] - sage: He.transitions() - [Transition from (1, 'A') to (2, 'B'): 0|0, - Transition from (2, 'B') to (2, 'A'): 0|1, - Transition from (2, 'A') to (2, 'B'): 1|0] + sage: A.composition(B, algorithm='explorative').transitions() + [Transition from (0, 0) to (0, 0): 0|0, + Transition from (0, 0) to (0, 1): 0|0] + sage: B.composition(A, algorithm='explorative').transitions() + [Transition from (0, 0) to (0, 0): 0|0, + Transition from (0, 0) to (1, 0): 0|0] In the following example, ``algorithm='direct'`` is inappropriate as there are edges with output labels of length greater than 1:: @@ -7052,7 +7070,9 @@ def composition(self, other, algorithm=None, sage: Hd = G.composition(F, algorithm='direct') In the following examples, we compose transducers and automata - and check whether the types are correct. :: + and check whether the types are correct. + + :: sage: from sage.combinat.finite_state_machine import ( ....: is_Automaton, is_Transducer) @@ -7082,13 +7102,88 @@ def composition(self, other, algorithm=None, True sage: is_Automaton(A.composition(T, algorithm='explorative')) True + + Non-deterministic final output cannot be handeled:: + + sage: F = Transducer([('I', 'A', 0, 42), ('I', 'B', 0, 42)], + ....: initial_states=['I'], + ....: final_states=['A', 'B']) + sage: G = Transducer(initial_states=[0], + ....: final_states=[0], + ....: input_alphabet=[0]) + sage: G.state(0).final_word_out = 0 + sage: H = F.composition(G, algorithm='explorative') + sage: for s in H.final_states(): + ....: print s, s.final_word_out + (0, 'I') [42] + sage: F.state('A').final_word_out = 'a' + sage: F.state('B').final_word_out = 'b' + sage: F.composition(G, algorithm='explorative') + Traceback (most recent call last): + ... + NotImplementedError: Stopping in state (0, 'I') leads to + non-deterministic final output. + + Check that the output and input alphabets are set correctly:: + + sage: F = Transducer([(0, 0, 1, 'A')], + ....: initial_states=[0], + ....: determine_alphabets=False) + sage: G = Transducer([(2, 2, 'A', 'a')], + ....: initial_states=[2], + ....: determine_alphabets=False) + sage: Hd = G(F, algorithm='direct') + sage: Hd.input_alphabet, Hd.output_alphabet + ([1], ['a']) + sage: He = G(F, algorithm='explorative') + Traceback (most recent call last): + ... + ValueError: No input alphabet is given. Try calling + determine_alphabets(). + sage: F.input_alphabet = [1] + sage: Hd = G(F, algorithm='direct') + sage: Hd.input_alphabet, Hd.output_alphabet + ([1], ['a']) + sage: He = G(F, algorithm='explorative') + sage: He.input_alphabet, He.output_alphabet + ([1], None) + sage: G.output_alphabet = ['a'] + sage: Hd = G(F, algorithm='direct') + sage: Hd.input_alphabet, Hd.output_alphabet + ([1], ['a']) + sage: He = G(F, algorithm='explorative') + sage: He.input_alphabet, He.output_alphabet + ([1], ['a']) + sage: Hd == He + True + sage: F.input_alphabet = None + sage: Hd = G(F, algorithm='direct') + sage: Hd.input_alphabet, Hd.output_alphabet + ([1], ['a']) + sage: He = G(F, algorithm='explorative') + Traceback (most recent call last): + ... + ValueError: No input alphabet is given. Try calling + determine_alphabets(). """ if not other._allow_composition_: raise TypeError("Composition with automaton is not " "possible.") if algorithm is None: - algorithm = 'direct' + if (any(len(t.word_out) > 1 + for t in other.iter_transitions()) + or + any(len(t.word_in) != 1 + for t in self.iter_transitions()) + #this might be used for multi-tape mode. + #or + #any(isinstance(t.word_in[0], tuple) and None in t.word_in[0] + # for t in self.iter_transitions()) + ): + algorithm = 'explorative' + else: + algorithm = 'direct' if algorithm == 'direct': return self._composition_direct_(other, only_accessible_components) elif algorithm == 'explorative': @@ -7177,58 +7272,61 @@ def _composition_explorative_(self, other): (None, None) sage: B.determinisation() Automaton with 1 states - - .. TODO:: - - The explorative algorithm should be re-implemented using the - process iterators of both finite state machines. - """ - def composition_transition(state, input): - (state1, state2) = state - transition1 = None - for transition in other.iter_transitions(state1): - if transition.word_in == [input]: - transition1 = transition - break - if transition1 is None: - raise LookupError - new_state1 = transition1.to_state - new_state2 = state2 - output = [] - for o in transition1.word_out: - transition2 = None - for transition in self.iter_transitions(new_state2): - if transition.word_in == [o]: - transition2 = transition - break - if transition2 is None: - raise LookupError - new_state2 = transition2.to_state - output += transition2.word_out - return ((new_state1, new_state2), output) - - if any(s.final_word_out for s in self.iter_final_states()) or \ - any(s.final_word_out for s in other.iter_final_states()): - raise NotImplementedError("Explorative composition is not " - "implemented for transducers with " - "non-empty final output words. Try " - "the direct algorithm instead.") - - if not self.is_deterministic() or not other.is_deterministic(): - raise NotImplementedError("Explorative composition is " - "currently not implemented for " - "non-deterministic transducers.") - - F = other.empty_copy(new_class=self.__class__) - new_initial_states = [(other.initial_states()[0], self.initial_states()[0])] + """ + def composition_transition((state1, state2), input): + return [((new_state1, new_state2), output_second) + for _, new_state1, output_first in + first.process([input], + list_of_outputs=True, + initial_state=state1, + write_final_word_out=False) + for _, new_state2, output_second in + second.process(output_first, + list_of_outputs=True, + initial_state=state2, + write_final_word_out=False, + always_include_output=True)] + + + first = other + if any(len(t.word_in) > 1 + for t in first.iter_transitions()): + first = first.split_transitions() + + second = self + if any(len(t.word_in) > 1 + for t in second.iter_transitions()): + second = second.split_transitions() + + F = first.empty_copy(new_class=second.__class__) + new_initial_states = itertools.product( + first.iter_initial_states(), + second.iter_initial_states()) F.add_from_transition_function(composition_transition, initial_states=new_initial_states) - for state in F.states(): - if all(map(lambda s: s.is_final, state.label())): - state.is_final = True - state.color = tuple(map(lambda s: s.color, state.label())) + for state in F.iter_states(): + (state1, state2) = state.label() + if state1.is_final: + final_output_second = second.process( + state1.final_word_out, + list_of_outputs=True, + initial_state=state2, + only_accepted=True, + always_include_output=True) + if (len(final_output_second) > 1 and + not equal(r[2] for r in final_output_second)): + raise NotImplementedError("Stopping in state %s " + "leads to " + "non-deterministic final " + "output." % state) + if final_output_second: + state.is_final = True + state.final_word_out = final_output_second[0][2] + + state.color = tuple(s.color for s in state.label()) + F.output_alphabet = second.output_alphabet return F @@ -8656,37 +8754,15 @@ def asymptotic_moments(self, variable=SR.symbol('n')): ....: input_alphabet=[-1, 0, 1], ....: initial_states=[0], ....: final_states=[0]) - - At the moment, we can not use composition with ``NAF``, - because it has non-empty final output words:: - - sage: NAFweight = weight_transducer.composition( - ....: NAF, - ....: algorithm='explorative') - Traceback (most recent call last): - ... - NotImplementedError: Explorative composition is not - implemented for transducers with non-empty final output - words. Try the direct algorithm instead. - - - Thus, we change ``NAF``, then compose and again construct - the final output words:: - - sage: for s in NAF.final_states(): - ....: s.final_word_out = [] - sage: NAFweight = weight_transducer.composition( - ....: NAF, - ....: algorithm='explorative').relabeled() - sage: NAFweight.construct_final_word_out(0) - sage: sorted(NAFweight.transitions()) - [Transition from 0 to 0: 0|0, - Transition from 0 to 1: 1|-, - Transition from 1 to 0: 0|1,0, - Transition from 1 to 2: 1|1,0, - Transition from 2 to 1: 0|-, - Transition from 2 to 2: 1|0] - sage: NAFweight(binary_27 + [0, 0]) + sage: NAFweight = weight_transducer.composition(NAF) + sage: NAFweight.transitions() + [Transition from (0, 0) to (0, 0): 0|0, + Transition from (0, 0) to ('.1', 0): 1|-, + Transition from ('.1', 0) to (0, 0): 0|1,0, + Transition from ('.1', 0) to (1, 0): 1|1,0, + Transition from (1, 0) to ('.1', 0): 0|-, + Transition from (1, 0) to (1, 0): 1|0] + sage: NAFweight(binary_27) [1, 0, 1, 0, 0, 1, 0] Now, we actually compute the asymptotic moments:: diff --git a/src/sage/combinat/finite_state_machine_generators.py b/src/sage/combinat/finite_state_machine_generators.py index bc8520bbf77..f7d8f325e37 100644 --- a/src/sage/combinat/finite_state_machine_generators.py +++ b/src/sage/combinat/finite_state_machine_generators.py @@ -23,6 +23,7 @@ :meth:`~TransducerGenerators.Identity` | Returns a transducer realizing the identity map. :meth:`~TransducerGenerators.abs` | Returns a transducer realizing absolute value. + :meth:`~TransducerGenerators.map` | Returns a transducer realizing a function. :meth:`~TransducerGenerators.operator` | Returns a transducer realizing a binary operation. :meth:`~TransducerGenerators.all` | Returns a transducer realizing logical ``and``. :meth:`~TransducerGenerators.any` | Returns a transducer realizing logical ``or``. @@ -293,6 +294,46 @@ def transition(state, input): return T + def map(self, f, input_alphabet): + r""" + Return a transducer which realizes a function + on the alphabet. + + INPUT: + + - ``f`` -- function to realize. + + - ``input_alphabet`` -- a list or other iterable. + + OUTPUT: + + A transducer mapping an input letter `x` to + `f(x)`. + + EXAMPLE: + + The following binary transducer realizes component-wise + absolute value (this transducer is also available as :meth:`.abs`):: + + sage: T = transducers.map(abs, [-1, 0, 1]) + sage: T.transitions() + [Transition from 0 to 0: -1|1, + Transition from 0 to 0: 0|0, + Transition from 0 to 0: 1|1] + sage: T.input_alphabet + [-1, 0, 1] + sage: T.initial_states() + [0] + sage: T.final_states() + [0] + sage: T([-1, 1, 0, 1]) + [1, 1, 0, 1] + """ + return Transducer(lambda state, input: (0, f(input)), + input_alphabet=input_alphabet, + initial_states=[0], + final_states=[0]) + def operator(self, operator, input_alphabet, number_of_operands=2): r""" @@ -353,7 +394,14 @@ def operator(self, operator, input_alphabet, number_of_operands=2): sage: T([(-1,), (1,), (0,)]) [1, 1, 0] - Compare this with the transducer generated by :meth:`.abs`:: + Compare this with the transducer generated by :meth:`.map`:: + + sage: T = transducers.map(abs, + ....: [-1, 0, 1]) + sage: T([-1, 1, 0]) + [1, 1, 0] + + In fact, this transducer is also available as :meth:`.abs`:: sage: T = transducers.abs([-1, 0, 1]) sage: T([-1, 1, 0]) @@ -669,10 +717,7 @@ def abs(self, input_alphabet): [1, 1, 0, 1] """ - return Transducer(lambda state, input: (0, abs(input)), - input_alphabet=input_alphabet, - initial_states=[0], - final_states=[0]) + return self.map(abs, input_alphabet) def GrayCode(self): diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index e3be0f2c9ac..74ff2f49f7f 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -12,7 +12,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element import Element from sage.structure.parent import Parent -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent from sage.structure.indexed_generators import IndexedGenerators from sage.modules.free_module_element import vector from sage.misc.misc import repr_lincomb @@ -1354,7 +1354,7 @@ def _an_element_(self): try: g = iter(self.basis().keys()) for c in range(1,4): - x = x + self.term(g.next(), R(c)) + x = x + self.term(next(g), R(c)) except Exception: pass return x @@ -2192,7 +2192,7 @@ def _ascii_art_(self, term): else: symb = tensor.symbol it = iter(zip(self._sets, term)) - module, t = it.next() + module, t = next(it) rpr = module._ascii_art_term(t) for (module,t) in it: rpr += AsciiArt([symb], [len(symb)]) diff --git a/src/sage/combinat/gelfand_tsetlin_patterns.py b/src/sage/combinat/gelfand_tsetlin_patterns.py index 960e79f97e3..bb5489372a1 100644 --- a/src/sage/combinat/gelfand_tsetlin_patterns.py +++ b/src/sage/combinat/gelfand_tsetlin_patterns.py @@ -47,7 +47,7 @@ from sage.combinat.partition import Partitions from sage.combinat.tableau import Tableau, SemistandardTableaux from sage.combinat.combinatorial_map import combinatorial_map -from sage.misc.misc import prod +from sage.misc.all import prod class GelfandTsetlinPattern(ClonableArray): r""" @@ -728,7 +728,7 @@ def __iter__(self): sage: T = GelfandTsetlinPatterns() sage: it = T.__iter__() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [[], [[1]], [[2]], @@ -741,7 +741,7 @@ def __iter__(self): [[3, 1], [1]]] sage: T = GelfandTsetlinPatterns(k=1) sage: it = T.__iter__() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [[], [[0]], [[1]], @@ -824,13 +824,13 @@ def _list_iter(self, n): iters = [None]*n ret = [None]*n iters[0] = self._top_row_iter(n) - ret[0] = iters[0].next() + ret[0] = next(iters[0]) min_pos = 0 iters[1] = self._row_iter(ret[0]) pos = 1 while pos >= min_pos: try: - ret[pos] = iters[pos].next() + ret[pos] = next(iters[pos]) pos += 1 # If we've reached 0 width, yield and backstep if pos == n: @@ -1017,7 +1017,7 @@ def __iter__(self): pos = 1 while pos >= min_pos: try: - ret[pos] = iters[pos].next() + ret[pos] = next(iters[pos]) pos += 1 # If we've reached 0 width, yield and backstep if pos == self._n: diff --git a/src/sage/combinat/gray_codes.py b/src/sage/combinat/gray_codes.py index 88367d5d9c4..2a600f9c702 100644 --- a/src/sage/combinat/gray_codes.py +++ b/src/sage/combinat/gray_codes.py @@ -162,7 +162,7 @@ def combinations(n,t): sage: c = combinations(Infinity,4) sage: s = set([0,1,2,3]) sage: for _ in xrange(10): - ....: i,j = c.next() + ....: i,j = next(c) ....: s.remove(i); s.add(j) ....: print s set([0, 1, 3, 4]) @@ -176,7 +176,7 @@ def combinations(n,t): set([1, 3, 4, 5]) set([0, 3, 4, 5]) sage: for _ in xrange(1000): - ....: i,j = c.next() + ....: i,j = next(c) ....: s.remove(i); s.add(j) sage: print s set([0, 4, 13, 14]) diff --git a/src/sage/combinat/hall_polynomial.py b/src/sage/combinat/hall_polynomial.py index ad5914a69ef..18c043e4f73 100644 --- a/src/sage/combinat/hall_polynomial.py +++ b/src/sage/combinat/hall_polynomial.py @@ -16,7 +16,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.misc.misc import prod +from sage.misc.all import prod from sage.rings.all import ZZ from sage.combinat.partition import Partition from sage.combinat.q_analogues import q_binomial diff --git a/src/sage/combinat/integer_list.py b/src/sage/combinat/integer_list.py index 0b23467e7b4..d511cddf0ad 100644 --- a/src/sage/combinat/integer_list.py +++ b/src/sage/combinat/integer_list.py @@ -840,6 +840,10 @@ def __init__(self, True sage: TestSuite(C).run() """ + from sage.misc.stopgap import stopgap + stopgap("This code contains bugs and may be mathematically unreliable.", + 17548) + # Convert to float infinity from sage.rings.infinity import infinity if max_slope == infinity: diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index 3be82f57cd1..8f3d9f2f56b 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -90,7 +90,7 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): ... NotImplementedError: infinite list sage: p = iter(I) - sage: for i in range(10): p.next() + sage: for i in range(10): next(p) [0, 0, 0] [1, 0, 0] [2, 0, 0] @@ -158,7 +158,7 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time sage: p = iter(I) # long time sage: for i in range(100): # long time - ... v = list(p.next()) + ... v = list(next(p)) ... assert sorted(v, reverse=True) == v We now check that there is as much of canonical vectors under the @@ -250,13 +250,13 @@ class IntegerVectorsModPermutationGroup_All(UniqueRepresentation, SearchForest): +Infinity sage: TestSuite(I).run() sage: it = iter(I) - sage: [it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it)] [[0, 0, 0, 0], [1, 0, 0, 0], [2, 0, 0, 0], [1, 1, 0, 0], [1, 0, 1, 0]] - sage: x = it.next(); x + sage: x = next(it); x [3, 0, 0, 0] sage: I.first() [0, 0, 0, 0] @@ -903,7 +903,7 @@ def an_element(self): else: try: v = iter(self) - return v.next() + return next(v) except StopIteration: from sage.categories.sets_cat import EmptySetError raise EmptySetError diff --git a/src/sage/combinat/interval_posets.py b/src/sage/combinat/interval_posets.py index fba7a093eaa..109f2a14795 100644 --- a/src/sage/combinat/interval_posets.py +++ b/src/sage/combinat/interval_posets.py @@ -2502,13 +2502,13 @@ def __init__(self): +Infinity sage: it = iter(S) - sage: [it.next() for i in xrange(5)] + sage: [next(it) for i in xrange(5)] [The tamari interval of size 0 induced by relations [], The tamari interval of size 1 induced by relations [], The tamari interval of size 2 induced by relations [], The tamari interval of size 2 induced by relations [(2, 1)], The tamari interval of size 2 induced by relations [(1, 2)]] - sage: it.next().parent() + sage: next(it).parent() Interval-posets sage: S(0,[]) The tamari interval of size 0 induced by relations [] diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py index 890878147b6..21d04ceaa61 100644 --- a/src/sage/combinat/k_tableau.py +++ b/src/sage/combinat/k_tableau.py @@ -4005,7 +4005,7 @@ def an_element(self): sage: ST.an_element() [[-1, -1, -1]] """ - return self.__iter__().next() + return next(self.__iter__()) def outer_shape(self): r""" diff --git a/src/sage/combinat/lyndon_word.py b/src/sage/combinat/lyndon_word.py index 5e297ad3201..6aa12aee4ce 100644 --- a/src/sage/combinat/lyndon_word.py +++ b/src/sage/combinat/lyndon_word.py @@ -21,7 +21,7 @@ from sage.combinat.composition import Composition, Compositions from sage.rings.all import divisors, gcd, moebius, Integer from sage.rings.arith import factorial -from sage.misc.misc import prod +from sage.misc.all import prod import __builtin__ import necklace from integer_vector import IntegerVectors diff --git a/src/sage/combinat/matrices/latin.py b/src/sage/combinat/matrices/latin.py index 27cea4a3228..333a655ab1a 100644 --- a/src/sage/combinat/matrices/latin.py +++ b/src/sage/combinat/matrices/latin.py @@ -1240,7 +1240,7 @@ def find_disjoint_mates(self, nr_to_find = None, allow_subtrade = False): sage: from sage.combinat.matrices.latin import * sage: B = back_circulant(4) sage: g = B.find_disjoint_mates(allow_subtrade = True) - sage: B1 = g.next() + sage: B1 = next(g) sage: B0, B1 = bitrade(B, B1) sage: assert is_bitrade(B0, B1) sage: print B0, "\n,\n", B1 @@ -2172,7 +2172,7 @@ def LatinSquare_generator(L_start, check_assertions = False): sage: from sage.combinat.matrices.latin import * sage: g = LatinSquare_generator(back_circulant(4)) - sage: g.next().is_latin_square() + sage: next(g).is_latin_square() True REFERENCE:: diff --git a/src/sage/combinat/misc.py b/src/sage/combinat/misc.py index 0437930bdf7..3c5804a664b 100644 --- a/src/sage/combinat/misc.py +++ b/src/sage/combinat/misc.py @@ -15,7 +15,7 @@ # # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.misc.misc import prod +from sage.misc.all import prod class DoublyLinkedList(): """ diff --git a/src/sage/combinat/necklace.py b/src/sage/combinat/necklace.py index 0b0bc0e289a..1a2ca0373da 100644 --- a/src/sage/combinat/necklace.py +++ b/src/sage/combinat/necklace.py @@ -27,7 +27,7 @@ from sage.combinat.combinat import CombinatorialClass from sage.rings.arith import euler_phi,factorial, divisors, gcd from sage.rings.integer import Integer -from sage.misc.misc import prod +from sage.misc.all import prod from sage.combinat.misc import DoublyLinkedList def Necklaces(content): diff --git a/src/sage/combinat/non_decreasing_parking_function.py b/src/sage/combinat/non_decreasing_parking_function.py index a8c2f9b7e67..50080aa93e8 100644 --- a/src/sage/combinat/non_decreasing_parking_function.py +++ b/src/sage/combinat/non_decreasing_parking_function.py @@ -187,7 +187,7 @@ def _infinite_cclass_slice(self, n): ... == NonDecreasingParkingFunctions(4)) True sage: it = iter(NonDecreasingParkingFunctions()) # indirect doctest - sage: [it.next() for i in range(8)] + sage: [next(it) for i in range(8)] [[], [1], [1, 1], [1, 2], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2]] """ return NonDecreasingParkingFunctions_n(n) diff --git a/src/sage/combinat/ordered_tree.py b/src/sage/combinat/ordered_tree.py index e71b6c467a7..89b64a72b66 100644 --- a/src/sage/combinat/ordered_tree.py +++ b/src/sage/combinat/ordered_tree.py @@ -610,9 +610,9 @@ def __init__(self): +Infinity sage: it = iter(B) - sage: (it.next(), it.next(), it.next(), it.next(), it.next()) + sage: (next(it), next(it), next(it), next(it), next(it)) ([], [[]], [[], []], [[[]]], [[], [], []]) - sage: it.next().parent() + sage: next(it).parent() Ordered trees sage: B([]) [] diff --git a/src/sage/combinat/parking_functions.py b/src/sage/combinat/parking_functions.py index d99efa8ed25..10d64be7268 100644 --- a/src/sage/combinat/parking_functions.py +++ b/src/sage/combinat/parking_functions.py @@ -236,7 +236,7 @@ def _infinite_cclass_slice(self, n): sage: (ParkingFunctions())._infinite_cclass_slice(4) == ParkingFunctions(4) True sage: it = iter(ParkingFunctions()) # indirect doctest - sage: [it.next() for i in range(8)] + sage: [next(it) for i in range(8)] [[], [1], [1, 1], [1, 2], [2, 1], [1, 1, 1], [1, 1, 2], [1, 2, 1]] """ return ParkingFunctions_n(n) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 2b7a5a8ee3f..2cf84800d91 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -89,11 +89,11 @@ ``for part in Partitions(4)`` this iterator is used in the background:: sage: g = iter(Partitions(4)) - sage: g.next() + sage: next(g) [4] - sage: g.next() + sage: next(g) [3, 1] - sage: g.next() + sage: next(g) [2, 2] sage: for p in Partitions(4): print p [4] @@ -1144,9 +1144,9 @@ def next(self): EXAMPLES:: - sage: Partition([4]).next() + sage: next(Partition([4])) [3, 1] - sage: Partition([1,1,1,1]).next() + sage: next(Partition([1,1,1,1])) False """ p = self @@ -4999,7 +4999,7 @@ def __iter__(self): sage: p = Partitions() sage: it = p.__iter__() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [[], [1], [2], [1, 1], [3], [2, 1], [1, 1, 1], [4], [3, 1], [2, 2]] """ n = 0 @@ -5019,7 +5019,7 @@ def __reversed__(self): sage: p = Partitions() sage: revit = p.__reversed__() - sage: [revit.next() for i in range(10)] + sage: [next(revit) for i in range(10)] [[], [1], [1, 1], [2], [1, 1, 1], [2, 1], [3], [1, 1, 1, 1], [2, 1, 1], [2, 2]] """ n = 0 @@ -5263,7 +5263,7 @@ def __iter__(self): sage: p = Partitions(max_part=3) sage: it = p.__iter__() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [[], [1], [2], [1, 1], [3], [2, 1], [1, 1, 1], [3, 1], [2, 2], [2, 1, 1]] """ n = 0 @@ -6114,7 +6114,7 @@ def _fast_iterator(self, n, parts): sage: P = Partitions(4, parts_in=[2,4]) sage: it = P._fast_iterator(4, [2,4]) - sage: it.next() + sage: next(it) [4] sage: type(_) @@ -6218,7 +6218,7 @@ def next(self, part): sage: Partitions(3, starting=[2,1]).next(Partition([2,1])) [1, 1, 1] """ - return part.next() + return next(part) class Partitions_ending(Partitions): """ @@ -6315,7 +6315,7 @@ def next(self, part): if part == self._ending: return None else: - return part.next() + return next(part) class PartitionsInBox(Partitions): r""" diff --git a/src/sage/combinat/perfect_matching.py b/src/sage/combinat/perfect_matching.py index c93cff43eb0..a67a4ddbdb9 100644 --- a/src/sage/combinat/perfect_matching.py +++ b/src/sage/combinat/perfect_matching.py @@ -365,9 +365,9 @@ def loops_iterator(self, other=None): sage: o = PerfectMatching([(1, 7), (2, 4), (3, 8), (5, 6)]) sage: p = PerfectMatching([(1, 6), (2, 7), (3, 4), (5, 8)]) sage: it = o.loops_iterator(p) - sage: it.next() + sage: next(it) [1, 7, 2, 4, 3, 8, 5, 6] - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -498,9 +498,9 @@ def crossings_iterator(self): sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n [(1, 3), (2, 8), (4, 7), (5, 6)] sage: it = n.crossings_iterator(); - sage: it.next() + sage: next(it) ((1, 3), (2, 8)) - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -597,7 +597,7 @@ def is_non_crossing(self): """ it = self.crossings_iterator() try: - it.next() + next(it) except StopIteration: return True else: @@ -621,11 +621,11 @@ def nestings_iterator(self): sage: n = PerfectMatching([(1, 6), (2, 7), (3, 5), (4, 8)]) sage: it = n.nestings_iterator(); - sage: it.next() + sage: next(it) ((1, 6), (3, 5)) - sage: it.next() + sage: next(it) ((2, 7), (3, 5)) - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -726,7 +726,7 @@ def is_non_nesting(self): """ it = self.nestings_iterator() try: - it.next() + next(it) except StopIteration: return True else: diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 3677eadc2ac..389bf284fd0 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -40,6 +40,7 @@ :meth:`~sage.combinat.permutation.Permutation.prev` | Returns the permutation that comes directly before ``self`` in lexicographic order (in the same symmetric group as ``self``). :meth:`~sage.combinat.permutation.Permutation.to_tableau_by_shape` | Returns a tableau of shape ``shape`` with the entries in ``self``. :meth:`~sage.combinat.permutation.Permutation.to_cycles` | Returns the permutation ``self`` as a list of disjoint cycles. + :meth:`~sage.combinat.permutation.Permutation.forget_cycles` | Return ``self`` under the forget cycle map. :meth:`~sage.combinat.permutation.Permutation.to_permutation_group_element` | Returns a ``PermutationGroupElement`` equal to ``self``. :meth:`~sage.combinat.permutation.Permutation.signature` | Returns the signature of the permutation ``sef``. :meth:`~sage.combinat.permutation.Permutation.is_even` | Returns ``True`` if the permutation ``self`` is even, and ``False`` otherwise. @@ -807,16 +808,16 @@ def next(self): EXAMPLES:: sage: p = Permutation([1, 3, 2]) - sage: p.next() + sage: next(p) [2, 1, 3] sage: p = Permutation([4,3,2,1]) - sage: p.next() + sage: next(p) False TESTS:: sage: p = Permutation([]) - sage: p.next() + sage: next(p) False """ p = self[:] @@ -939,6 +940,10 @@ def to_cycles(self, singletons=True): """ Return the permutation ``self`` as a list of disjoint cycles. + The cycles are returned in the order of increasing smallest + elements, and each cycle is returned as a tuple which starts + with its smallest element. + If ``singletons=False`` is given, the list does not contain the singleton cycles. @@ -949,6 +954,9 @@ def to_cycles(self, singletons=True): sage: Permutation([2,1,3,4]).to_cycles(singletons=False) [(1, 2)] + sage: Permutation([4,1,5,2,6,3]).to_cycles() + [(1, 4, 2), (3, 5, 6)] + The algorithm is of complexity `O(n)` where `n` is the size of the given permutation. @@ -994,7 +1002,7 @@ def to_cycles(self, singletons=True): l = self[:] - #Go through until we've considered every number between 1 and len(p) + #Go through until we've considered every number between 1 and len(l) for i in range(len(l)): if l[i] == False: continue @@ -2177,6 +2185,72 @@ def cycle_type(self): from sage.combinat.partition import Partition return Partition(cycle_type) + @combinatorial_map(name='forget cycles') + def forget_cycles(self): + r""" + Return the image of ``self`` under the map which forgets cycles. + + Consider a permutation `\sigma` written in standard cyclic form: + + .. MATH:: + + \sigma = (a_{1,1}, \ldots, a_{1,k_1}) (a_{2,1}, \ldots, a_{2,k_2}) + \cdots (a_{m,1}, \ldots, a_{m,k_m}), + + where `a_{1,1} < a_{2,1} < \cdots < a_{m,1}` and `a_{j,1} < a_{j,i}` + for all `1 \leq j \leq m` and `2 \leq i \leq k_j` where we include + cycles of length 1 as well. The image of the forget cycle map `\phi` + is given by + + .. MATH:: + + \phi(\sigma) = [a_{1,1}, \ldots, a_{1,k_1}, a_{2,1} \ldots, + a_{2,k_2}, \ldots, a_{m,1}, \ldots, a_{m,k_m}], + + considered as a permutation in 1-line notation. + + EXAMPLES:: + + sage: P = Permutations(5) + sage: x = P([1, 5, 3, 4, 2]) + sage: x.forget_cycles() + [1, 2, 5, 3, 4] + + We select all permutations with a cycle composition of `[2, 3, 1]` + in `S_6`:: + + sage: P = Permutations(6) + sage: l = [p for p in P if [len(t) for t in p.to_cycles()] == [1,3,2]] + + Next we apply `\phi` and then take the inverse, and then view the + results as a poset under the Bruhat order:: + + sage: l = [p.forget_cycles().inverse() for p in l] + sage: B = Poset([l, lambda x,y: x.bruhat_lequal(y)]) + sage: R. = QQ[] + sage: sum(q^B.rank_function()(x) for x in B) + q^5 + 2*q^4 + 3*q^3 + 3*q^2 + 2*q + 1 + + We check the statement in [CC13]_ that the posets + `C_{[1,3,1,1]}` and `C_{[1,3,2]}` are isomorphic:: + + sage: l2 = [p for p in P if [len(t) for t in p.to_cycles()] == [1,3,1,1]] + sage: l2 = [p.forget_cycles().inverse() for p in l2] + sage: B2 = Poset([l2, lambda x,y: x.bruhat_lequal(y)]) + sage: B.is_isomorphic(B2) + True + + REFERENCES: + + .. [CC13] Mahir Bilen Can and Yonah Cherniavsky. + *Omitting parentheses from the cyclic notation*. (2013). + :arxiv:`1308.0936v2`. + """ + ret = [] + for t in self.to_cycles(): + ret += list(t) + return Permutations()(ret) + @combinatorial_map(name='foata_bijection') def foata_bijection(self): r""" @@ -5715,7 +5789,7 @@ def __iter__(self): TESTS:: sage: it = iter(Permutations()) - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ n = 0 diff --git a/src/sage/combinat/permutation_cython.pyx b/src/sage/combinat/permutation_cython.pyx index 5970b3718e6..c603a70bb07 100644 --- a/src/sage/combinat/permutation_cython.pyx +++ b/src/sage/combinat/permutation_cython.pyx @@ -141,7 +141,9 @@ def permutation_iterator_transposition_list(int n): """ - cdef int *c, *o, N, m + cdef int *c + cdef int *o + cdef int N, m cdef list T if n <= 1: diff --git a/src/sage/combinat/posets/elements.py b/src/sage/combinat/posets/elements.py index 7832c2b8369..b27afd59980 100644 --- a/src/sage/combinat/posets/elements.py +++ b/src/sage/combinat/posets/elements.py @@ -17,7 +17,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** from sage.structure.element import Element -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent class PosetElement(Element): diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 61b3f3e2077..ba7cd847f29 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -4968,7 +4968,7 @@ def greene_shape(self): part = 0 (pold, vold) = (0, 0) while size != n: - (p, v) = chron.next() + (p, v) = next(chron) if v > vold: size += p if part > 0: @@ -5307,31 +5307,31 @@ def _ford_fulkerson_chronicle(G, s, t, a): False sage: a = {(1, 6): 4, (2, 4): 0, (1, 3): 4, (1, 7): 1, (3, 7): 6, (7, 9): 1, (6, 7): 3, (6, 8): 1, (8, 9): 0, (8, 12): 2} sage: ffc = _ford_fulkerson_chronicle(G, s, t, a) - sage: ffc.next() + sage: next(ffc) (1, 0) - sage: ffc.next() + sage: next(ffc) (2, 0) - sage: ffc.next() + sage: next(ffc) (2, 1) - sage: ffc.next() + sage: next(ffc) (3, 1) - sage: ffc.next() + sage: next(ffc) (4, 1) - sage: ffc.next() + sage: next(ffc) (5, 1) - sage: ffc.next() + sage: next(ffc) (5, 2) - sage: ffc.next() + sage: next(ffc) (6, 2) - sage: ffc.next() + sage: next(ffc) (7, 2) - sage: ffc.next() + sage: next(ffc) (8, 2) - sage: ffc.next() + sage: next(ffc) (9, 2) - sage: ffc.next() + sage: next(ffc) (10, 2) - sage: ffc.next() + sage: next(ffc) (11, 2) """ from sage.graphs.digraph import DiGraph diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py index c449dde71c0..226ee138a43 100644 --- a/src/sage/combinat/q_analogues.py +++ b/src/sage/combinat/q_analogues.py @@ -17,7 +17,7 @@ #***************************************************************************** from sage.misc.cachefunc import cached_function -from sage.misc.misc import prod +from sage.misc.all import prod from sage.rings.all import ZZ from sage.combinat.dyck_word import DyckWords from sage.combinat.partition import Partition diff --git a/src/sage/combinat/ranker.py b/src/sage/combinat/ranker.py index 611fe68cb7c..9c16f3973ed 100644 --- a/src/sage/combinat/ranker.py +++ b/src/sage/combinat/ranker.py @@ -128,7 +128,7 @@ def count(): @cached_function def rank(x): - i = counter.next() + i = next(counter) unrank.set_cache(x, i) return i @@ -241,8 +241,8 @@ def unrank(L, i): try: it = iter(L) for _ in range(i): - it.next() - return it.next() + next(it) + return next(it) except StopIteration as e: raise IndexError("index out of range") raise ValueError("Don't know how to unrank on {}".format(L)) diff --git a/src/sage/combinat/ribbon_shaped_tableau.py b/src/sage/combinat/ribbon_shaped_tableau.py index 310c3251df5..96208c3969b 100644 --- a/src/sage/combinat/ribbon_shaped_tableau.py +++ b/src/sage/combinat/ribbon_shaped_tableau.py @@ -249,7 +249,7 @@ def __iter__(self): EXAMPLES:: sage: it = StandardRibbonShapedTableaux().__iter__() - sage: [it.next() for x in range(10)] + sage: [next(it) for x in range(10)] [[], [[1]], [[1, 2]], diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 6d941d08a0d..f604fa84ac7 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -310,11 +310,11 @@ def __iter__(self): sage: KR = crystals.KirillovReshetikhin(['A', 3, 1], 2, 1, model='KR') sage: g = KR.__iter__() - sage: g.next() + sage: next(g) [[1], [2]] - sage: g.next() + sage: next(g) [[1], [3]] - sage: g.next() + sage: next(g) [[2], [3]] """ index_set = self._cartan_type.classical().index_set() diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index 29218fb3764..a4e91ed3b7d 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -480,7 +480,7 @@ def __iter__(self): sage: RC = RiggedConfigurations(['A', 3, 1], [[2,1], [1,1]]) sage: g = RC.__iter__() - sage: g.next() + sage: next(g) (/) @@ -488,7 +488,7 @@ def __iter__(self): (/) - sage: g.next() + sage: next(g) (/) diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py index 0ad349f9ffa..8bc2c5578b1 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py @@ -329,9 +329,9 @@ def __iter__(self): sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['A', 3, 1], [[2,1], [1,1]]) sage: g = KRT.__iter__() - sage: g.next() + sage: next(g) [[2], [3]] (X) [[1]] - sage: g.next() + sage: next(g) [[2], [4]] (X) [[1]] """ index_set = self._cartan_type.classical().index_set() diff --git a/src/sage/combinat/root_system/pieri_factors.py b/src/sage/combinat/root_system/pieri_factors.py index d2237ec6a08..13520fe9034 100644 --- a/src/sage/combinat/root_system/pieri_factors.py +++ b/src/sage/combinat/root_system/pieri_factors.py @@ -12,7 +12,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.constant_function import ConstantFunction -from sage.misc.misc import prod, attrcall +from sage.misc.all import prod, attrcall from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation @@ -162,7 +162,7 @@ def __iter__(self): sage: PF = WeylGroup(['A',3,1]).pieri_factors() sage: f = PF.__iter__() - sage: [f.next().reduced_word() for i in range(5)] + sage: [next(f).reduced_word() for i in range(5)] [[], [0], [1], [2], [3]] """ return iter(self.elements()) @@ -765,13 +765,13 @@ def __iter__(self): sage: W = WeylGroup(['A',4,1]) sage: PF = W.pieri_factors() sage: f = PF.__iter__() - sage: f.next() + sage: next(f) [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] - sage: [f.next().reduced_word() for i in range(6)] + sage: [next(f).reduced_word() for i in range(6)] [[0], [1], [2], [3], [4], [1, 0]] """ from sage.combinat.subset import Subsets diff --git a/src/sage/combinat/root_system/plot.py b/src/sage/combinat/root_system/plot.py index af9d5107b8b..9faff6fdab4 100644 --- a/src/sage/combinat/root_system/plot.py +++ b/src/sage/combinat/root_system/plot.py @@ -230,7 +230,7 @@ sage: succ = attrcall("pred") sage: positive_roots = RecursivelyEnumeratedSet(seed, succ, structure='graded') sage: it = iter(positive_roots) - sage: first_positive_roots = [it.next() for i in range(10)] + sage: first_positive_roots = [next(it) for i in range(10)] sage: L.plot(roots=first_positive_roots, affine=False, alcoves=False) Graphics object consisting of 24 graphics primitives @@ -257,7 +257,7 @@ sage: succ = attrcall("pred") sage: positive_coroots = RecursivelyEnumeratedSet(seed, succ, structure='graded') sage: it = iter(positive_coroots) - sage: first_positive_coroots = [it.next() for i in range(20)] + sage: first_positive_coroots = [next(it) for i in range(20)] sage: p = L.plot(fundamental_chamber=True, reflection_hyperplanes=first_positive_coroots, ... affine=False, alcove_labels=1, ... bounding_box=[[-9,9],[-1,2]], diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 7322f1757a9..4446b4eea16 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -409,7 +409,7 @@ def a_long_simple_root(self): """ if self.dynkin_diagram().rank() == 1: return self.simple_roots()[self.index_set()[0]] - longest=self.dynkin_diagram().edge_iterator().next() + longest=next(self.dynkin_diagram().edge_iterator()) for j in self.dynkin_diagram().edge_iterator(): if j[2]>longest[2]: longest=j diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 8a90188c8da..31e50dbdb24 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -21,7 +21,7 @@ from sage.misc.abstract_method import abstract_method from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute -from sage.misc.misc import prod +from sage.misc.all import prod from sage.categories.category_types import Category_over_base_ring from sage.combinat.family import Family from root_lattice_realizations import RootLatticeRealizations diff --git a/src/sage/combinat/root_system/weyl_group.py b/src/sage/combinat/root_system/weyl_group.py index bb015edff78..e290114477c 100644 --- a/src/sage/combinat/root_system/weyl_group.py +++ b/src/sage/combinat/root_system/weyl_group.py @@ -540,34 +540,42 @@ def classical(self): return ClassicalWeylSubgroup(self._domain, prefix=self._prefix) def bruhat_graph(self, x, y): - """ - The Bruhat graph Gamma(x,y), defined if x <= y in the Bruhat order, has - as its vertices the Bruhat interval, {t | x <= t <= y}, and as its - edges the pairs u, v such that u = r.v where r is a reflection, that - is, a conjugate of a simple reflection. + r""" + Return the Bruhat graph as a directed graph, with an edge `u \to v` + if and only if `u < v` in the Bruhat order, and `u = r \cdot v`. - Returns the Bruhat graph as a directed graph, with an edge u --> v - if and only if u < v in the Bruhat order, and u = r.v. + The Bruhat graph `\Gamma(x,y)`, defined if `x \leq y` in the + Bruhat order, has as its vertices the Bruhat interval + `\{ t | x \leq t \leq y \}`, and as its edges are the pairs + `(u, v)` such that `u = r \cdot v` where `r` is a reflection, + that is, a conjugate of a simple reflection. - See: + REFERENCES: - Carrell, The Bruhat graph of a Coxeter group, a conjecture of Deodhar, and - rational smoothness of Schubert varieties. Algebraic groups and their - generalizations: classical methods (University Park, PA, 1991), 53--61, - Proc. Sympos. Pure Math., 56, Part 1, Amer. Math. Soc., Providence, RI, 1994. + Carrell, The Bruhat graph of a Coxeter group, a conjecture of Deodhar, + and rational smoothness of Schubert varieties. Algebraic groups and + their generalizations: classical methods (University Park, PA, 1991), + 53--61, Proc. Sympos. Pure Math., 56, Part 1, Amer. Math. Soc., + Providence, RI, 1994. EXAMPLES:: - sage: W = WeylGroup("A3", prefix = "s") - sage: [s1,s2,s3] = W.simple_reflections() - sage: W.bruhat_graph(s1*s3,s1*s2*s3*s2*s1) + sage: W = WeylGroup("A3", prefix="s") + sage: s1, s2, s3 = W.simple_reflections() + sage: G = W.bruhat_graph(s1*s3, s1*s2*s3*s2*s1); G Digraph on 10 vertices + + Check that the graph has the correct number of edges + (see :trac:`17744`):: + + sage: len(G.edges()) + 16 """ g = self.bruhat_interval(x, y) - ref = self.reflections() + ref = self.reflections().keys() d = {} - for x in g: - d[x] = [y for y in g if x.length() < y.length() and x*y.inverse() in ref] + for u in g: + d[u] = [v for v in g if u.length() < v.length() and u*v.inverse() in ref] return DiGraph(d) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 8f0a7a8ea9e..c437d8f36db 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -1073,7 +1073,7 @@ def _iterator_part(self, part): sage: S = SetPartitions(3) sage: it = S._iterator_part(Partition([1,1,1])) - sage: list(sorted(map(list, it.next()))) + sage: list(sorted(map(list, next(it)))) [[1], [2], [3]] sage: S21 = SetPartitions(3,Partition([2,1])) sage: len(list(S._iterator_part(Partition([2,1])))) == S21.cardinality() @@ -1222,7 +1222,7 @@ def __iter__(self): EXAMPLES:: sage: it = SetPartitions().__iter__() - sage: [it.next() for x in range(10)] + sage: [next(it) for x in range(10)] [{}, {{1}}, {{1, 2}}, {{1}, {2}}, {{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2}, {3}}, {{1, 2, 3, 4}}] """ diff --git a/src/sage/combinat/set_partition_ordered.py b/src/sage/combinat/set_partition_ordered.py index f327c56a213..f6b6fb2781e 100644 --- a/src/sage/combinat/set_partition_ordered.py +++ b/src/sage/combinat/set_partition_ordered.py @@ -30,7 +30,7 @@ from sage.sets.set import Set, is_Set from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.misc.classcall_metaclass import ClasscallMetaclass -from sage.misc.misc import prod +from sage.misc.all import prod from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.list_clone import ClonableArray diff --git a/src/sage/combinat/sf/jack.py b/src/sage/combinat/sf/jack.py index 2613e1452bd..616de4eb923 100644 --- a/src/sage/combinat/sf/jack.py +++ b/src/sage/combinat/sf/jack.py @@ -39,7 +39,7 @@ import sage.categories.all from sage.rings.all import Integer, gcd, lcm, QQ from sage.rings.fraction_field import is_FractionField -from sage.misc.misc import prod +from sage.misc.all import prod from sage.categories.morphism import SetMorphism from sage.categories.homset import Hom, End from sage.rings.fraction_field import FractionField diff --git a/src/sage/combinat/sf/macdonald.py b/src/sage/combinat/sf/macdonald.py index 0c7bda5ef2f..90b670b7887 100644 --- a/src/sage/combinat/sf/macdonald.py +++ b/src/sage/combinat/sf/macdonald.py @@ -53,7 +53,7 @@ import sage.combinat.partition from sage.matrix.all import MatrixSpace from sage.rings.all import QQ -from sage.misc.misc import prod +from sage.misc.all import prod from sage.rings.fraction_field import FractionField import functools diff --git a/src/sage/combinat/sf/ns_macdonald.py b/src/sage/combinat/sf/ns_macdonald.py index b4a1ed1cdaf..94a4b0bc1a4 100644 --- a/src/sage/combinat/sf/ns_macdonald.py +++ b/src/sage/combinat/sf/ns_macdonald.py @@ -6,7 +6,7 @@ from sage.combinat.combination import Combinations from sage.combinat.permutation import Permutation from sage.rings.all import QQ, PolynomialRing -from sage.misc.misc import prod +from sage.misc.all import prod from sage.combinat.backtrack import GenericBacktracker import copy diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index df68dc5ab10..078f5c8da88 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -220,7 +220,7 @@ import sage.libs.symmetrica.all as symmetrica # used in eval() from sage.combinat.free_module import CombinatorialFreeModule from sage.matrix.constructor import matrix -from sage.misc.misc import prod, uniq +from sage.misc.all import prod, uniq from copy import copy from functools import reduce diff --git a/src/sage/combinat/shuffle.py b/src/sage/combinat/shuffle.py index e18c8755599..e1447d90f37 100644 --- a/src/sage/combinat/shuffle.py +++ b/src/sage/combinat/shuffle.py @@ -124,7 +124,7 @@ def __init__(self, l1, l2, element_constructor=None): self._element_constructor_ = element_constructor else: try: - e = iter(l1).next() + e = next(iter(l1)) if hasattr(e, "parent") and hasattr(e.parent(), "_element_constructor_"): self._element_constructor_ = e.parent()._element_constructor_ else: diff --git a/src/sage/combinat/similarity_class_type.py b/src/sage/combinat/similarity_class_type.py index 7fcad4dd02a..0ba9e182731 100644 --- a/src/sage/combinat/similarity_class_type.py +++ b/src/sage/combinat/similarity_class_type.py @@ -177,7 +177,7 @@ class type, it is also possible to compute the number of classes of that type from operator import mul from itertools import chain -from sage.misc.misc import prod +from sage.misc.all import prod from sage.functions.all import factorial from sage.rings.arith import moebius from sage.structure.parent import Parent diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py index 024921208f8..1a25def9f2b 100644 --- a/src/sage/combinat/skew_partition.py +++ b/src/sage/combinat/skew_partition.py @@ -1422,7 +1422,7 @@ def __iter__(self): sage: SP = SkewPartitions() sage: it = SP.__iter__() - sage: [it.next() for x in range(10)] + sage: [next(it) for x in range(10)] [[] / [], [1] / [], [2] / [], diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index 245e9a974cb..e0cd3671649 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -1446,7 +1446,7 @@ def __iter__(self): EXAMPLES:: sage: it = StandardTableaux().__iter__() - sage: [it.next() for x in range(10)] + sage: [next(it) for x in range(10)] [[], [[1]], [[1, 2]], @@ -1812,7 +1812,7 @@ def __iter__(self): EXAMPLES:: sage: it = SemistandardSkewTableaux(max_entry = 5).__iter__() - sage: [it.next() for x in range(12)] + sage: [next(it) for x in range(12)] [[], [[1]], [[2]], @@ -1831,7 +1831,7 @@ def __iter__(self): for all `n`:: sage: it = SemistandardSkewTableaux().__iter__() - sage: [it.next() for x in range(10)] + sage: [next(it) for x in range(10)] [[], [[1]], [[1, 1]], diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index 4dc24028bc7..0d611efc681 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -306,7 +306,7 @@ def __getitem__(self, n): from sage.matrix.matrix_space import MatrixSpace from sage.rings.rational_field import QQ from sage.combinat import combinat -from sage.misc.misc import prod +from sage.misc.all import prod import sage.interfaces.gap as gap # This one should be here! @@ -657,7 +657,7 @@ def cf(self): EXAMPLES:: sage: it = sloane.A000009.cf() - sage: [it.next() for i in range(14)] + sage: [next(it) for i in range(14)] [1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 15, 18] """ R, x = QQ['x'].objgen() @@ -683,7 +683,7 @@ def _precompute(self, how_many=50): except AttributeError: self._f = self.cf() f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def _eval(self, n): @@ -765,7 +765,7 @@ def pi(self): EXAMPLES:: sage: it = sloane.A000796.pi() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [3, 1, 4, 1, 5, 9, 2, 6, 5, 3] """ k, a, b, a1, b1 = ZZ(2), ZZ(4), ZZ(1), ZZ(12), ZZ(4) @@ -793,7 +793,7 @@ def _precompute(self, how_many=1000): except AttributeError: self._f = self.pi() f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def _eval(self, n): @@ -4155,7 +4155,7 @@ def _precompute(self, how_many=500): except AttributeError: self._f = self.fib() f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def fib(self): """ @@ -4164,7 +4164,7 @@ def fib(self): EXAMPLES:: sage: it = sloane.A000045.fib() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] """ x, y = Integer(0), Integer(1) @@ -5077,7 +5077,7 @@ def _precompute(self, how_many=10): except AttributeError: self._f = self.df() f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def df(self): """ @@ -5086,7 +5086,7 @@ def df(self): EXAMPLES:: sage: it = sloane.A006882.df() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [1, 1, 2, 3, 8, 15, 48, 105, 384, 945] """ x = Integer(1) @@ -5367,14 +5367,14 @@ def _precompute(self, how_many=20): except AttributeError: self._f = self.gen(*self._a0a1d) f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def gen(self,a0,a1,d): """ EXAMPLES:: sage: it = sloane.A000153.gen(0,1,2) - sage: [it.next() for i in range(5)] + sage: [next(it) for i in range(5)] [0, 1, 2, 7, 32] """ x, y = ZZ(a0), ZZ(a1) @@ -5724,7 +5724,7 @@ def gen(self,a0,a1,d): sage: from sage.combinat.sloane_functions import ExtremesOfPermanentsSequence2 sage: e = ExtremesOfPermanentsSequence2() sage: it = e.gen(6,43,6) - sage: [it.next() for i in range(5)] + sage: [next(it) for i in range(5)] [6, 43, 307, 2542, 23799] """ x, y = ZZ(a0), ZZ(a1) @@ -6772,7 +6772,7 @@ def recur_gen2b(a0,a1,a2,a3,b): sage: from sage.combinat.sloane_functions import recur_gen2b sage: it = recur_gen2b(1,1,1,1, lambda n: 0) - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] """ x, y = ZZ(a0), ZZ(a1) @@ -6798,7 +6798,7 @@ def _precompute(self, how_many=20): except AttributeError: self._f = recur_gen2b(*self._params) f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def _eval(self, n): """ @@ -7622,7 +7622,7 @@ def recur_gen2(a0,a1,a2,a3): sage: from sage.combinat.sloane_functions import recur_gen2 sage: it = recur_gen2(1,1,1,1) - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] """ x, y = ZZ(a0), ZZ(a1) @@ -7652,7 +7652,7 @@ def _precompute(self, how_many=150): except AttributeError: self._f = recur_gen2(*self._params) f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def _eval(self, n): """ @@ -8627,7 +8627,7 @@ def recur_gen3(a0,a1,a2,a3,a4,a5): sage: from sage.combinat.sloane_functions import recur_gen3 sage: it = recur_gen3(1,1,1,1,1,1) - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] [1, 1, 1, 3, 5, 9, 17, 31, 57, 105] """ x, y ,z = Integer(a0), Integer(a1), Integer(a2) @@ -8702,7 +8702,7 @@ def _precompute(self, how_many=20): except AttributeError: self._f = recur_gen3(1,1,1,1,1,1) f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def _eval(self, n): """ @@ -8789,7 +8789,7 @@ def _precompute(self, how_many=20): except AttributeError: self._f = recur_gen3(0,0,1,1,1,1) f = self._f - self._b += [f.next() for i in range(how_many)] + self._b += [next(f) for i in range(how_many)] def _eval(self, n): """ diff --git a/src/sage/combinat/species/combinatorial_logarithm.py b/src/sage/combinat/species/combinatorial_logarithm.py index 26fe7225579..a410d5cc7bf 100644 --- a/src/sage/combinat/species/combinatorial_logarithm.py +++ b/src/sage/combinat/species/combinatorial_logarithm.py @@ -72,7 +72,7 @@ def _cl_gen (R = RationalField()): sage: from sage.combinat.species.combinatorial_logarithm import _cl_gen sage: g = _cl_gen() - sage: [g.next() for i in range(4)] + sage: [next(g) for i in range(4)] [0, p[1], -1/2*p[1, 1] - 1/2*p[2], 1/3*p[1, 1, 1] - 1/3*p[3]] """ return (_cl_term(i, R) for i in _integers_from(0)) diff --git a/src/sage/combinat/species/empty_species.py b/src/sage/combinat/species/empty_species.py index 50e174e3d76..3d46424cdf2 100644 --- a/src/sage/combinat/species/empty_species.py +++ b/src/sage/combinat/species/empty_species.py @@ -110,7 +110,7 @@ def _gs(self, series_ring, base_ring): sage: F.generating_series().count(4) 0 """ - return series_ring.zero_element() + return series_ring.zero() _itgs = _gs _cis = _gs diff --git a/src/sage/combinat/species/generating_series.py b/src/sage/combinat/species/generating_series.py index f523c95aefe..851706df1b2 100644 --- a/src/sage/combinat/species/generating_series.py +++ b/src/sage/combinat/species/generating_series.py @@ -262,7 +262,7 @@ def _functorial_compose_gen(self, y, ao): sage: g1 = WP.generating_series() sage: g2 = P2.generating_series() sage: g = g1._functorial_compose_gen(g2, 0) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [1, 1, 1, 4/3, 8/3, 128/15, 2048/45, 131072/315, 2097152/315, 536870912/2835] """ n = 0 @@ -278,7 +278,7 @@ def factorial_gen(): sage: from sage.combinat.species.generating_series import factorial_gen sage: g = factorial_gen() - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [1, 1, 2, 6, 24] """ z = Integer(1) @@ -424,7 +424,7 @@ def _stretch_gen(self, k, ao): sage: CIS = CycleIndexSeriesRing(p) sage: f = CIS([p([1])]) sage: g = f._stretch_gen(2,0) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [p[2], 0, p[2], 0, p[2], 0, p[2], 0, p[2], 0] """ from sage.combinat.partition import Partition @@ -500,7 +500,7 @@ def _ogs_gen(self, ao): sage: P = species.PermutationSpecies() sage: cis = P.cycle_index_series() sage: g = cis._ogs_gen(0) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ for i in range(ao): @@ -532,7 +532,7 @@ def _egs_gen(self, ao): sage: P = species.PermutationSpecies() sage: cis = P.cycle_index_series() sage: g = cis._egs_gen(0) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ for i in range(ao): @@ -633,7 +633,7 @@ def _functorial_compose_gen(self, g, ao): sage: P2_cis = P2.cycle_index_series() sage: WP_cis = WP.cycle_index_series() sage: g = WP_cis._functorial_compose_gen(P2_cis,0) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [p[], p[1], p[1, 1] + p[2], @@ -837,7 +837,7 @@ def _compose_gen(self, y, ao): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: E_cis = E.cycle_index_series() sage: g = E_cis._compose_gen(C.cycle_index_series(),0) - sage: [g.next() for i in range(4)] + sage: [next(g) for i in range(4)] [p[], p[1], p[1, 1] + p[2], p[1, 1, 1] + p[2, 1] + p[3]] """ assert y.coefficient(0) == 0 @@ -926,7 +926,7 @@ def _weighted_compose_gen(self, y_species, ao): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: E_cis = E.cycle_index_series() sage: g = E_cis._weighted_compose_gen(C,0) - sage: [g.next() for i in range(4)] + sage: [next(g) for i in range(4)] [p[], p[1], p[1, 1] + p[2], p[1, 1, 1] + p[2, 1] + p[3]] """ parent = self.parent() diff --git a/src/sage/combinat/species/misc.py b/src/sage/combinat/species/misc.py index 805f2316500..cd65dd0af7f 100644 --- a/src/sage/combinat/species/misc.py +++ b/src/sage/combinat/species/misc.py @@ -16,7 +16,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** from sage.groups.all import PermutationGroup, PermutationGroup_generic, PermutationGroupElement, SymmetricGroup -from sage.misc.misc import prod +from sage.misc.all import prod from functools import wraps def change_support(perm, support, change_perm=None): diff --git a/src/sage/combinat/species/permutation_species.py b/src/sage/combinat/species/permutation_species.py index c72caec60ca..d19fdc4fbeb 100644 --- a/src/sage/combinat/species/permutation_species.py +++ b/src/sage/combinat/species/permutation_species.py @@ -248,7 +248,7 @@ def _cis_gen(self, base_ring, n): sage: P = species.PermutationSpecies() sage: g = P._cis_gen(QQ, 2) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [p[], 0, p[2], 0, p[2, 2], 0, p[2, 2, 2], 0, p[2, 2, 2, 2], 0] """ from sage.combinat.sf.sf import SymmetricFunctions diff --git a/src/sage/combinat/species/product_species.py b/src/sage/combinat/species/product_species.py index a37f074ddf1..9e1f98c9a52 100644 --- a/src/sage/combinat/species/product_species.py +++ b/src/sage/combinat/species/product_species.py @@ -370,7 +370,7 @@ def _equation(self, var_mapping): sage: S.algebraic_equation_system() [node0 - z^2] """ - from sage.misc.misc import prod + from sage.misc.all import prod return prod(var_mapping[operand] for operand in self._state_info) diff --git a/src/sage/combinat/species/series.py b/src/sage/combinat/species/series.py index b888194793c..9e1db82eec0 100644 --- a/src/sage/combinat/species/series.py +++ b/src/sage/combinat/species/series.py @@ -31,9 +31,10 @@ from stream import Stream, Stream_class from series_order import bounded_decrement, increment, inf, unk from sage.rings.all import Integer -from sage.misc.misc import prod +from sage.misc.all import prod from functools import partial from sage.misc.misc import repr_lincomb, is_iterator +from sage.misc.superseded import deprecated_function_alias from sage.algebras.algebra import Algebra from sage.algebras.algebra_element import AlgebraElement @@ -121,7 +122,6 @@ def _coerce_impl(self, x): """ return self(x) - def __call__(self, x=None, order=unk): """ EXAMPLES:: @@ -203,17 +203,28 @@ def __call__(self, x=None, order=unk): raise TypeError("do not know how to coerce %s into self"%x) - def zero_element(self): + def zero(self): """ Returns the zero power series. EXAMPLES:: sage: L = LazyPowerSeriesRing(QQ) + sage: L.zero() + 0 + + TESTS: + + Check that the method `zero_element` raises a warning (:trac:`17694`):: + sage: L.zero_element() + doctest:...: DeprecationWarning: zero_element is deprecated. Please use zero instead. + See http://trac.sagemath.org/17694 for details. 0 """ - return self(self.base_ring()(0)) + return self(self.base_ring().zero()) + + zero_element = deprecated_function_alias(17694, zero) def identity_element(self): """ @@ -308,7 +319,7 @@ def _sum_gen(self, series_list): sage: L = LazyPowerSeriesRing(QQ) sage: series_list = [ L([1]), L([0,1]), L([0,0,1]) ] sage: g = L._sum_gen(series_list) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [1, 2, 3, 3, 3] """ last_index = len(series_list) - 1 @@ -341,7 +352,7 @@ def _sum_generator_gen(self, g): ... while True: ... yield s sage: g = L._sum_generator_gen(f()) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] """ s = Stream(g) @@ -385,10 +396,10 @@ def _product_generator_gen(self, g): sage: L = LazyPowerSeriesRing(QQ) sage: g = imap(lambda i: L([1]+[0]*i+[1]), _integers_from(0)) sage: g2 = L._product_generator_gen(g) - sage: [g2.next() for i in range(10)] + sage: [next(g2) for i in range(10)] [1, 1, 2, 4, 7, 12, 20, 33, 53, 84] """ - z = g.next() + z = next(g) yield z.coefficient(0) yield z.coefficient(1) @@ -486,7 +497,7 @@ def __init__(self, A, stream=None, order=None, aorder=None, aorder_changed=True, self.order = inf self.aorder_changed = aorder_changed self.is_initialized = is_initialized - self._zero = A.base_ring().zero_element() + self._zero = A.base_ring().zero() self._name = name def compute_aorder(*args, **kwargs): @@ -1040,13 +1051,13 @@ def _plus_gen(self, y, ao): sage: L = LazyPowerSeriesRing(QQ) sage: gs1 = L([1]) sage: g = gs1._plus_gen(gs1, 0) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [2, 2, 2, 2, 2] :: sage: g = gs1._plus_gen(gs1, 2) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [0, 0, 2, 2, 2] """ base_ring = self.parent().base_ring() @@ -1115,7 +1126,7 @@ def _times_gen(self, y, ao): sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1,1,0]) sage: g = f._times_gen(f,0) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [1, 2, 1, 0, 0] """ base_ring = self.parent().base_ring() @@ -1220,7 +1231,7 @@ def _compose_gen(self, y, ao): sage: s = L([1]) sage: t = L([0,1]) sage: g = s._compose_gen(t, 0) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [1, 1, 2, 4, 8, 16, 32, 64, 128, 256] """ assert y.coefficient(0) == 0 @@ -1260,10 +1271,10 @@ def iterator(self, n=0, initial=None): sage: L = LazyPowerSeriesRing(QQ) sage: f = L(range(10)) sage: g = f.iterator(2) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [2, 3, 4, 5, 6] sage: g = f.iterator(2, initial=[0,0]) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [0, 0, 2, 3, 4] """ if initial is not None: @@ -1284,11 +1295,11 @@ def _power_gen(self): sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1,1,0]) sage: g = f._power_gen() - sage: g.next().coefficients(5) + sage: next(g).coefficients(5) [1, 1, 0, 0, 0] - sage: g.next().coefficients(5) + sage: next(g).coefficients(5) [1, 2, 1, 0, 0] - sage: g.next().coefficients(5) + sage: next(g).coefficients(5) [1, 3, 3, 1, 0] """ z = self @@ -1365,7 +1376,7 @@ def _diff_gen(self, ao): sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1]) sage: g = f._diff_gen(0) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] """ n = 1 @@ -1456,7 +1467,7 @@ def _integral_zero_gen(self, ao): sage: L = LazyPowerSeriesRing(QQ) sage: s = L.gen() sage: g = s._integral_zero_gen(1) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [0, 0, 1/2, 0, 0] """ for n in range(ao): @@ -1480,7 +1491,7 @@ def _integral_nonzero_gen(self, integration_constant): sage: L = LazyPowerSeriesRing(QQ) sage: f = L._new_initial(2, Stream([0,0,4,5,6,0])).derivative() sage: g = f._integral_nonzero_gen(1) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [1, 0, 4, 5, 6] """ yield integration_constant @@ -1557,7 +1568,7 @@ def exponential(self): sage: u = f.exponential() sage: g = inv_factorial() sage: z1 = [1,1,2,5,15,52,203,877,4140,21147,115975] - sage: l1 = [z*g.next() for z in z1] + sage: l1 = [z*next(g) for z in z1] sage: l1 = [1] + l1[1:] sage: u.coefficients(11) [1, 1, 1, 5/6, 5/8, 13/30, 203/720, 877/5040, 23/224, 1007/17280, 4639/145152] @@ -1621,19 +1632,19 @@ def _restricted_gen(self, mn, mx, ao): sage: L = LazyPowerSeriesRing(QQ) sage: a = L([1]) sage: g = a._restricted_gen(None, None, 2) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [0, 0, 1, 1, 1, 1, 1, 1, 1, 1] sage: g = a._restricted_gen(1, None, 2) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [0, 0, 1, 1, 1, 1, 1, 1, 1, 1] sage: g = a._restricted_gen(3, None, 2) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [0, 0, 0, 1, 1, 1, 1, 1, 1, 1] :: sage: g = a._restricted_gen(1, 5, 2) - sage: [g.next() for i in range(6)] + sage: [next(g) for i in range(6)] [0, 0, 1, 1, 1, 0] """ BR = self.parent().base_ring() diff --git a/src/sage/combinat/species/set_species.py b/src/sage/combinat/species/set_species.py index ca66f4f88a4..672547b7ee4 100644 --- a/src/sage/combinat/species/set_species.py +++ b/src/sage/combinat/species/set_species.py @@ -185,7 +185,7 @@ def _cis_gen(self, base_ring): sage: S = species.SetSpecies() sage: g = S._cis_gen(QQ) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [0, p[1], 1/2*p[2], 1/3*p[3], 1/4*p[4]] """ from sage.combinat.sf.sf import SymmetricFunctions diff --git a/src/sage/combinat/species/stream.py b/src/sage/combinat/species/stream.py index 0a33b98c4e2..4653c2e8b7a 100644 --- a/src/sage/combinat/species/stream.py +++ b/src/sage/combinat/species/stream.py @@ -18,7 +18,7 @@ def _integers_from(n): sage: from sage.combinat.species.stream import _integers_from sage: g = _integers_from(5) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [5, 6, 7, 8, 9] """ while True: @@ -38,7 +38,7 @@ def _apply_function(func, list): ... sage: l = [2] sage: g = _apply_function(square, l) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [4, 16, 256, 65536, 4294967296] """ while True: @@ -330,7 +330,7 @@ def __getitem__(self, i): else: while self._last_index < i: try: - self._list.append(self._gen.next()) + self._list.append(next(self._gen)) self._last_index += 1 except StopIteration: self.end_reached = True @@ -347,7 +347,7 @@ def __iter__(self): sage: from sage.combinat.species.stream import Stream sage: s = Stream([1,2,3]) sage: g = iter(s) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [1, 2, 3, 3, 3] """ i = 0 @@ -491,7 +491,7 @@ def _stretch_gen(self, k): sage: from sage.combinat.species.stream import Stream sage: s = Stream(range(1, 10)) sage: g = s._stretch_gen(2) - sage: [g.next() for i in range(10)] + sage: [next(g) for i in range(10)] [1, 0, 2, 0, 3, 0, 4, 0, 5, 0] """ yield self[0] diff --git a/src/sage/combinat/species/subset_species.py b/src/sage/combinat/species/subset_species.py index b252ebe94c5..435df21c831 100644 --- a/src/sage/combinat/species/subset_species.py +++ b/src/sage/combinat/species/subset_species.py @@ -234,7 +234,7 @@ def _cis_gen(self, base_ring): sage: S = species.SubsetSpecies() sage: g = S._cis_gen(QQ) - sage: [g.next() for i in range(5)] + sage: [next(g) for i in range(5)] [0, 2*p[1], p[2], 2/3*p[3], 1/2*p[4]] """ from sage.combinat.sf.sf import SymmetricFunctions diff --git a/src/sage/combinat/subset.py b/src/sage/combinat/subset.py index 3612bfd20f4..8efb5894338 100644 --- a/src/sage/combinat/subset.py +++ b/src/sage/combinat/subset.py @@ -123,7 +123,7 @@ def Subsets(s, k=None, submultiset=False): sage: S2.cardinality() 256 sage: it = iter(S2) - sage: [it.next() for _ in xrange(8)] + sage: [next(it) for _ in xrange(8)] [{}, {{}}, {{1}}, {{2}}, {{3}}, {{1, 2}}, {{1, 3}}, {{2, 3}}] sage: S2.random_element() # random {{2}, {1, 2, 3}, {}} diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index d7394868735..223ddc60caa 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -92,7 +92,7 @@ import permutation from sage.misc.flatten import flatten from sage.groups.perm_gps.permgroup import PermutationGroup -from sage.misc.misc import uniq, prod +from sage.misc.all import uniq, prod from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.sets_cat import Sets diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index d8931210585..c87b07dc9ac 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -43,11 +43,11 @@ sage: q = Polyomino([(0,0), (0,1), (1,0), (1,1)]) sage: T = TilingSolver([p,q], box=[3,2]) sage: it = T.solve() - sage: it.next() + sage: next(it) [Polyomino: [(0, 0), (0, 1), (1, 0), (1, 1)], Color: gray, Polyomino: [(2, 0), (2, 1)], Color: gray] - sage: it.next() + sage: next(it) [Polyomino: [(1, 0), (1, 1), (2, 0), (2, 1)], Color: gray, Polyomino: [(0, 0), (0, 1)], Color: gray] - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -67,9 +67,9 @@ sage: len(T.rows()) 15 sage: it = T.solve() - sage: it.next() + sage: next(it) [Polyomino: [(0,)], Color: gray, Polyomino: [(1,), (2,)], Color: gray, Polyomino: [(3,), (4,), (5,)], Color: gray] - sage: it.next() + sage: next(it) [Polyomino: [(0,)], Color: gray, Polyomino: [(1,), (2,), (3,)], Color: gray, Polyomino: [(4,), (5,)], Color: gray] sage: T.number_of_solutions() 6 @@ -103,7 +103,7 @@ one solution:: sage: T = TilingSolver(L, (8,8), reflection=True) - sage: solution = T.solve().next() + sage: solution = next(T.solve()) sage: G = sum([piece.show2d() for piece in solution], Graphics()) sage: G.show(aspect_ratio=1, axes=False) @@ -139,7 +139,7 @@ Solve the puzzle and show one solution:: sage: T = TilingSolver(L, (8,8,1)) - sage: solution = T.solve().next() + sage: solution = next(T.solve()) sage: G = sum([piece.show3d(size=0.85) for piece in solution], Graphics()) sage: G.show(aspect_ratio=1, viewer='tachyon') @@ -159,7 +159,7 @@ sage: T = TilingSolver([y], box=(5,10), reusable=True, reflection=True) sage: T.number_of_solutions() 10 - sage: solution = T.solve().next() + sage: solution = next(T.solve()) sage: G = sum([piece.show2d() for piece in solution], Graphics()) sage: G.show(aspect_ratio=1) @@ -221,7 +221,7 @@ import itertools from sage.structure.sage_object import SageObject from sage.misc.cachefunc import cached_method, cached_function -from sage.misc.misc import prod +from sage.misc.all import prod from sage.combinat.all import WeylGroup from sage.plot.all import Graphics from sage.plot.polygon import polygon @@ -433,7 +433,7 @@ def __iter__(self): sage: from sage.combinat.tiling import Polyomino sage: p = Polyomino([(0,0,0), (0,1,0), (1,1,0), (1,1,1)], color='blue') sage: it = iter(p) - sage: it.next() + sage: next(it) (1, 1, 0) """ return iter(self._blocs) @@ -997,14 +997,14 @@ class TilingSolver(SageObject): Solutions are given by an iterator:: sage: it = T.solve() - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: gray Polyomino: [(0, 0, 1), (0, 0, 2)], Color: gray Polyomino: [(0, 0, 3), (0, 0, 4), (0, 0, 5)], Color: gray Another solution:: - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: gray Polyomino: [(0, 0, 1), (0, 0, 2), (0, 0, 3)], Color: gray Polyomino: [(0, 0, 4), (0, 0, 5)], Color: gray @@ -1404,10 +1404,10 @@ def dlx_common_prefix_solutions(self): [82, 119, 150, 171, 38, 161, 8, 63, 140, 107] """ it = self.dlx_solutions() - B = it.next() + B = next(it) while True: yield B - A, B = B, it.next() + A, B = B, next(it) common_prefix = [] for a, b in itertools.izip(A, B): if a == b: @@ -1462,10 +1462,10 @@ def dlx_incremental_solutions(self): 123 """ it = self.dlx_solutions() - B = it.next() + B = next(it) while True: yield B - A, B = B, it.next() + A, B = B, next(it) common_prefix = 0 for a, b in itertools.izip(A, B): if a == b: @@ -1504,15 +1504,15 @@ def solve(self, partial=None): sage: r = Polyomino([(0,0,0), (0,0,1), (0,0,2)]) sage: T = TilingSolver([p,q,r], box=(1,1,6)) sage: it = T.solve() - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: gray Polyomino: [(0, 0, 1), (0, 0, 2)], Color: gray Polyomino: [(0, 0, 3), (0, 0, 4), (0, 0, 5)], Color: gray - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: gray Polyomino: [(0, 0, 1), (0, 0, 2), (0, 0, 3)], Color: gray Polyomino: [(0, 0, 4), (0, 0, 5)], Color: gray - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0), (0, 0, 1)], Color: gray Polyomino: [(0, 0, 2), (0, 0, 3), (0, 0, 4)], Color: gray Polyomino: [(0, 0, 5)], Color: gray @@ -1520,18 +1520,18 @@ def solve(self, partial=None): Including the partial solutions:: sage: it = T.solve(partial='common_prefix') - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: gray Polyomino: [(0, 0, 1), (0, 0, 2)], Color: gray Polyomino: [(0, 0, 3), (0, 0, 4), (0, 0, 5)], Color: gray - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: gray - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: gray Polyomino: [(0, 0, 1), (0, 0, 2), (0, 0, 3)], Color: gray Polyomino: [(0, 0, 4), (0, 0, 5)], Color: gray - sage: for p in it.next(): p - sage: for p in it.next(): p + sage: for p in next(it): p + sage: for p in next(it): p Polyomino: [(0, 0, 0), (0, 0, 1)], Color: gray Polyomino: [(0, 0, 2), (0, 0, 3), (0, 0, 4)], Color: gray Polyomino: [(0, 0, 5)], Color: gray @@ -1543,7 +1543,7 @@ def solve(self, partial=None): sage: r = Polyomino([(0,0,0), (0,0,1), (0,0,2)], color='yellow') sage: T = TilingSolver([p,q,r], box=(1,1,6), reusable=True) sage: it = T.solve() - sage: for p in it.next(): p + sage: for p in next(it): p Polyomino: [(0, 0, 0)], Color: yellow Polyomino: [(0, 0, 1)], Color: yellow Polyomino: [(0, 0, 2)], Color: yellow @@ -1554,7 +1554,7 @@ def solve(self, partial=None): TESTS:: sage: T = TilingSolver([p,q,r], box=(1,1,7)) - sage: T.solve().next() + sage: next(T.solve()) Traceback (most recent call last): ... StopIteration diff --git a/src/sage/combinat/tutorial.py b/src/sage/combinat/tutorial.py index b38a543e527..682cba8a33a 100644 --- a/src/sage/combinat/tutorial.py +++ b/src/sage/combinat/tutorial.py @@ -1012,18 +1012,18 @@ returns successively the binomial coefficients `\binom 3 i` with `i=0,1,2,3`:: - sage: it.next() + sage: next(it) 1 - sage: it.next() + sage: next(it) 3 - sage: it.next() + sage: next(it) 3 - sage: it.next() + sage: next(it) 1 When the iterator is finally exhausted, an exception is raised:: - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -1131,9 +1131,9 @@ sage: counter_examples = \ ... (p for p in range(1000) ... if is_prime(p) and not is_prime(mersenne(p))) - sage: counter_examples.next() + sage: next(counter_examples) 11 - sage: counter_examples.next() + sage: next(counter_examples) 23 .. topic:: Exercice @@ -1318,18 +1318,18 @@ therefore an iterator over the successive values returned by ``yield``:: sage: g = f(4) - sage: g.next() + sage: next(g) 0 - sage: g.next() + sage: next(g) 1 - sage: g.next() + sage: next(g) 2 - sage: g.next() + sage: next(g) 3 :: - sage: g.next() + sage: next(g) Traceback (most recent call last): ... StopIteration diff --git a/src/sage/combinat/words/abstract_word.py b/src/sage/combinat/words/abstract_word.py index b9aca87ed58..ec3c825dac1 100644 --- a/src/sage/combinat/words/abstract_word.py +++ b/src/sage/combinat/words/abstract_word.py @@ -294,10 +294,10 @@ def __cmp__(self, other): cmp_fcn = self._parent.cmp_letters while True: try: - cs = self_it.next() + cs = next(self_it) except StopIteration: try: - co = other_it.next() + co = next(other_it) except StopIteration: # If both self_it and other_it are exhausted then # self == other. Return 0. @@ -308,7 +308,7 @@ def __cmp__(self, other): return -1 else: try: - co = other_it.next() + co = next(other_it) except StopIteration: # If self_it is not exhausted but other_it is, then # other is a proper prefix of self: return 1. @@ -381,10 +381,10 @@ def __eq__(self, other): self_it, other_it = iter(self), iter(other) while True: try: - cs = self_it.next() + cs = next(self_it) except StopIteration: try: - co = other_it.next() + co = next(other_it) except StopIteration: # If both self_it and other_it are exhausted then # self == other. Return 0. @@ -395,7 +395,7 @@ def __eq__(self, other): return False else: try: - co = other_it.next() + co = next(other_it) except StopIteration: # If self_it is not exhausted but other_it is, then # other is a proper prefix of self: return 1. @@ -635,7 +635,7 @@ def is_empty(self): False """ try: - iter(self).next() + next(iter(self)) return False except StopIteration: return True @@ -658,7 +658,7 @@ def _to_integer_iterator(self, use_parent_alphabet=False): sage: from itertools import count sage: w = Word(count()) sage: ir = w._to_integer_iterator() - sage: [ir.next() for _ in range(10)] + sage: [next(ir) for _ in range(10)] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] sage: w = Word(iter("abbacabba")) sage: ir = w._to_integer_iterator() @@ -928,7 +928,7 @@ def _iterated_right_palindromic_closure_iterator(self, f=None): sage: w = Word() sage: it = w._iterated_right_palindromic_closure_iterator() - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -1011,7 +1011,7 @@ def _iterated_right_palindromic_closure_recursive_iterator(self, f=None): sage: w = Word() sage: it = w._iterated_right_palindromic_closure_recursive_iterator() - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -1412,17 +1412,17 @@ def _finite_differences_iterator(self, mod=None): if mod in (None, 0): i = iter(self) j = iter(self) - j.next() + next(j) while True: - yield j.next() - i.next() + yield next(j) - next(i) elif mod in ZZ: Zn = Integers(mod) i = iter(self) j = iter(self) - j.next() + next(j) while True: - yield Zn(j.next() - i.next()) + yield Zn(next(j) - next(i)) else: raise TypeError('mod(=%s) must be None or an integer'%mod) @@ -1605,11 +1605,11 @@ def factor_occurrences_iterator(self, fact): sage: TM = words.ThueMorseWord() sage: fact = Word([0,1,1,0,1]) sage: it = TM.factor_occurrences_iterator(fact) - sage: it.next() + sage: next(it) 0 - sage: it.next() + sage: next(it) 12 - sage: it.next() + sage: next(it) 24 """ if fact.is_empty(): @@ -1646,23 +1646,23 @@ def return_words_iterator(self, fact): sage: TM = words.ThueMorseWord() sage: fact = Word([0,1,1,0,1]) sage: it = TM.return_words_iterator(fact) - sage: it.next() + sage: next(it) word: 011010011001 - sage: it.next() + sage: next(it) word: 011010010110 - sage: it.next() + sage: next(it) word: 0110100110010110 - sage: it.next() + sage: next(it) word: 01101001 - sage: it.next() + sage: next(it) word: 011010011001 - sage: it.next() + sage: next(it) word: 011010010110 """ it = self.factor_occurrences_iterator(fact) - i = it.next() + i = next(it) while True: - j = it.next() + j = next(it) yield self[i:j] i = j @@ -1688,17 +1688,17 @@ def complete_return_words_iterator(self, fact): sage: TM = words.ThueMorseWord() sage: fact = Word([0,1,1,0,1]) sage: it = TM.complete_return_words_iterator(fact) - sage: it.next() + sage: next(it) word: 01101001100101101 - sage: it.next() + sage: next(it) word: 01101001011001101 - sage: it.next() + sage: next(it) word: 011010011001011001101 - sage: it.next() + sage: next(it) word: 0110100101101 - sage: it.next() + sage: next(it) word: 01101001100101101 - sage: it.next() + sage: next(it) word: 01101001011001101 REFERENCES: @@ -1708,9 +1708,9 @@ def complete_return_words_iterator(self, fact): """ it = self.factor_occurrences_iterator(fact) L = fact.length() - i = it.next() + i = next(it) while True: - j = it.next() + j = next(it) yield self[i:j+L] i = j diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index ce151013b94..90485bdac75 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -137,20 +137,20 @@ Factors and Rauzy Graphs ======================== -Enumeration of factors, the successive values returned by it.next() +Enumeration of factors, the successive values returned by next(it) can appear in a different order depending on hardware. Therefore we mark the three first results of the test random. The important test is that the iteration stops properly on the fourth call:: sage: w = Word([4,5,6])^7 sage: it = w.factor_iterator(4) - sage: it.next() # random + sage: next(it) # random word: 6456 - sage: it.next() # random + sage: next(it) # random word: 5645 - sage: it.next() # random + sage: next(it) # random word: 4564 - sage: it.next() + sage: next(it) Traceback (most recent call last): ... StopIteration @@ -1946,11 +1946,11 @@ def is_cadence(self, seq): return True try: it = iter(self) - s = islice(it, seq[0], None).next() + s = next(islice(it, seq[0], None)) for i in xrange(1, len(seq)): steps = seq[i] - seq[i-1] - for n in xrange(steps-1): it.next() - if it.next() != s: + for n in xrange(steps-1): next(it) + if next(it) != s: return False except StopIteration: return False @@ -2004,7 +2004,7 @@ def longest_common_suffix(self, other): return other iter = enumerate(izip(reversed(self), reversed(other))) - i,(b,c) = iter.next() + i,(b,c) = next(iter) if b != c: #In this case, return the empty word return self[:0] @@ -3273,10 +3273,10 @@ def is_subword_of(self, other): """ its = iter(self) try: - s = its.next() + s = next(its) for e in other: if s == e: - s = its.next() + s = next(its) else: return False except StopIteration: @@ -4872,12 +4872,12 @@ def balance(self): end = iter(self) abelian = dict(zip(alphabet, [0]*len(alphabet))) for _ in range(i): - abelian[end.next()] += 1 + abelian[next(end)] += 1 abel_max = abelian.copy() abel_min = abelian.copy() for _ in range(self.length() - i): - lost = start.next() - gain = end.next() + lost = next(start) + gain = next(end) abelian[gain] += 1 abelian[lost] -= 1 abel_max[gain] = max(abel_max[gain], abelian[gain]) @@ -5040,11 +5040,11 @@ def abelian_vectors(self, n): end = iter(self) abelian = [0] * size for _ in range(n): - abelian[rank[end.next()]] += 1 + abelian[rank[next(end)]] += 1 S.add(tuple(abelian)) for letter in end: abelian[rank[letter]] += 1 - abelian[rank[start.next()]] -= 1 + abelian[rank[next(start)]] -= 1 S.add(tuple(abelian)) return S @@ -5678,17 +5678,17 @@ def delta_inv(self, W=None, s=None): if self.is_empty(): return Words(alphabet)() if s is None: - s = cycle_alphabet.next() + s = next(cycle_alphabet) else: if s not in alphabet: raise ValueError("starting letter not in alphabet") - t = cycle_alphabet.next() + t = next(cycle_alphabet) while t != s: - t = cycle_alphabet.next() + t = next(cycle_alphabet) w = [] for i in self: w.extend([s] * i) - s = cycle_alphabet.next() + s = next(cycle_alphabet) return Words(alphabet)(w) def delta(self): diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index 7f3e604ffc6..35fbfdbf7c3 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -709,7 +709,7 @@ def __call__(self, w, order=1, datatype='iter'): letter = w[0] elif hasattr(w, '__iter__'): try: - letter = w.next() + letter = next(w) except StopIteration: return self.codomain()() elif w in self._domain.alphabet(): @@ -1678,7 +1678,7 @@ def _fixed_point_iterator(self, letter): sage: s = WordMorphism({('a', 1):[('a', 1), ('a', 2)], ('a', 2):[('a', 1)]}) sage: it = s._fixed_point_iterator(('a',1)) - sage: it.next() + sage: next(it) ('a', 1) This shows that ticket :trac:`13668` has been resolved:: @@ -1963,7 +1963,7 @@ def has_left_conjugate(self): I = itertools.ifilterfalse(FiniteWord_class.is_empty, self.images()) try: - letter = I.next()[0] + letter = next(I)[0] except StopIteration: return True @@ -2436,7 +2436,7 @@ def rauzy_fractal_points(self, n=None, exchange=False, eig=None, translate=None, S = 0 orbit_points = dict([(a,[]) for a in alphabet]) for _ in xrange(n): - a = u.next() + a = next(u) S += canonical_basis_proj[a] orbit_points[a].append(S) diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py index c05df8196a2..d1dfa32cc9a 100644 --- a/src/sage/combinat/words/paths.py +++ b/src/sage/combinat/words/paths.py @@ -59,6 +59,8 @@ Methods inherited from FiniteWordPath_all: ... This only works on Python classes that derive from SageObject. + ... + See http://trac.sagemath.org/2536 for details. Since p is a finite word, many functions from the word library are available:: @@ -1279,7 +1281,7 @@ def projected_point_iterator(self, v=None, ring=None): sage: P = WordPaths('123',[(1,0,0),(0,1,0),(0,0,1)]) sage: w = P(D[:200]) sage: it = w.projected_point_iterator(v) - sage: for i in range(6): it.next() + sage: for i in range(6): next(it) (0.000000000000000, 0.000000000000000) (-0.526233343362516, 0.000000000000000) (0.220830337618112, -0.477656250512816) @@ -1292,7 +1294,7 @@ def projected_point_iterator(self, v=None, ring=None): sage: P = WordPaths('ab','ne') sage: p = P('aabbabbab') sage: it = p.projected_point_iterator(ring=RealField(20)) - sage: for i in range(8): it.next() + sage: for i in range(8): next(it) (0.00000) (0.78087) (1.5617) @@ -1418,7 +1420,7 @@ def plot_projection(self, v=None, letters=None, color=None, ring=None, color = dict( (a, hue(A.rank(a)/float(A.cardinality()))) for a in A ) it = self.projected_point_iterator(v, ring=ring) if kind == 'right': - start = it.next() + start = next(it) elif kind != 'left': raise ValueError('unknown value for kind (=%s)'%kind) tout = [point([c], color=color[a], size=size) for a, c in izip(self, it) if a in letters] @@ -1706,9 +1708,11 @@ def plot_directive_vector(self, options=dict(rgbcolor='blue')): INPUT: - - ``options`` - (dictionary, default: {'rgbcolor': 'blue'} graphic + - ``options`` - dictionary, default: {'rgbcolor': 'blue'} graphic options for the arrow + If the start is the same as the end, a single point is returned. + EXAMPLES:: sage: P = WordPaths('abcd'); P @@ -1716,18 +1720,19 @@ def plot_directive_vector(self, options=dict(rgbcolor='blue')): sage: p = P('aaaccaccacacacaccccccbbdd'); p Path: aaaccaccacacacaccccccbbdd sage: R = p.plot() + p.plot_directive_vector() - sage: show(R, axes=False, aspect_ratio=1) + sage: R.plot(axes=False, aspect_ratio=1) + Graphics object consisting of 4 graphics primitives TESTS: A closed path:: sage: P('acbd').plot_directive_vector() - Graphics object consisting of 0 graphics primitives + Graphics object consisting of 1 graphics primitive """ start = self.start_point() end = self.end_point() - if (start == end) : + if (start == end): G = point(start, pointsize=10, **options) else: G = arrow(start, end, **options) diff --git a/src/sage/combinat/words/word_char.pyx b/src/sage/combinat/words/word_char.pyx index 5ff580d84ad..0226b705fde 100644 --- a/src/sage/combinat/words/word_char.pyx +++ b/src/sage/combinat/words/word_char.pyx @@ -210,7 +210,8 @@ cdef class WordDatatype_char(WordDatatype): TO DISCUSS: in Integer (sage.rings.integer) this method is actually an external function. But we might want to have several possible inheritance. """ - cdef WordDatatype_char other = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef WordDatatype_char other = t.__new__(t) other._data = data other._master = master # can be None other._is_slice = 0 if master is None else 1 @@ -511,7 +512,7 @@ cdef class WordDatatype_char(WordDatatype): cdef WordDatatype_char w = self cdef size_t i, rest - if PY_TYPE_CHECK_EXACT(exp, Rational): + if type(exp) is Rational: if w._length % exp.denominator(): raise ValueError("undefined") i = exp.floor() diff --git a/src/sage/combinat/words/word_generators.py b/src/sage/combinat/words/word_generators.py index ec3be815a82..1bd29e2301f 100644 --- a/src/sage/combinat/words/word_generators.py +++ b/src/sage/combinat/words/word_generators.py @@ -198,8 +198,8 @@ def __init__(self, p, q, alphabet=(0,1), algorithm='cf'): elif (p, q) == (1, 0): w = [alphabet[1]] else: - from sage.rings.all import QQ, CFF - cf = CFF(QQ((p, q))) + from sage.rings.rational_field import QQ + cf = QQ((p, q)).continued_fraction_list() u = [alphabet[0]] v = [alphabet[1]] #do not consider the first zero if p < q @@ -838,9 +838,11 @@ def CharacteristicSturmianWord(self, slope, alphabet=(0, 1), bits=None): :: sage: words.CharacteristicSturmianWord(1/golden_ratio^2, bits=30) + doctest:...: DeprecationWarning: the argument 'bits' is deprecated + See http://trac.sagemath.org/14567 for details. word: 0100101001001010010100100101001001010010... sage: _.length() - 6765 + +Infinity :: @@ -867,15 +869,24 @@ def CharacteristicSturmianWord(self, slope, alphabet=(0, 1), bits=None): sage: u[1:-1] == v[:-2] True """ + if bits is not None: + from sage.misc.superseded import deprecation + deprecation(14567, "the argument 'bits' is deprecated") + if len(set(alphabet)) != 2: raise TypeError("alphabet does not contain two distinct elements") + if slope in RR: if not 0 < slope < 1: msg = "The argument slope (=%s) must be in ]0,1[."%slope raise ValueError(msg) - from sage.rings.all import CFF - cf = iter(CFF(slope, bits=bits)) - length = 'finite' + from sage.rings.continued_fraction import continued_fraction + cf = continued_fraction(slope) + if cf.length() == Infinity: + length = Infinity + else: + length = 'finite' + cf = iter(cf) elif hasattr(slope, '__iter__'): cf = iter(slope) length = Infinity @@ -912,26 +923,26 @@ def _CharacteristicSturmianWord_LetterIterator(self, cf, alphabet=(0,1)): EXAMPLES:: - sage: CFF(1/golden_ratio^2)[:8] - [0, 2, 1, 1, 1, 1, 1, 1] + sage: continued_fraction(1/golden_ratio^2)[:8] + [0; 2, 1, 1, 1, 1, 2] sage: cf = iter(_) sage: Word(words._CharacteristicSturmianWord_LetterIterator(cf)) - word: 0100101001001010010100100101001001 + word: 0100101001001010010100100101001010 :: sage: alpha = (sqrt(3)-1)/2 - sage: CFF(alpha)[:10] - [0, 2, 1, 2, 1, 2, 1, 2, 1, 2] + sage: continued_fraction(alpha)[:10] + [0; 2, 1, 2, 1, 2, 1, 2, 1, 2] sage: cf = iter(_) sage: Word(words._CharacteristicSturmianWord_LetterIterator(cf)) word: 0100100101001001001010010010010100100101... """ - if cf.next() != 0: + if next(cf) != 0: raise ValueError("The first term of the continued fraction expansion must be zero.") s0 = [1] s1 = [0] - e = cf.next() + e = next(cf) if not e >= 1: raise ValueError("The second term of the continued fraction expansion must be larger or equal to 1.") s1, s0 = s1*(e-1) + s0, s1 @@ -941,7 +952,7 @@ def _CharacteristicSturmianWord_LetterIterator(self, cf, alphabet=(0,1)): n += 1 yield alphabet[i] else: - s1, s0 = s1*cf.next() + s0, s1 + s1, s0 = s1*next(cf) + s0, s1 def KolakoskiWord(self, alphabet=(1,2)): r""" @@ -1289,14 +1300,14 @@ def _StandardEpisturmianWord_LetterIterator(self, directive_word): else: d = iter(directive_word) W = directive_word.parent() - w = W(d.next()) + w = W(next(d)) n = 0 while True: for x in w[n:]: n += 1 yield x else: - w = W(w*W(d.next())).palindromic_closure() + w = W(w*W(next(d))).palindromic_closure() def MinimalSmoothPrefix(self, n): r""" @@ -1619,11 +1630,11 @@ def _s_adic_iterator(self, sequence, letters): """ from itertools import tee,izip sequence_it,sequence = tee(sequence) - m = sequence_it.next() + m = next(sequence_it) codomain = m.codomain() p = codomain.identity_morphism() letters_it,letters = tee(letters) - precedent_letter = m(letters_it.next())[0] + precedent_letter = m(next(letters_it))[0] yield precedent_letter for (i,(m,a)) in enumerate(izip(sequence, letters)): @@ -1884,7 +1895,7 @@ def s_adic(self, sequence, letters, morphisms=None): from itertools import tee seq_it,seq= tee(seq) - m = seq_it.next() + m = next(seq_it) W = m.codomain() kwds = {} diff --git a/src/sage/combinat/words/word_infinite_datatypes.py b/src/sage/combinat/words/word_infinite_datatypes.py index 9cbcd1d8978..603d35d6fce 100644 --- a/src/sage/combinat/words/word_infinite_datatypes.py +++ b/src/sage/combinat/words/word_infinite_datatypes.py @@ -69,7 +69,7 @@ def __iter__(self): sage: w = Word(lambda x : x % 2) sage: it = iter(w) - sage: [it.next() for _ in range(10)] + sage: [next(it) for _ in range(10)] [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] TESTS:: @@ -78,7 +78,7 @@ def __iter__(self): sage: s = WordDatatype_callable(Words(), lambda n:n%3+10, length=10); s sage: it = iter(s) - sage: [it.next() for _ in range(10)] + sage: [next(it) for _ in range(10)] [10, 11, 12, 10, 11, 12, 10, 11, 12, 10] """ if self._len is Infinity: @@ -346,7 +346,7 @@ def __iter__(self): sage: w = Word(lambda x : x % 2) sage: it = iter(w) - sage: [it.next() for _ in range(10)] + sage: [next(it) for _ in range(10)] [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] """ if self._len is Infinity: @@ -844,11 +844,11 @@ def __getitem__(self, key): else: key = self.length() + key it = iter(self) - a = it.next() + a = next(it) counter = 0 while counter < key: try: - a = it.next() + a = next(it) counter += 1 except StopIteration: raise IndexError("word index out of range") @@ -921,7 +921,7 @@ def __iter__(self): sage: w = Word(iter([0,1,0,0,1,0,1,0,0,1,0,1,0])) sage: it = iter(w) - sage: [it.next() for _ in range(10)] + sage: [next(it) for _ in range(10)] [0, 1, 0, 0, 1, 0, 1, 0, 0, 1] """ # first iterator through the cached values @@ -1123,7 +1123,7 @@ def __getitem__(self, key): else: while self._last_index < key: try: - self._list.append(self._gen.next()) + self._list.append(next(self._gen)) self._last_index += 1 except StopIteration: raise IndexError("word index out of range") diff --git a/src/sage/combinat/words/words.py b/src/sage/combinat/words/words.py index bca5cfa9463..18b1d430168 100644 --- a/src/sage/combinat/words/words.py +++ b/src/sage/combinat/words/words.py @@ -1174,7 +1174,7 @@ def iter_morphisms(self, arg=None, codomain=None, min_length=1): sage: W = Words('ab') sage: it = W.iter_morphisms() - sage: for _ in range(7): it.next() + sage: for _ in range(7): next(it) WordMorphism: a->a, b->a WordMorphism: a->a, b->b WordMorphism: a->b, b->a @@ -1187,7 +1187,7 @@ def iter_morphisms(self, arg=None, codomain=None, min_length=1): sage: W = Words('ab') sage: it = W.iter_morphisms(min_length=0) - sage: for _ in range(7): it.next() + sage: for _ in range(7): next(it) WordMorphism: a->, b-> WordMorphism: a->a, b-> WordMorphism: a->b, b-> @@ -1299,7 +1299,7 @@ def iter_morphisms(self, arg=None, codomain=None, min_length=1): WordMorphism: x->, y->bb, z->a WordMorphism: x->, y->bb, z->b sage: it = W.iter_morphisms(codomain=Y) - sage: for _ in range(10): it.next() + sage: for _ in range(10): next(it) WordMorphism: a->x, b->x WordMorphism: a->x, b->y WordMorphism: a->x, b->z diff --git a/src/sage/crypto/boolean_function.pyx b/src/sage/crypto/boolean_function.pyx index afbca024b03..93fea4e7f07 100644 --- a/src/sage/crypto/boolean_function.pyx +++ b/src/sage/crypto/boolean_function.pyx @@ -959,7 +959,7 @@ cdef class BooleanFunction(SageObject): s = vector(self.truth_table()).support() from sage.combinat.combination import Combinations - from sage.misc.misc import prod + from sage.misc.all import prod from sage.matrix.constructor import Matrix from sage.rings.arith import binomial diff --git a/src/sage/data_structures/binary_matrix.pxd b/src/sage/data_structures/binary_matrix.pxd new file mode 100644 index 00000000000..31d3fd8c4d5 --- /dev/null +++ b/src/sage/data_structures/binary_matrix.pxd @@ -0,0 +1,8 @@ +from sage.data_structures.bitset cimport bitset_t + +cdef struct binary_matrix_s: + Py_ssize_t n_cols + Py_ssize_t n_rows + bitset_t* rows + +ctypedef binary_matrix_s[1] binary_matrix_t diff --git a/src/sage/data_structures/binary_matrix.pxi b/src/sage/data_structures/binary_matrix.pxi new file mode 100644 index 00000000000..ea6ec731588 --- /dev/null +++ b/src/sage/data_structures/binary_matrix.pxi @@ -0,0 +1,102 @@ +r""" +A binary matrix datatype in Cython + +It's almost a copy of the bitset datatype, but allows a differentiation of the +rows of the matrix. That's the only advantage compared to storing all the rows +of a matrix in a loooooonng bitset. + +A ``binary_matrix_t`` structure contains : + +- ``Py_ssize_t n_cols`` -- number of columns + +- ``Py_ssize_t n_rows`` -- number of rows + +- ``bitset_t * rows`` -- ``rows[i]`` points toward a block of type ``bitset_t`` + containing the bits of row `i`. + +""" + +from sage.data_structures.binary_matrix cimport * +include 'sage/data_structures/bitset.pxi' + + +cdef inline binary_matrix_init(binary_matrix_t m, Py_ssize_t n_rows, Py_ssize_t n_cols): + r""" + Allocate an empty binary matrix with ``n_rows`` rows and ``n_cols`` columns. + """ + cdef Py_ssize_t i + + m.n_cols = n_cols + m.n_rows = n_rows + m.rows = sage_malloc(n_rows * sizeof(bitset_t)) + if m.rows == NULL: + raise MemoryError + + for i in range(n_rows): + bitset_init(m.rows[i], n_cols) + +cdef inline binary_matrix_free(binary_matrix_t m): + r""" + Frees the memory allocated by the matrix + """ + cdef Py_ssize_t i + + for i in range(m.n_rows): + bitset_free(m.rows[i]) + sage_free(m.rows) + +cdef inline binary_matrix_fill(binary_matrix_t m, bint bit): + r""" + Fill the whole matrix with a bit + """ + cdef Py_ssize_t i + + if bit: # set the matrix to 1 + for i in range(m.n_rows): + bitset_set_first_n(m.rows[i], m.n_cols) + else: + for i in range(m.n_rows): + bitset_clear(m.rows[i]) + +cdef inline binary_matrix_complement(binary_matrix_t m): + r""" + Complements all of the matrix' bits. + """ + cdef Py_ssize_t i + for i in range(m.n_rows): + bitset_complement(m.rows[i], m.rows[i]) + +cdef inline binary_matrix_set1(binary_matrix_t m, Py_ssize_t row, Py_ssize_t col): + r""" + Sets an entry to 1 + """ + bitset_add(m.rows[row], col) + +cdef inline binary_matrix_set0(binary_matrix_t m, Py_ssize_t row, Py_ssize_t col): + r""" + Sets an entry to 0 + """ + bitset_discard(m.rows[row], col) + +cdef inline binary_matrix_set(binary_matrix_t m, Py_ssize_t row, Py_ssize_t col, bint value): + r""" + Sets an entry + """ + bitset_set_to(m.rows[row],col,value) + +cdef inline bint binary_matrix_get(binary_matrix_t m, Py_ssize_t row, Py_ssize_t col): + r""" + Returns the value of a given entry + """ + return bitset_in(m.rows[row], col) + +cdef inline binary_matrix_print(binary_matrix_t m): + r""" + Prints the binary matrix + """ + cdef Py_ssize_t i,j + import sys + for i in range(m.n_rows): + for j in range(m.n_cols): + sys.stdout.write("1" if binary_matrix_get(m, i, j) else ".",) + print "" diff --git a/src/sage/data_structures/bitset.pxi b/src/sage/data_structures/bitset.pxi index 76452bbe35c..f0f9a3c8deb 100644 --- a/src/sage/data_structures/bitset.pxi +++ b/src/sage/data_structures/bitset.pxi @@ -289,6 +289,20 @@ cdef inline bint bitset_issuperset(bitset_t a, bitset_t b): """ return bitset_issubset(b, a) + +cdef inline bint bitset_are_disjoint(bitset_t a, bitset_t b): + """ + Tests whether ``a`` and ``b`` have an empty intersection. + + We assume ``a.limbs <= b.limbs``. + """ + cdef mp_size_t i + for i from 0 <= i < a.limbs: + if (a.bits[i]&b.bits[i]) != 0: + return False + return True + + ############################################################################# # Bitset Bit Manipulation ############################################################################# diff --git a/src/sage/data_structures/bounded_integer_sequences.pyx b/src/sage/data_structures/bounded_integer_sequences.pyx index 346d64803d2..12d91dc03f1 100644 --- a/src/sage/data_structures/bounded_integer_sequences.pyx +++ b/src/sage/data_structures/bounded_integer_sequences.pyx @@ -112,13 +112,11 @@ include "sage/ext/interrupt.pxi" include "sage/ext/stdsage.pxi" include 'sage/data_structures/bitset.pxi' +from cpython.int cimport PyInt_FromSize_t from cpython.slice cimport PySlice_Check, PySlice_GetIndicesEx from sage.libs.gmp.mpn cimport mpn_rshift, mpn_lshift, mpn_copyi, mpn_ior_n, mpn_zero, mpn_copyd, mpn_cmp from sage.libs.flint.flint cimport FLINT_BIT_COUNT as BIT_COUNT -cdef extern from "Python.h": - cdef PyInt_FromSize_t(size_t ival) - cimport cython ################### diff --git a/src/sage/databases/conway.py b/src/sage/databases/conway.py index 397296e787d..3a0f7aa2457 100644 --- a/src/sage/databases/conway.py +++ b/src/sage/databases/conway.py @@ -20,7 +20,7 @@ #***************************************************************************** import collections, os -from sage.misc.misc import SAGE_SHARE +from sage.env import SAGE_SHARE _CONWAYDATA = os.path.join(SAGE_SHARE, 'conway_polynomials', 'conway_polynomials.sobj') @@ -74,7 +74,7 @@ def __iter__(self): TESTS:: sage: from sage.databases.conway import DictInMapping - sage: iter(DictInMapping({'foo': 'bar'})).next() + sage: next(iter(DictInMapping({'foo': 'bar'}))) 'foo' """ return iter(self._store) @@ -174,9 +174,9 @@ def __iter__(self): sage: c = ConwayPolynomials() sage: itr = iter(c) - sage: itr.next() + sage: next(itr) (65537, 4) - sage: itr.next() + sage: next(itr) (2, 1) """ for a,b in self._store.iteritems(): diff --git a/src/sage/databases/cremona.py b/src/sage/databases/cremona.py index 06e73cbb745..6e908be27e0 100644 --- a/src/sage/databases/cremona.py +++ b/src/sage/databases/cremona.py @@ -53,7 +53,8 @@ import sage.schemes.elliptic_curves.constructor as elliptic from sql_db import SQLDatabase, verify_column from sage.misc.package import is_package_installed -from sage.misc.misc import SAGE_SHARE, walltime +from sage.env import SAGE_SHARE +from sage.misc.all import walltime import re import string @@ -635,16 +636,16 @@ def __iter__(self): TESTS:: sage: it = CremonaDatabase().__iter__() - sage: it.next().label() + sage: next(it).label() '11a1' - sage: it.next().label() + sage: next(it).label() '11a2' - sage: it.next().label() + sage: next(it).label() '11a3' - sage: it.next().label() + sage: next(it).label() '14a1' - sage: skip = [it.next() for _ in range(100)] - sage: it.next().label() + sage: skip = [next(it) for _ in range(100)] + sage: next(it).label() '45a3' """ query = "SELECT curve FROM t_curve,t_class USING(class) ORDER BY conductor" @@ -814,7 +815,7 @@ def coefficients_and_data(self, label): + "deg,gens,cp,om,L,reg,sha FROM t_curve,t_class " \ + "USING(class) WHERE curve=?",(label,)) try: - c = q.next() + c = next(q) except StopIteration: if N < self.largest_conductor(): message = "There is no elliptic curve with label " + label \ @@ -873,7 +874,7 @@ def data_from_coefficients(self, ainvs): + "USING(class) WHERE eqn=?", (ainvs.replace(' ', ''),)) try: - c = q.next() + c = next(q) except StopIteration: raise RuntimeError("There is no elliptic curve with coefficients " + ainvs + " in the database") @@ -1151,7 +1152,7 @@ def largest_conductor(self): #print "Computing largest conductor." q = self.__connection__.cursor().execute('SELECT conductor FROM ' \ + 't_class ORDER BY conductor DESC LIMIT 1') - self.__largest_conductor__ = q.next()[0] + self.__largest_conductor__ = next(q)[0] return self.__largest_conductor__ def smallest_conductor(self): @@ -1223,18 +1224,18 @@ def number_of_curves(self, N=0, i=0): return self.__number_of_curves__ q = self.__connection__.cursor().execute('SELECT COUNT(curve) ' \ + 'FROM t_curve') - self.__number_of_curves__ = q.next()[0] + self.__number_of_curves__ = next(q)[0] return self.__number_of_curves__ if i == 0: q = self.__connection__.cursor().execute('SELECT COUNT(curve) ' \ + 'FROM t_curve,t_class USING(class) WHERE conductor=?', \ (int(N),)) - return q.next()[0] + return next(q)[0] if not isinstance(i, str): i = cremona_letter_code(i) q = self.__connection__.cursor().execute('SELECT COUNT(curve) FROM ' \ + 't_curve WHERE class=?',(str(N)+i,)) - return q.next()[0] + return next(q)[0] def number_of_isogeny_classes(self, N=0): """ @@ -1262,11 +1263,11 @@ def number_of_isogeny_classes(self, N=0): return self.__number_of_isogeny_classes__ q = self.__connection__.cursor().execute('SELECT COUNT(class) ' \ + 'FROM t_class') - self.__number_of_isogeny_classes__ = q.next()[0] + self.__number_of_isogeny_classes__ = next(q)[0] return self.__number_of_isogeny_classes__ q = self.__connection__.cursor().execute('SELECT COUNT(class) FROM ' \ + 't_class WHERE conductor=?',(int(N),)) - return q.next()[0] + return next(q)[0] def random(self): """ @@ -1281,7 +1282,7 @@ def random(self): q = self.__connection__.cursor().execute('SELECT conductor FROM ' \ + 't_class WHERE conductor>=? ORDER BY conductor',(int(N),)) try: - N = q.next()[0] + N = next(q)[0] except StopIteration: N = 11 iso = randint(0, self.number_of_isogeny_classes(N)-1) @@ -1659,7 +1660,7 @@ def CremonaDatabase(name=None,mini=None,set_global=None): Traceback (most recent call last): ... ValueError: Desired database (='should not exist') does not exist - sage: from sage.misc.misc import SAGE_SHARE + sage: from sage.env import SAGE_SHARE sage: os.path.isfile(os.path.join(SAGE_SHARE,'cremona','should_not_exist.db')) False """ diff --git a/src/sage/databases/cunningham_tables.py b/src/sage/databases/cunningham_tables.py index 79bfeb98393..6196b1eacae 100644 --- a/src/sage/databases/cunningham_tables.py +++ b/src/sage/databases/cunningham_tables.py @@ -2,7 +2,7 @@ from sage.misc.cachefunc import cached_function from sage.rings.integer import Integer from sage.structure.sage_object import load -from sage.misc.misc import SAGE_SHARE +from sage.env import SAGE_SHARE @cached_function def cunningham_prime_factors(): diff --git a/src/sage/databases/db_class_polynomials.py b/src/sage/databases/db_class_polynomials.py index 14d9ad2b08a..00ec031f5b6 100644 --- a/src/sage/databases/db_class_polynomials.py +++ b/src/sage/databases/db_class_polynomials.py @@ -17,11 +17,11 @@ import bz2, os -import sage.misc.misc +from sage.env import SAGE_SHARE from sage.rings.integer_ring import IntegerRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -dblocation = os.path.join(sage.misc.misc.SAGE_SHARE,'kohel') +dblocation = os.path.join(SAGE_SHARE, 'kohel') disc_length = 7 level_length = 3 diff --git a/src/sage/databases/db_modular_polynomials.py b/src/sage/databases/db_modular_polynomials.py index 8640e077b9a..9b5fb2e80f3 100644 --- a/src/sage/databases/db_modular_polynomials.py +++ b/src/sage/databases/db_modular_polynomials.py @@ -18,12 +18,12 @@ import bz2, os -import sage.misc.misc +from sage.env import SAGE_SHARE from sage.rings.integer import Integer from sage.rings.integer_ring import IntegerRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -dblocation = os.path.join(sage.misc.misc.SAGE_SHARE,'kohel') +dblocation = os.path.join(SAGE_SHARE, 'kohel') def _dbz_to_integer_list(name): file = os.path.join(dblocation, name) diff --git a/src/sage/databases/jones.py b/src/sage/databases/jones.py index dc14ecef2bb..6f81f642fe9 100644 --- a/src/sage/databases/jones.py +++ b/src/sage/databases/jones.py @@ -70,12 +70,12 @@ from sage.rings.all import NumberField, RationalField, PolynomialRing from sage.misc.misc import powerset -import sage.misc.misc +from sage.env import SAGE_SHARE from sage.structure.sage_object import load, save -JONESDATA = os.path.join(sage.misc.misc.SAGE_SHARE, 'jones') +JONESDATA = os.path.join(SAGE_SHARE, 'jones') class JonesDatabase: def __init__(self): diff --git a/src/sage/databases/odlyzko.py b/src/sage/databases/odlyzko.py index 73d50c6415e..a63eeb57442 100644 --- a/src/sage/databases/odlyzko.py +++ b/src/sage/databases/odlyzko.py @@ -21,7 +21,8 @@ import os import sage.misc.db as db -import sage.misc.misc as misc +from sage.env import SAGE_SHARE +from sage.misc.all import verbose def zeta_zeros(): r""" @@ -52,13 +53,12 @@ def zeta_zeros(): sage: zz[12] # optional - database_odlyzko_zeta 59.347044003... """ - path = os.path.join(misc.SAGE_SHARE,'odlyzko') + path = os.path.join(SAGE_SHARE,'odlyzko') file = os.path.join(path,'zeros1') if os.path.exists(file+".pickle"): - misc.verbose("Loading Odlyzko database from " + file + ".pickle") + verbose("Loading Odlyzko database from " + file + ".pickle") return db.load(file+".pickle") - misc.verbose("Creating Odlyzko Database.") + verbose("Creating Odlyzko Database.") F = [eval(x) for x in open(file).read().split()] db.save(F, file+".pickle") return F - diff --git a/src/sage/databases/oeis.py b/src/sage/databases/oeis.py index 66a556ccb48..3e49d54f381 100644 --- a/src/sage/databases/oeis.py +++ b/src/sage/databases/oeis.py @@ -10,7 +10,9 @@ AUTHORS: - - Thierry Monteil (2012-02-10 -- 2013-06-21): initial version. +- Thierry Monteil (2012-02-10 -- 2013-06-21): initial version. + +- Vincent Delecroix (2014): modifies continued fractions because of trac:`14567` EXAMPLES:: @@ -928,7 +930,7 @@ def natural_object(self): sage: s = oeis._imaginary_sequence('nonn,cofr') sage: s.natural_object().parent() - Field of all continued fractions + QQ as continued fractions sage: s = oeis._imaginary_sequence('nonn') sage: s.natural_object().parent() @@ -1254,13 +1256,13 @@ def __iter__(self): A007540: Wilson primes: primes p such that (p-1)! == -1 (mod p^2). sage: i = w.__iter__() # optional -- internet - sage: i.next() # optional -- internet + sage: next(i) # optional -- internet 5 - sage: i.next() # optional -- internet + sage: next(i) # optional -- internet 13 - sage: i.next() # optional -- internet + sage: next(i) # optional -- internet 563 - sage: i.next() # optional -- internet + sage: next(i) # optional -- internet Traceback (most recent call last): ... LookupError: Future values not provided by OEIS. diff --git a/src/sage/databases/sloane.py b/src/sage/databases/sloane.py index 30d01c648aa..fe17144efad 100644 --- a/src/sage/databases/sloane.py +++ b/src/sage/databases/sloane.py @@ -85,7 +85,7 @@ import bz2, os, re, urllib from sage.misc.all import verbose -from sage.misc.misc import SAGE_SHARE +from sage.env import SAGE_SHARE import sage.rings.integer_ring ZZ = sage.rings.integer_ring.IntegerRing() from sage.misc.superseded import deprecation diff --git a/src/sage/databases/sql_db.py b/src/sage/databases/sql_db.py index 3b1e4eaa809..36da1ac8c41 100644 --- a/src/sage/databases/sql_db.py +++ b/src/sage/databases/sql_db.py @@ -251,7 +251,7 @@ def construct_skeleton(database): skeleton = {} cur = database.__connection__.cursor() exe = cur.execute("SELECT name FROM sqlite_master WHERE TYPE='table'") - from sage.misc.misc import SAGE_SHARE + from sage.env import SAGE_SHARE for table in exe.fetchall(): skeleton[table[0]] = {} exe1 = cur.execute("PRAGMA table_info(%s)"%table[0]) @@ -561,12 +561,12 @@ def __iter__(self): sage: param = (5,) sage: Q = SQLQuery(G,q,param) sage: it = Q.__iter__() - sage: it.next() + sage: next(it) (18, u'D??') - sage: it.next() + sage: next(it) (19, u'D?C') - sage: skip = [it.next() for _ in range(15)] - sage: it.next() + sage: skip = [next(it) for _ in range(15)] + sage: next(it) (35, u'DBk') """ try: diff --git a/src/sage/databases/stein_watkins.py b/src/sage/databases/stein_watkins.py index 20d44f3debe..f3115dd9d39 100644 --- a/src/sage/databases/stein_watkins.py +++ b/src/sage/databases/stein_watkins.py @@ -41,15 +41,15 @@ sage: d Stein-Watkins Database a.0 Iterator -We type ``d.next()`` to get each isogeny class of +We type ``next(d)`` to get each isogeny class of curves from ``d``:: - sage: C = d.next() # optional - database_stein_watkins - sage: C # optional - database_stein_watkins + sage: C = next(d) # optional - database_stein_watkins + sage: C # optional - database_stein_watkins Stein-Watkins isogeny class of conductor 11 - sage: d.next() # optional - database_stein_watkins + sage: next(d) # optional - database_stein_watkins Stein-Watkins isogeny class of conductor 14 - sage: d.next() # optional - database_stein_watkins + sage: next(d) # optional - database_stein_watkins Stein-Watkins isogeny class of conductor 15 An isogeny class has a number of attributes that give data about @@ -75,7 +75,7 @@ sage: C.isogeny_number # optional - database_stein_watkins '25' -If we were to continue typing ``d.next()`` we would +If we were to continue typing ``next(d)`` we would iterate over all curves in the Stein-Watkins database up to conductor `10^5`. We could also type ``for C in d: ...`` @@ -84,24 +84,24 @@ following:: sage: d = SteinWatkinsAllData(1) - sage: C = d.next() # optional - database_stein_watkins - sage: C # optional - database_stein_watkins + sage: C = next(d) # optional - database_stein_watkins + sage: C # optional - database_stein_watkins Stein-Watkins isogeny class of conductor 100002 - sage: C.curves # optional - database_stein_watkins + sage: C.curves # optional - database_stein_watkins [[[1, 1, 0, 112, 0], '(8,1,2,1)', 'X', '2'], [[1, 1, 0, -448, -560], '[4,2,1,2]', 'X', '2']] Next we access the prime-conductor data:: sage: d = SteinWatkinsPrimeData(0) - sage: C = d.next() # optional - database_stein_watkins + sage: C = next(d) # optional - database_stein_watkins sage: C # optional - database_stein_watkins Stein-Watkins isogeny class of conductor 11 -Each call ``d.next()`` gives another elliptic curve of +Each call ``next(d)`` gives another elliptic curve of prime conductor:: - sage: C = d.next() # optional - database_stein_watkins + sage: C = next(d) # optional - database_stein_watkins sage: C # optional - database_stein_watkins Stein-Watkins isogeny class of conductor 17 sage: C.curves # optional - database_stein_watkins @@ -109,7 +109,7 @@ [[1, -1, 1, -6, -4], '[2]', '1', '2x'], [[1, -1, 1, -1, -14], '(4)', '1', '4'], [[1, -1, 1, -91, -310], '[1]', '1', '2']] - sage: C = d.next() # optional - database_stein_watkins + sage: C = next(d) # optional - database_stein_watkins sage: C # optional - database_stein_watkins Stein-Watkins isogeny class of conductor 19 @@ -140,7 +140,7 @@ import bz2, os -from sage.misc.misc import SAGE_SHARE +from sage.env import SAGE_SHARE class SteinWatkinsIsogenyClass: def __init__(self, conductor): @@ -240,7 +240,7 @@ def __iter__(self): yield C def next(self): - return self._iter.next() + return next(self._iter) def __getitem__(self, N): """ @@ -282,12 +282,12 @@ def iter_levels(self): sage: d = SteinWatkinsAllData(1) sage: E = d.iter_levels() - sage: E.next() # optional - database_stein_watkins + sage: next(E) # optional - database_stein_watkins [Stein-Watkins isogeny class of conductor 100002] - sage: E.next() # optional - database_stein_watkins + sage: next(E) # optional - database_stein_watkins [Stein-Watkins isogeny class of conductor 100005, Stein-Watkins isogeny class of conductor 100005] - sage: E.next() # optional - database_stein_watkins + sage: next(E) # optional - database_stein_watkins [Stein-Watkins isogeny class of conductor 100007] """ iter = self.__iter__() @@ -295,7 +295,7 @@ def iter_levels(self): N = 0 while True: try: - E = iter.next() + E = next(iter) except StopIteration: if C != []: yield C @@ -352,7 +352,7 @@ def ecdb_num_curves(max_level=200000): v = [int(0) for _ in xrange(max_level+1)] while True: try: - C = d.next() + C = next(d) except StopIteration: i += 1 d = SteinWatkinsAllData(i) diff --git a/src/sage/databases/symbolic_data.py b/src/sage/databases/symbolic_data.py index 99c39fddc9a..b0b4b4d0eac 100644 --- a/src/sage/databases/symbolic_data.py +++ b/src/sage/databases/symbolic_data.py @@ -75,7 +75,7 @@ def __init__(self): sage: sd = SymbolicData(); sd # optional - database_symbolic_data SymbolicData with 372 ideals """ - from sage.misc.misc import SAGE_SHARE + from sage.env import SAGE_SHARE path = os.path.join(SAGE_SHARE, 'symbolic_data') self.__intpath = path + "/Data/XMLResources/INTPS/" self.__genpath = path + "/Data/XMLResources/GenPS/" diff --git a/src/sage/dev/cmd_line_interface.py b/src/sage/dev/cmd_line_interface.py index a5b772c41a2..c69526a9a86 100644 --- a/src/sage/dev/cmd_line_interface.py +++ b/src/sage/dev/cmd_line_interface.py @@ -132,13 +132,13 @@ def _get_input(self, prompt, options=None, default=None, input_func=raw_input): itr = (opt for opt in options if opt.lower().startswith(s.lower())) try: - ret = itr.next() + ret = next(itr) except StopIteration: self.show("Please specify an allowable option.") continue try: - ret = itr.next() + ret = next(itr) self.show("Please disambiguate between options.") except StopIteration: return ret diff --git a/src/sage/dev/misc.py b/src/sage/dev/misc.py index 1da590374a7..58e918310cb 100644 --- a/src/sage/dev/misc.py +++ b/src/sage/dev/misc.py @@ -59,7 +59,7 @@ def tmp_filename(): True """ try: - from sage.misc.misc import tmp_filename + from sage.misc.temporary_file import tmp_filename return tmp_filename() except ImportError: from tempfile import NamedTemporaryFile @@ -83,7 +83,7 @@ def tmp_dir(): True """ try: - from sage.misc.misc import tmp_dir + from sage.misc.all import tmp_dir return tmp_dir() except ImportError: from tempfile import mkdtemp diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index ec7dde01b7d..5e8d37f9501 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -1564,7 +1564,7 @@ def sel_exit(): # Start new workers if possible while source_iter is not None and len(workers) < opt.nthreads: try: - source = source_iter.next() + source = next(source_iter) except StopIteration: source_iter = None else: diff --git a/src/sage/ext/fast_eval.pyx b/src/sage/ext/fast_eval.pyx index 545548a640f..f2c47740a54 100644 --- a/src/sage/ext/fast_eval.pyx +++ b/src/sage/ext/fast_eval.pyx @@ -19,27 +19,29 @@ what it can in C, and will call out to Python if necessary. Essential to the understanding of this class is the distinction between symbolic expressions and callable symbolic expressions (where the latter binds argument names to argument positions). The -\code{*vars} parameter passed around encapsulates this information. +``*vars`` parameter passed around encapsulates this information. -See the function \code{fast_float(f, *vars)} to create a fast-callable +See the function ``fast_float(f, *vars)`` to create a fast-callable version of f. -NOTE: Sage temporarily has two implementations of this functionality; -one in this file, which will probably be deprecated soon, and one in -fast_callable.pyx. The following instructions are for the old -implementation; you probably want to be looking at fast_callable.pyx -instead. - -To provide this interface for a class, implement -\code{_fast_float_(self, *vars)}. The basic building blocks are -provided by the functions \code{fast_float_constant} (returns a -constant function), \code{fast_float_arg} (selects the $n$-th value -when called with $\ge n$ arguments), and \code{fast_float_func} which +.. NOTE:: + + Sage temporarily has two implementations of this functionality ; + one in this file, which will probably be deprecated soon, and one in + fast_callable.pyx. The following instructions are for the old + implementation; you probably want to be looking at fast_callable.pyx + instead. + +To provide this interface for a class, implement ``fast_float_(self, *vars)``. The basic building blocks are +provided by the functions ``fast_float_constant`` (returns a +constant function), ``fast_float_arg`` (selects the ``n``-th value +when called with ``\ge_n`` arguments), and ``fast_float_func`` which wraps a callable Python function. These may be combined with the standard Python arithmetic operators, and support many of the basic -math functions such sqrt, exp, and trig functions. +math functions such ``sqrt``, ``exp``, and trig functions. + +EXAMPLES:: -EXAMPLES: sage: from sage.ext.fast_eval import fast_float sage: f = fast_float(sqrt(x^7+1), 'x', old=True) sage: f(1) @@ -47,28 +49,32 @@ EXAMPLES: sage: f.op_list() ['load 0', 'push 7.0', 'pow', 'push 1.0', 'add', 'call sqrt(1)'] - To interpret that last line, we load argument 0 ('x' in this case) onto - the stack, push the constant 2.0 onto the stack, call the pow function - (which takes 2 arguments from the stack), push the constant 1.0, add the - top two arguments of the stack, and then call sqrt. +To interpret that last line, we load argument 0 (``x`` in this case) onto +the stack, push the constant 2.0 onto the stack, call the pow function +(which takes 2 arguments from the stack), push the constant 1.0, add the +top two arguments of the stack, and then call sqrt. + +Here we take ``sin`` of the first argument and add it to ``f``:: -Here we take sin of the first argument and add it to f: sage: from sage.ext.fast_eval import fast_float_arg sage: g = fast_float_arg(0).sin() sage: (f+g).op_list() ['load 0', 'push 7.0', 'pow', 'push 1.0', 'add', 'call sqrt(1)', 'load 0', 'call sin(1)', 'add'] TESTS: + This used to segfault because of an assumption that assigning None to a -variable would raise a TypeError: +variable would raise a TypeError:: + sage: from sage.ext.fast_eval import fast_float_arg, fast_float sage: fast_float_arg(0)+None Traceback (most recent call last): ... TypeError -AUTHOR: - -- Robert Bradshaw (2008-10): Initial version +AUTHORS: + +- Robert Bradshaw (2008-10): Initial version """ @@ -275,7 +281,8 @@ cdef op_to_tuple(fast_double_op op): try: param = param_count, cfunc_names[op.params.func] except KeyError: - raise ValueError, "Unknown C function: 0x%x" % op.params.func + raise ValueError("Unknown C function: 0x%x" + % op.params.func) elif op.type == PY_FUNC: param = (op.params.func) else: @@ -286,7 +293,7 @@ cdef op_to_tuple(fast_double_op op): return s, param def _unpickle_FastDoubleFunc(nargs, max_height, op_list): - cdef FastDoubleFunc self = PY_NEW(FastDoubleFunc) + cdef FastDoubleFunc self = FastDoubleFunc.__new__(FastDoubleFunc) self.nops = len(op_list) self.nargs = nargs self.max_height = max_height @@ -382,7 +389,7 @@ cdef inline int process_op(fast_double_op op, double* stack, double* argv, int t elif op.type == POW: if stack[top-1] < 0 and stack[top] != floor(stack[top]): - raise ValueError, "negative number to a fractional power not real" + raise ValueError("negative number to a fractional power not real") stack[top-1] = pow(stack[top-1], stack[top]) return top-1 @@ -433,7 +440,7 @@ cdef inline int process_op(fast_double_op op, double* stack, double* argv, int t Py_DECREF(py_args) return top - raise RuntimeError, "Bad op code %s" % op.type + raise RuntimeError("Bad op code %s" % op.type) cdef class FastDoubleFunc: @@ -442,7 +449,8 @@ cdef class FastDoubleFunc: the real numbers (e.g. for plotting). It represents an expression as a stack-based series of operations. - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import FastDoubleFunc sage: f = FastDoubleFunc('const', 1.5) # the constant function sage: f() @@ -461,7 +469,8 @@ cdef class FastDoubleFunc: sage: list(h) ['push 1.5', 'load 0', 'add', 'call sin(1)'] - We can wrap Python functions too: + We can wrap Python functions too:: + sage: h = FastDoubleFunc('callable', lambda x,y: x*x*x - y, g, f) sage: h(10) 998.5 @@ -470,7 +479,8 @@ cdef class FastDoubleFunc: sage: list(h) ['load 0', 'push 1.5', 'py_call at 0x...>(2)'] - Here's a more complicated expression: + Here's a more complicated expression:: + sage: from sage.ext.fast_eval import fast_float_constant, fast_float_arg sage: a = fast_float_constant(1.5) sage: b = fast_float_constant(3.14) @@ -487,9 +497,9 @@ cdef class FastDoubleFunc: sage: list(f) ['push 1.5', 'load 0', 'dup', 'mul', 'mul', 'push 3.14', 'load 0', 'mul', 'add', 'push 7.0', 'add', 'load 1', 'load 1', 'call sin(1)', 'dup', 'mul', 'push 1.5', 'add', 'call sqrt(1)', 'div', 'sub'] + AUTHORS: - AUTHOR: - -- Robert Bradshaw + - Robert Bradshaw """ def __init__(self, type, param, *args): @@ -539,11 +549,10 @@ cdef class FastDoubleFunc: self.ops[self.nops-1].params.func = py_func else: - raise ValueError, "Unknown operation: %s" % type + raise ValueError("Unknown operation: %s" % type) self.allocate_stack() - cdef int allocate_stack(FastDoubleFunc self) except -1: self.argv = sage_malloc(sizeof(double) * self.nargs) if self.argv == NULL: @@ -562,7 +571,8 @@ cdef class FastDoubleFunc: def __reduce__(self): """ - TESTS: + TESTS:: + sage: from sage.ext.fast_eval import fast_float_arg, fast_float_func sage: f = fast_float_arg(0).sin() * 10 + fast_float_func(hash, fast_float_arg(1)) sage: loads(dumps(f)) == f @@ -576,7 +586,8 @@ cdef class FastDoubleFunc: Two functions are considered equal if they represent the same exact sequence of operations. - TESTS: + TESTS:: + sage: from sage.ext.fast_eval import fast_float_arg sage: fast_float_arg(0) == fast_float_arg(0) True @@ -606,7 +617,8 @@ cdef class FastDoubleFunc: def __call__(FastDoubleFunc self, *args): """ - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(2) sage: f(0,1,2,3) @@ -621,7 +633,7 @@ cdef class FastDoubleFunc: TypeError: a float is required """ if len(args) < self.nargs: - raise TypeError, "Wrong number of arguments (need at least %s, got %s)" % (self.nargs, len(args)) + raise TypeError("Wrong number of arguments (need at least %s, got %s)" % (self.nargs, len(args))) cdef int i = 0 for i from 0 <= i < self.nargs: self.argv[i] = args[i] @@ -639,9 +651,10 @@ cdef class FastDoubleFunc: def _fast_float_(self, *vars): r""" - Returns \code{self} if there are enough arguments, otherwise raises a TypeError. + Returns ``self`` if there are enough arguments, otherwise raises a ``TypeError``. + + EXAMPLES:: - EXAMPLES: sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(1) sage: f._fast_float_('x','y') is f @@ -652,7 +665,7 @@ cdef class FastDoubleFunc: TypeError: Needs at least 2 arguments (1 provided) """ if self.nargs > len(vars): - raise TypeError, "Needs at least %s arguments (%s provided)" % (self.nargs, len(vars)) + raise TypeError("Needs at least %s arguments (%s provided)" % (self.nargs, len(vars))) return self def op_list(self): @@ -660,9 +673,11 @@ cdef class FastDoubleFunc: Returns a list of string representations of the operations that make up this expression. - Python and C function calls may be only available by function pointer addresses. + Python and C function calls may be only available by function + pointer addresses. + + EXAMPLES:: - EXAMPLES: sage: from sage.ext.fast_eval import fast_float_constant, fast_float_arg sage: a = fast_float_constant(17) sage: x = fast_float_arg(0) @@ -680,9 +695,10 @@ cdef class FastDoubleFunc: def __iter__(self): """ - Returns the list of operations of self. + Returns the list of operations of ``self``. + + EXAMPLES:: - EXAMPLES: sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0)*2 + 3 sage: list(f) @@ -692,10 +708,11 @@ cdef class FastDoubleFunc: cpdef bint is_pure_c(self): """ - Returns True if this function can be evaluated without + Returns ``True`` if this function can be evaluated without any python calls (at any level). - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_constant, fast_float_arg, fast_float_func sage: fast_float_constant(2).is_pure_c() True @@ -714,7 +731,8 @@ cdef class FastDoubleFunc: """ Returns a list of all python calls used by function. - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_func, fast_float_arg sage: x = fast_float_arg(0) sage: f = fast_float_func(hash, sqrt(x)) @@ -736,7 +754,8 @@ cdef class FastDoubleFunc: def __add__(left, right): """ - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0) + fast_float_arg(1) sage: f(3,4) @@ -746,7 +765,8 @@ cdef class FastDoubleFunc: def __sub__(left, right): """ - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0) - fast_float_arg(2) sage: f(3,4,5) @@ -756,7 +776,8 @@ cdef class FastDoubleFunc: def __mul__(left, right): """ - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0) * 2 sage: f(17) @@ -766,7 +787,8 @@ cdef class FastDoubleFunc: def __div__(left, right): """ - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0) / 7 sage: f(14) @@ -776,7 +798,8 @@ cdef class FastDoubleFunc: def __pow__(FastDoubleFunc left, right, dummy): """ - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import FastDoubleFunc sage: f = FastDoubleFunc('arg', 0)^2 sage: f(2) @@ -791,7 +814,8 @@ cdef class FastDoubleFunc: sage: f(5,3) 125.0 - TESTS: + TESTS:: + sage: var('a,b') (a, b) sage: ff = (a^b)._fast_float_(a,b) @@ -824,7 +848,8 @@ cdef class FastDoubleFunc: def __neg__(FastDoubleFunc self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = -fast_float_arg(0) sage: f(3.5) @@ -834,7 +859,8 @@ cdef class FastDoubleFunc: def __abs__(FastDoubleFunc self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = abs(fast_float_arg(0)) sage: f(-3) @@ -844,7 +870,8 @@ cdef class FastDoubleFunc: def __float__(self): """ - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_constant, fast_float_arg sage: ff = fast_float_constant(17) sage: float(ff) @@ -861,11 +888,12 @@ cdef class FastDoubleFunc: if self.nargs == 0: return self._call_c(NULL) else: - raise TypeError, "Not a constant." + raise TypeError("Not a constant.") def abs(FastDoubleFunc self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).abs() sage: f(3) @@ -875,7 +903,8 @@ cdef class FastDoubleFunc: def __invert__(FastDoubleFunc self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = ~fast_float_arg(0) sage: f(4) @@ -885,7 +914,8 @@ cdef class FastDoubleFunc: def sqrt(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).sqrt() sage: f(4) @@ -900,7 +930,9 @@ cdef class FastDoubleFunc: def _richcmp_(left, right, op): """ Compare left and right. - EXAMPLES: + + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: import operator sage: f = fast_float_arg(0)._richcmp_(2, operator.lt) @@ -943,7 +975,8 @@ cdef class FastDoubleFunc: def log(self, base=None): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).log() sage: f(2) @@ -970,7 +1003,8 @@ cdef class FastDoubleFunc: def exp(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).exp() sage: f(1) @@ -986,7 +1020,8 @@ cdef class FastDoubleFunc: def ceil(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).ceil() sage: f(1.5) @@ -998,7 +1033,8 @@ cdef class FastDoubleFunc: def floor(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).floor() sage: f(11.5) @@ -1014,7 +1050,8 @@ cdef class FastDoubleFunc: def sin(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).sin() sage: f(pi/2) @@ -1024,7 +1061,8 @@ cdef class FastDoubleFunc: def cos(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).cos() sage: f(0) @@ -1034,7 +1072,8 @@ cdef class FastDoubleFunc: def tan(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).tan() sage: f(pi/3) @@ -1044,7 +1083,8 @@ cdef class FastDoubleFunc: def csc(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).csc() sage: f(pi/2) @@ -1054,7 +1094,8 @@ cdef class FastDoubleFunc: def sec(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).sec() sage: f(pi) @@ -1064,7 +1105,8 @@ cdef class FastDoubleFunc: def cot(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).cot() sage: f(pi/4) @@ -1074,7 +1116,8 @@ cdef class FastDoubleFunc: def arcsin(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).arcsin() sage: f(0.5) @@ -1084,7 +1127,8 @@ cdef class FastDoubleFunc: def arccos(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).arccos() sage: f(sqrt(3)/2) @@ -1094,7 +1138,8 @@ cdef class FastDoubleFunc: def arctan(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).arctan() sage: f(1) @@ -1108,7 +1153,8 @@ cdef class FastDoubleFunc: def sinh(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).sinh() sage: f(log(2)) @@ -1118,7 +1164,8 @@ cdef class FastDoubleFunc: def cosh(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).cosh() sage: f(log(2)) @@ -1128,7 +1175,8 @@ cdef class FastDoubleFunc: def tanh(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).tanh() sage: f(0) @@ -1138,7 +1186,8 @@ cdef class FastDoubleFunc: def arcsinh(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).arcsinh() sage: f(sinh(5)) @@ -1148,7 +1197,8 @@ cdef class FastDoubleFunc: def arccosh(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).arccosh() sage: f(cosh(5)) @@ -1158,7 +1208,8 @@ cdef class FastDoubleFunc: def arctanh(self): """ - EXAMPLE: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0).arctanh() sage: abs(f(tanh(0.5)) - 0.5) < 0.0000001 @@ -1177,7 +1228,7 @@ cdef class FastDoubleFunc: ################################################################### cdef FastDoubleFunc unop(FastDoubleFunc self, char type): - cdef FastDoubleFunc feval = PY_NEW(FastDoubleFunc) + cdef FastDoubleFunc feval = FastDoubleFunc.__new__(FastDoubleFunc) feval.nargs = self.nargs feval.nops = self.nops + 1 feval.max_height = self.max_height @@ -1193,9 +1244,10 @@ cdef class FastDoubleFunc: cdef FastDoubleFunc binop(_left, _right, char type): r""" Returns a function that calculates left and right on the stack, leaving - their results on the top, and then calls operation \code{type}. + their results on the top, and then calls operation ``type``. + + EXAMPLES:: - EXAMPLES: sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(1) sage: g = fast_float_arg(2) * 11 @@ -1206,7 +1258,8 @@ cdef FastDoubleFunc binop(_left, _right, char type): sage: (f+g).op_list() ['load 1', 'load 2', 'push 11.0', 'mul', 'add'] - Correctly calculates the maximum stack heights and number of arguments: + Correctly calculates the maximum stack heights and number of arguments:: + sage: f.max_height 1 sage: g.max_height @@ -1237,7 +1290,7 @@ cdef FastDoubleFunc binop(_left, _right, char type): if left is None or right is None: raise TypeError - cdef FastDoubleFunc feval = PY_NEW(FastDoubleFunc) + cdef FastDoubleFunc feval = FastDoubleFunc.__new__(FastDoubleFunc) feval.nargs = max(left.nargs, right.nargs) feval.nops = left.nops + right.nops + 1 feval.max_height = max(left.max_height, right.max_height+1) @@ -1259,13 +1312,15 @@ def fast_float_constant(x): """ Return a fast-to-evaluate constant function. - EXAMPLES: + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_constant sage: f = fast_float_constant(-2.75) sage: f() -2.75 - This is all that goes on under the hood: + This is all that goes on under the hood:: + sage: fast_float_constant(pi).op_list() ['push 3.14159265359'] """ @@ -1276,9 +1331,11 @@ def fast_float_arg(n): Return a fast-to-evaluate argument selector. INPUT: - n -- the (zero-indexed) argument to select - EXAMPLES: + - ``n`` -- the (zero-indexed) argument to select + + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_arg sage: f = fast_float_arg(0) sage: f(1,2) @@ -1287,7 +1344,8 @@ def fast_float_arg(n): sage: f(1,2) 2.0 - This is all that goes on under the hood: + This is all that goes on under the hood:: + sage: fast_float_arg(10).op_list() ['load 10'] """ @@ -1298,10 +1356,12 @@ def fast_float_func(f, *args): Returns a wrapper around a python function. INPUT: - f -- a callable python object - args -- a list of FastDoubleFunc inputs - EXAMPLES: + - ``f`` -- a callable python object + - ``args`` -- a list of FastDoubleFunc inputs + + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float_func, fast_float_arg sage: f = fast_float_arg(0) sage: g = fast_float_arg(1) @@ -1309,7 +1369,8 @@ def fast_float_func(f, *args): sage: h(5, 10) -5.0 - This is all that goes on under the hood: + This is all that goes on under the hood:: + sage: h.op_list() ['load 0', 'load 1', 'py_call at 0x...>(2)'] """ @@ -1328,13 +1389,15 @@ def fast_float(f, *vars, old=None, expect_one_var=False): On failure, returns the input unchanged. INPUT: - f -- an expression - vars -- the names of the arguments - old -- use the original algorithm for fast_float - expect_one_var -- don't give deprecation warning if vars is - omitted, as long as expression has only one var - EXAMPLES: + - ``f`` -- an expression + - ``vars`` -- the names of the arguments + - ``old`` -- use the original algorithm for fast_float + - ``expect_one_var`` -- don't give deprecation warning if ``vars`` is + omitted, as long as expression has only one var + + EXAMPLES:: + sage: from sage.ext.fast_eval import fast_float sage: x,y = var('x,y') sage: f = fast_float(sqrt(x^2+y^2), 'x', 'y') @@ -1342,7 +1405,8 @@ def fast_float(f, *vars, old=None, expect_one_var=False): 5.0 Specifying the argument names is essential, as fast_float objects - only distinguish between arguments by order. + only distinguish between arguments by order. :: + sage: f = fast_float(x-y, 'x','y') sage: f(1,2) -1.0 @@ -1385,10 +1449,10 @@ def fast_float(f, *vars, old=None, expect_one_var=False): pass if f is None: - raise TypeError, "no way to make fast_float from None" + raise TypeError("no way to make fast_float from None") return f + def is_fast_float(x): return PY_TYPE_CHECK(x, FastDoubleFunc) or PY_TYPE_CHECK(x, Wrapper) - diff --git a/src/sage/ext/gen_interpreters.py b/src/sage/ext/gen_interpreters.py index 660c0f2f4d4..b98126ca205 100644 --- a/src/sage/ext/gen_interpreters.py +++ b/src/sage/ext/gen_interpreters.py @@ -2549,7 +2549,7 @@ def __init__(self): return z._complex.dat[0] + _Complex_I * z._complex.dat[1] cdef inline ComplexDoubleElement dz_to_CDE(double_complex dz): - cdef ComplexDoubleElement z = PY_NEW(ComplexDoubleElement) + cdef ComplexDoubleElement z = ComplexDoubleElement.__new__(ComplexDoubleElement) z._complex.dat[0] = creal(dz) z._complex.dat[1] = cimag(dz) return z diff --git a/src/sage/ext/multi_modular.pxd b/src/sage/ext/multi_modular.pxd index 67b400a577b..d4d3da1a451 100644 --- a/src/sage/ext/multi_modular.pxd +++ b/src/sage/ext/multi_modular.pxd @@ -1,3 +1,6 @@ +# distutils: libraries = gmp +# distutils: extra_compile_args = -std=c99 + include "sage/ext/cdefs.pxi" from sage.ext.mod_int cimport * diff --git a/src/sage/finance/time_series.pyx b/src/sage/finance/time_series.pyx index 5f3291596c6..9716a7b3560 100644 --- a/src/sage/finance/time_series.pyx +++ b/src/sage/finance/time_series.pyx @@ -2556,7 +2556,7 @@ cdef new_time_series(Py_ssize_t length): """ if length < 0: raise ValueError, "length must be nonnegative" - cdef TimeSeries t = PY_NEW(TimeSeries) + cdef TimeSeries t = TimeSeries.__new__(TimeSeries) t._length = length t._values = sage_malloc(sizeof(double)*length) return t diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py index 8df019aaa68..e0472302827 100644 --- a/src/sage/functions/bessel.py +++ b/src/sage/functions/bessel.py @@ -186,8 +186,7 @@ from sage.libs.mpmath import utils as mpmath_utils from sage.misc.latex import latex from sage.rings.all import RR, Integer -from sage.structure.coerce import parent -from sage.structure.element import get_coercion_model +from sage.structure.element import parent, get_coercion_model from sage.symbolic.constants import pi from sage.symbolic.function import BuiltinFunction from sage.symbolic.expression import Expression diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py index 334d706c86b..d3784bc0002 100644 --- a/src/sage/functions/exp_integral.py +++ b/src/sage/functions/exp_integral.py @@ -53,7 +53,7 @@ from sage.symbolic.function import BuiltinFunction from sage.symbolic.expression import Expression -from sage.structure.coerce import parent +from sage.structure.all import parent from sage.libs.mpmath import utils as mpmath_utils mpmath_utils_call = mpmath_utils.call # eliminate some overhead in _evalf_ diff --git a/src/sage/functions/hyperbolic.py b/src/sage/functions/hyperbolic.py index addbed4ad91..80d2f638eb9 100644 --- a/src/sage/functions/hyperbolic.py +++ b/src/sage/functions/hyperbolic.py @@ -2,8 +2,14 @@ Hyperbolic Functions """ from sage.symbolic.function import GinacFunction, BuiltinFunction +from sage.rings.infinity import Infinity +from sage.symbolic.expression import Expression +from sage.symbolic.constants import pi, I +from sage.rings.integer_ring import ZZ + import math + class HyperbolicFunction(BuiltinFunction): r""" Abstract base class for the functions defined in this file. @@ -32,8 +38,8 @@ def __init__(self, name, latex_name=None, conversions=None, sage: from sage.functions.hyperbolic import HyperbolicFunction sage: class Barh(HyperbolicFunction): - ... def __init__(self): - ... HyperbolicFunction.__init__(self, 'barh') + ....: def __init__(self): + ....: HyperbolicFunction.__init__(self, 'barh') sage: barh = Barh() sage: barh(x) barh(x) @@ -48,8 +54,8 @@ def _evalf_(self, x, parent=None, algorithm=None): sage: from sage.functions.hyperbolic import HyperbolicFunction sage: class Fooh(HyperbolicFunction): - ... def __init__(self): - ... HyperbolicFunction.__init__(self, 'fooh',evalf_float=lambda x: 2*x) + ....: def __init__(self): + ....: HyperbolicFunction.__init__(self, 'fooh',evalf_float=lambda x: 2*x) sage: fooh = Fooh() sage: fooh(float(5)) 10.0 @@ -66,6 +72,7 @@ def _evalf_(self, x, parent=None, algorithm=None): return self._evalf_float(x) return getattr(x, self.name())() + class Function_sinh(GinacFunction): def __init__(self): r""" @@ -101,6 +108,7 @@ def __init__(self): sinh = Function_sinh() + class Function_cosh(GinacFunction): def __init__(self): r""" @@ -186,6 +194,7 @@ def __init__(self): tanh = Function_tanh() + class Function_coth(HyperbolicFunction): def __init__(self): r""" @@ -208,6 +217,33 @@ def __init__(self): HyperbolicFunction.__init__(self, "coth", latex_name=r"\coth", evalf_float=lambda x: 1/math.tanh(x)) + def _eval_(self, x): + """ + EXAMPLES:: + + sage: coth(0) + +Infinity + sage: coth(pi*I) + +Infinity + sage: coth(pi*I/2) + 0 + sage: coth(7*pi*I/2) + 0 + sage: coth(8*pi*I/2) + +Infinity + sage: coth(7.*pi*I/2) + coth(3.50000000000000*I*pi) + """ + if x.is_zero(): + return Infinity + if isinstance(x, Expression): + y = 2 * x / pi / I + if y.is_integer(): + if ZZ(y) % 2 == 1: + return 0 + else: + return Infinity + def _eval_numpy_(self, x): """ EXAMPLES:: @@ -233,6 +269,7 @@ def _derivative_(self, *args, **kwds): coth = Function_coth() + class Function_sech(HyperbolicFunction): def __init__(self): r""" @@ -255,6 +292,33 @@ def __init__(self): HyperbolicFunction.__init__(self, "sech", latex_name=r"{\rm sech}", evalf_float=lambda x: 1/math.cosh(x)) + def _eval_(self, x): + """ + EXAMPLES:: + + sage: sech(0) + 1 + sage: sech(pi*I) + -1 + sage: sech(pi*I/2) + +Infinity + sage: sech(7*pi*I/2) + +Infinity + sage: sech(8*pi*I/2) + 1 + sage: sech(8.*pi*I/2) + sech(4.00000000000000*I*pi) + """ + if x.is_zero(): + return 1 + if isinstance(x, Expression): + y = 2 * x / pi / I + if y.is_integer(): + if ZZ(y) % 2 == 1: + return Infinity + else: + return ZZ(-1) ** ZZ(y / 2) + def _eval_numpy_(self, x): """ EXAMPLES:: @@ -303,6 +367,31 @@ def __init__(self): HyperbolicFunction.__init__(self, "csch", latex_name=r"{\rm csch}", evalf_float=lambda x: 1/math.sinh(x)) + def _eval_(self, x): + """ + EXAMPLES:: + + sage: csch(0) + +Infinity + sage: csch(pi*I) + +Infinity + sage: csch(pi*I/2) + -I + sage: csch(7*pi*I/2) + I + sage: csch(7.*pi*I/2) + csch(3.50000000000000*I*pi) + """ + if x.is_zero(): + return Infinity + if isinstance(x, Expression): + y = 2 * x / pi / I + if y.is_integer(): + if ZZ(y) % 2 == 1: + return ZZ(-1) ** ZZ((y + 1) / 2) * I + else: + return Infinity + def _eval_numpy_(self, x): """ EXAMPLES:: @@ -333,6 +422,7 @@ def _derivative_(self, *args, **kwds): # Inverse hyperbolic functions # ################################ + class Function_arcsinh(GinacFunction): def __init__(self): r""" @@ -390,6 +480,7 @@ def __init__(self): arcsinh = asinh = Function_arcsinh() + class Function_arccosh(GinacFunction): def __init__(self): r""" @@ -469,6 +560,7 @@ def __init__(self): arccosh = acosh = Function_arccosh() + class Function_arctanh(GinacFunction): def __init__(self): r""" @@ -524,6 +616,7 @@ def __init__(self): arctanh = atanh = Function_arctanh() + class Function_arccoth(HyperbolicFunction): def __init__(self): r""" @@ -584,6 +677,7 @@ def _derivative_(self, *args, **kwds): arccoth = acoth = Function_arccoth() + class Function_arcsech(HyperbolicFunction): def __init__(self): r""" @@ -634,6 +728,7 @@ def _derivative_(self, *args, **kwds): arcsech = asech = Function_arcsech() + class Function_arccsch(HyperbolicFunction): def __init__(self): r""" diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index 58ccb61263c..00c911628f4 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -10,7 +10,7 @@ from sage.symbolic.constants import e as const_e from sage.libs.mpmath import utils as mpmath_utils -from sage.structure.coerce import parent as s_parent +from sage.structure.all import parent as s_parent from sage.symbolic.expression import Expression from sage.rings.real_double import RDF from sage.rings.complex_double import CDF diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index ab86ee405f2..2939b99d3d1 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -327,7 +327,7 @@ from sage.symbolic.function import BuiltinFunction from sage.symbolic.expression import is_Expression from sage.functions.other import factorial, binomial -from sage.structure.coerce import parent +from sage.structure.all import parent _done = False def _init(): diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index d750d3dd99c..e7b53c89039 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -15,7 +15,7 @@ coercion_model = sage.structure.element.get_coercion_model() # avoid name conflicts with `parent` as a function parameter -from sage.structure.coerce import parent as s_parent +from sage.structure.all import parent as s_parent from sage.symbolic.constants import pi from sage.functions.log import exp @@ -1515,7 +1515,7 @@ def _binomial_sym(self, n, k): if k == 1: return n - from sage.misc.misc import prod + from sage.misc.all import prod return prod([n-i for i in xrange(k)])/factorial(k) def _eval_(self, n, k): diff --git a/src/sage/functions/prime_pi.pyx b/src/sage/functions/prime_pi.pyx index 77d31694e4f..3c7efc264af 100644 --- a/src/sage/functions/prime_pi.pyx +++ b/src/sage/functions/prime_pi.pyx @@ -146,7 +146,8 @@ cdef class PrimePi(BuiltinFunction): super(PrimePi, self).__init__('prime_pi', latex_name=r"\pi", conversions={'mathematica':'PrimePi', 'pari':'primepi'}) - cdef uint32_t *__primes, __numPrimes, __maxSieve, __primeBound + cdef uint32_t *__primes + cdef uint32_t __numPrimes, __maxSieve, __primeBound cdef int_fast8_t *__tabS cdef uint_fast16_t *__smallPi cdef uint8_t *__pariPrimePtr @@ -322,7 +323,8 @@ cdef class PrimePi(BuiltinFunction): """ Populates ``self.__primes`` with all primes < b """ - cdef uint32_t *prime, newNumPrimes, i + cdef uint32_t *prime + cdef uint32_t newNumPrimes, i pari.init_primes(b+1u) self.__pariPrimePtr = diffptr newNumPrimes = self._pi(b, 0ull) @@ -414,7 +416,8 @@ cdef class PrimePi(BuiltinFunction): # Laigle-Chapuy if i == 5u: return ((x/77u)<<4u) + self.__tabS[x%2310u] cdef uint32_t s = ((x/77u)<<4u) + self.__tabS[x%2310u] - cdef uint32_t y=x/13u, j=5u, *prime=self.__primes+5 + cdef uint32_t y = x/13u, j = 5u + cdef uint32_t *prime = self.__primes+5 while y > self.__maxSieve: s -= self._phi32(y, j) j += 1u diff --git a/src/sage/games/quantumino.py b/src/sage/games/quantumino.py index c87a9367de5..e838733754d 100644 --- a/src/sage/games/quantumino.py +++ b/src/sage/games/quantumino.py @@ -59,7 +59,7 @@ To solve the puzzle where the pentamino numbered 12 is put aside:: sage: from sage.games.quantumino import QuantuminoSolver - sage: s = QuantuminoSolver(12).solve().next() # long time (10 s) + sage: s = next(QuantuminoSolver(12).solve()) # long time (10 s) sage: s # long time (<1s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 1, 1)], Color: blue @@ -72,7 +72,7 @@ To solve the puzzle where the pentamino numbered 7 is put aside:: - sage: s = QuantuminoSolver(7).solve().next() # long time (10 s) + sage: s = next(QuantuminoSolver(7).solve()) # long time (10 s) sage: s # long time (<1s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 2, 1), (1, 0, 0)], Color: orange @@ -105,29 +105,29 @@ because it needs to create the complete data to describe the problem:: sage: it = QuantuminoSolver(7).solve() - sage: it.next() # not tested (10s) + sage: next(it) # not tested (10s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 2, 1), (1, 0, 0)], Color: orange - sage: it.next() # not tested (0.001s) + sage: next(it) # not tested (0.001s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 2, 1), (1, 0, 0)], Color: orange - sage: it.next() # not tested (0.001s) + sage: next(it) # not tested (0.001s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 2, 1), (1, 0, 0)], Color: orange To get the solution inside other boxes:: - sage: s = QuantuminoSolver(7, box=(4,4,5)).solve().next() # not tested (2s) + sage: s = next(QuantuminoSolver(7, box=(4,4,5)).solve()) # not tested (2s) sage: s.show3d() # not tested (<1s) :: - sage: s = QuantuminoSolver(7, box=(2,2,20)).solve().next() # not tested (1s) + sage: s = next(QuantuminoSolver(7, box=(2,2,20)).solve()) # not tested (1s) sage: s.show3d() # not tested (<1s) If there are no solution, a StopIteration error is raised:: - sage: QuantuminoSolver(7, box=(3,3,3)).solve().next() + sage: next(QuantuminoSolver(7, box=(3,3,3)).solve()) Traceback (most recent call last): ... StopIteration @@ -267,7 +267,7 @@ class QuantuminoState(SageObject): :: sage: from sage.games.quantumino import QuantuminoSolver - sage: QuantuminoSolver(3).solve().next() # not tested (1.5s) + sage: next(QuantuminoSolver(3).solve()) # not tested (1.5s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (1, 0, 0), (1, 0, 1)], Color: green """ @@ -345,7 +345,7 @@ def show3d(self, size=0.85): EXAMPLES:: sage: from sage.games.quantumino import QuantuminoSolver - sage: s = QuantuminoSolver(0).solve().next() # not tested (1.5s) + sage: s = next(QuantuminoSolver(0).solve()) # not tested (1.5s) sage: G = s.show3d() # not tested (<1s) sage: type(G) # not tested @@ -477,7 +477,7 @@ def solve(self, partial=None): Get one solution:: sage: from sage.games.quantumino import QuantuminoSolver - sage: s = QuantuminoSolver(8).solve().next() # long time (9s) + sage: s = next(QuantuminoSolver(8).solve()) # long time (9s) sage: s # long time (fast) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 0, 1), (0, 1, 0), (1, 0, 0), (1, 1, 0)], Color: yellow @@ -507,10 +507,10 @@ def solve(self, partial=None): Enumerate the solutions:: sage: it = QuantuminoSolver(0).solve() - sage: it.next() # not tested + sage: next(it) # not tested Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (1, 0, 0), (1, 1, 0), (1, 1, 1), (1, 2, 0)], Color: deeppink - sage: it.next() # not tested + sage: next(it) # not tested Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (1, 0, 0), (1, 1, 0), (1, 1, 1), (1, 2, 0)], Color: deeppink @@ -518,32 +518,32 @@ def solve(self, partial=None): between consecutive solutions (an animation would be better):: sage: it = QuantuminoSolver(0).solve(partial='common') - sage: it.next().show3d() # not tested (2s) - sage: it.next().show3d() # not tested (< 1s) - sage: it.next().show3d() # not tested (< 1s) + sage: next(it).show3d() # not tested (2s) + sage: next(it).show3d() # not tested (< 1s) + sage: next(it).show3d() # not tested (< 1s) Generalizations of the game inside different boxes:: - sage: QuantuminoSolver(7, (4,4,5)).solve().next() # long time (2s) + sage: next(QuantuminoSolver(7, (4,4,5)).solve()) # long time (2s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 2, 1), (1, 0, 0)], Color: orange - sage: QuantuminoSolver(7, (2,2,20)).solve().next() # long time (1s) + sage: next(QuantuminoSolver(7, (2,2,20)).solve()) # long time (1s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 2, 1), (1, 0, 0)], Color: orange - sage: QuantuminoSolver(3, (2,2,20)).solve().next() # long time (1s) + sage: next(QuantuminoSolver(3, (2,2,20)).solve()) # long time (1s) Quantumino state where the following pentamino is put aside : Polyomino: [(0, 0, 0), (0, 1, 0), (0, 2, 0), (1, 0, 0), (1, 0, 1)], Color: green If the volume of the box is not 80, there is no solution:: - sage: QuantuminoSolver(7, box=(3,3,9)).solve().next() + sage: next(QuantuminoSolver(7, box=(3,3,9)).solve()) Traceback (most recent call last): ... StopIteration If the box is too small, there is no solution:: - sage: QuantuminoSolver(4, box=(40,2,1)).solve().next() + sage: next(QuantuminoSolver(4, box=(40,2,1)).solve()) Traceback (most recent call last): ... StopIteration diff --git a/src/sage/games/sudoku.py b/src/sage/games/sudoku.py index f2c1c85ffe6..271607857c0 100644 --- a/src/sage/games/sudoku.py +++ b/src/sage/games/sudoku.py @@ -79,7 +79,7 @@ def sudoku(m): if not(isinstance(m, Matrix)): raise ValueError('sudoku function expects puzzle to be a matrix, perhaps use the Sudoku class') - solution = Sudoku(m).solve(algorithm='dlx').next() + solution = next(Sudoku(m).solve(algorithm='dlx')) return (solution.to_matrix() if solution else None) @@ -116,7 +116,7 @@ class Sudoku(SageObject): | 3 | 2| | |4 9 | 5 | 3| +-----+-----+-----+ - sage: print a.solve().next() + sage: print next(a.solve()) +-----+-----+-----+ |5 1 3|6 8 7|2 4 9| |8 4 9|5 2 1|6 3 7| @@ -452,7 +452,7 @@ def to_latex(self): gen = (x for x in self.puzzle) for row in range(nsquare): for col in range(nsquare): - entry = gen.next() + entry = next(gen) array.append((str(entry) if entry else ' ')) array.append(('' if col == nsquare - 1 else '&')) array.append(('\\\\\n' if (row+1) % n else '\\\\\\hline\n')) @@ -512,7 +512,7 @@ def solve(self, algorithm = 'dlx'): |5 | 8 | 3 6| | 3| | | +-----+-----+-----+ - sage: h.solve(algorithm='backtrack').next() + sage: next(h.solve(algorithm='backtrack')) +-----+-----+-----+ |8 1 4|6 3 7|9 2 5| |3 2 5|1 4 9|6 8 7| @@ -526,7 +526,7 @@ def solve(self, algorithm = 'dlx'): |5 7 9|4 8 1|2 3 6| |1 8 3|5 6 2|7 4 9| +-----+-----+-----+ - sage: h.solve(algorithm='dlx').next() + sage: next(h.solve(algorithm='dlx')) +-----+-----+-----+ |8 1 4|6 3 7|9 2 5| |3 2 5|1 4 9|6 8 7| @@ -548,7 +548,7 @@ def solve(self, algorithm = 'dlx'): in his database. We solve it twice. :: sage: b = Sudoku('8..6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......') - sage: b.solve(algorithm='dlx').next() == b.solve(algorithm='backtrack').next() + sage: next(b.solve(algorithm='dlx')) == next(b.solve(algorithm='backtrack')) True @@ -567,7 +567,7 @@ def solve(self, algorithm = 'dlx'): '6.2.5.........4.3..........43...8....1....2........7..5..27...........81...6.....',\ '.923.........8.1...........1.7.4...........658.........6.5.2...4.....7.....9.....'] sage: p = [Sudoku(top[i]) for i in range(10)] - sage: verify = [p[i].solve(algorithm='dlx').next() == p[i].solve(algorithm='backtrack').next() for i in range(10)] + sage: verify = [next(p[i].solve(algorithm='dlx')) == next(p[i].solve(algorithm='backtrack')) for i in range(10)] sage: verify == [True]*10 True @@ -576,14 +576,14 @@ def solve(self, algorithm = 'dlx'): A `25\times 25` puzzle that the backtrack algorithm is not equipped to handle. Since ``solve`` returns a generator this test will not go boom until we ask for a solution with ``next``. :: sage: too_big = Sudoku([0]*625) - sage: too_big.solve(algorithm='backtrack').next() + sage: next(too_big.solve(algorithm='backtrack')) Traceback (most recent call last): ... ValueError: The Sudoku backtrack algorithm is limited to puzzles of size 16 or smaller. An attempt to use a non-existent algorithm. :: - sage: Sudoku([0]).solve(algorithm='bogus').next() + sage: next(Sudoku([0]).solve(algorithm='bogus')) Traceback (most recent call last): ... NotImplementedError: bogus is not an algorithm for Sudoku puzzles @@ -661,7 +661,7 @@ def backtrack(self): | 4 | | 7| | 7| |3 | +-----+-----+-----+ - sage: print g.solve(algorithm='backtrack').next() + sage: print next(g.solve(algorithm='backtrack')) +-----+-----+-----+ |1 6 2|8 5 7|4 9 3| |5 3 4|1 2 9|6 7 8| @@ -696,7 +696,7 @@ def backtrack(self): | 2| 1 | | | | 4 | 9| +-----+-----+-----+ - sage: print c.solve(algorithm='backtrack').next() + sage: print next(c.solve(algorithm='backtrack')) +-----+-----+-----+ |9 8 7|6 5 4|3 2 1| |2 4 6|1 7 3|9 8 5| @@ -765,7 +765,7 @@ def dlx(self, count_only=False): solution and then check to see if there are more or not. :: sage: e = Sudoku('4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......') - sage: print e.dlx().next() + sage: print next(e.dlx()) [4, 1, 7, 3, 6, 9, 8, 2, 5, 6, 3, 2, 1, 5, 8, 9, 4, 7, 9, 5, 8, 7, 2, 4, 3, 1, 6, 8, 2, 5, 4, 3, 7, 1, 6, 9, 7, 9, 1, 5, 8, 6, 4, 3, 2, 3, 4, 6, 9, 1, 2, 7, 5, 8, 2, 8, 9, 6, 4, 3, 5, 7, 1, 5, 7, 3, 2, 9, 1, 6, 8, 4, 1, 6, 4, 8, 7, 5, 2, 9, 3] sage: len(list(e.dlx())) 1 @@ -782,7 +782,7 @@ def dlx(self, count_only=False): A larger puzzle, with multiple solutions, but we just get one. :: sage: j = Sudoku('....a..69.3....1d.2...8....e.4....b....5..c.......7.......g...f....1.e..2.b.8..3.......4.d.....6.........f..7.g..9.a..c...5.....8..f.....1..e.79.c....b.....2...6.....g.7......84....3.d..a.5....5...7..e...ca.....3.1.......b......f....4...d..e..g.92.6..8....') - sage: print j.dlx().next() + sage: print next(j.dlx()) [5, 15, 16, 14, 10, 13, 7, 6, 9, 2, 3, 4, 11, 8, 12, 1, 13, 3, 2, 12, 11, 16, 8, 15, 1, 6, 7, 14, 10, 4, 9, 5, 1, 10, 11, 6, 9, 4, 3, 5, 15, 8, 12, 13, 16, 7, 14, 2, 9, 8, 7, 4, 12, 2, 1, 14, 10, 5, 16, 11, 6, 3, 15, 13, 12, 16, 4, 1, 13, 14, 9, 10, 2, 7, 11, 6, 8, 15, 5, 3, 3, 14, 5, 7, 16, 11, 15, 4, 12, 13, 8, 9, 1, 2, 10, 6, 2, 6, 13, 11, 1, 8, 5, 3, 4, 15, 14, 10, 7, 9, 16, 12, 15, 9, 8, 10, 2, 6, 12, 7, 3, 16, 5, 1, 4, 14, 13, 11, 8, 11, 3, 15, 5, 10, 4, 2, 13, 1, 6, 12, 14, 16, 7, 9, 16, 12, 14, 13, 7, 15, 11, 1, 8, 9, 4, 5, 2, 6, 3, 10, 6, 2, 10, 5, 14, 12, 16, 9, 7, 11, 15, 3, 13, 1, 4, 8, 4, 7, 1, 9, 8, 3, 6, 13, 16, 14, 10, 2, 5, 12, 11, 15, 11, 5, 9, 8, 6, 7, 13, 16, 14, 3, 1, 15, 12, 10, 2, 4, 7, 13, 15, 3, 4, 1, 10, 8, 5, 12, 2, 16, 9, 11, 6, 14, 10, 1, 6, 2, 15, 5, 14, 12, 11, 4, 9, 7, 3, 13, 8, 16, 14, 4, 12, 16, 3, 9, 2, 11, 6, 10, 13, 8, 15, 5, 1, 7] The puzzle ``h`` from above, but purposely made unsolvable with addition in second entry. :: @@ -790,7 +790,7 @@ def dlx(self, count_only=False): sage: hbad = Sudoku('82.6..9.5.............2.31...7318.6.24.....73...........279.1..5...8..36..3......') sage: len(list(hbad.dlx())) 0 - sage: hbad.dlx().next() + sage: next(hbad.dlx()) Traceback (most recent call last): ... StopIteration @@ -798,7 +798,7 @@ def dlx(self, count_only=False): A stupidly small puzzle to test the lower limits of arbitrary sized input. :: sage: s = Sudoku('.') - sage: print s.solve(algorithm='dlx').next() + sage: print next(s.solve(algorithm='dlx')) +-+ |1| +-+ @@ -867,7 +867,7 @@ def make_row(row, col, entry): gen = (entry for entry in self.puzzle) for row in range(nsquare): for col in range(nsquare): - puzz = gen.next() + puzz = next(gen) # All (zero-based) entries are possible, or only one is possible entries = ([puzz-1] if puzz else range(nsquare)) for entry in entries: diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index 89f6ff99dfb..7e771b33692 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -212,8 +212,7 @@ from sage.misc.superseded import deprecation from sage.modules.all import span, vector from sage.rings.all import QQ, RR, ZZ, gcd -from sage.structure.all import SageObject -from sage.structure.coerce import parent +from sage.structure.all import SageObject, parent from sage.libs.ppl import C_Polyhedron, Generator_System, Constraint_System, \ Linear_Expression, ray as PPL_ray, point as PPL_point, \ Poly_Con_Relation @@ -1056,17 +1055,17 @@ def classify_cone_2d(ray0, ray1, check=True): sage: from sage.geometry.cone import normalize_rays sage: for i in range(10): - ... ray0 = random_vector(ZZ, 3) - ... ray1 = random_vector(ZZ, 3) - ... if ray0.is_zero() or ray1.is_zero(): continue - ... ray0, ray1 = normalize_rays([ray0, ray1], ZZ^3) - ... d, k = classify_cone_2d(ray0, ray1, check=True) - ... assert (d,k) == classify_cone_2d(ray1, ray0) - ... if d == 0: continue - ... frac = Hirzebruch_Jung_continued_fraction_list(k/d) - ... if len(frac)>100: continue # avoid expensive computation - ... hilb = Cone([ray0, ray1]).Hilbert_basis() - ... assert len(hilb) == len(frac) + 1 + ....: ray0 = random_vector(ZZ, 3) + ....: ray1 = random_vector(ZZ, 3) + ....: if ray0.is_zero() or ray1.is_zero(): continue + ....: ray0, ray1 = normalize_rays([ray0, ray1], ZZ^3) + ....: d, k = classify_cone_2d(ray0, ray1, check=True) + ....: assert (d,k) == classify_cone_2d(ray1, ray0) + ....: if d == 0: continue + ....: frac = (k/d).continued_fraction_list("hj") + ....: if len(frac)>100: continue # avoid expensive computation + ....: hilb = Cone([ray0, ray1]).Hilbert_basis() + ....: assert len(hilb) == len(frac) + 1 """ if check: assert ray0.parent() is ray1.parent() diff --git a/src/sage/geometry/fan.py b/src/sage/geometry/fan.py index e7e6714098a..811b16b0698 100644 --- a/src/sage/geometry/fan.py +++ b/src/sage/geometry/fan.py @@ -2531,7 +2531,7 @@ def is_isomorphic(self, other): return other._2d_echelon_form() in self._2d_echelon_forms() generator = fan_isomorphism_generator(self, other) try: - generator.next() + next(generator) return True except StopIteration: return False diff --git a/src/sage/geometry/fan_isomorphism.py b/src/sage/geometry/fan_isomorphism.py index 5c4804e9b8d..6a20f83f7f7 100644 --- a/src/sage/geometry/fan_isomorphism.py +++ b/src/sage/geometry/fan_isomorphism.py @@ -98,7 +98,7 @@ def fan_isomorphism_generator(fan1, fan2): ... Cone([m1*vector([-1,-14]), m1*vector([-100, -5])])]) sage: fan2 = Fan([Cone([m2*vector([23, 14]), m2*vector([ 3,100])]), ... Cone([m2*vector([-1,-14]), m2*vector([-100, -5])])]) - sage: fan_isomorphism_generator(fan1, fan2).next() + sage: next(fan_isomorphism_generator(fan1, fan2)) [18 1 -5] [ 4 0 -1] [ 5 0 -1] @@ -240,7 +240,7 @@ def find_isomorphism(fan1, fan2, check=False): """ generator = fan_isomorphism_generator(fan1, fan2) try: - m = generator.next() + m = next(generator) except StopIteration: raise FanNotIsomorphicError diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index adddb797bb9..8a5649d365d 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -1914,7 +1914,7 @@ def varchenko_matrix(self, names='h'): """ from sage.rings.all import PolynomialRing from sage.matrix.constructor import identity_matrix - from sage.misc.misc import prod + from sage.misc.all import prod k = len(self) R = PolynomialRing(QQ, names, k) h = R.gens() diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index a6b7e8dbcfd..1604edd8f5e 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -110,7 +110,7 @@ from sage.matrix.constructor import matrix from sage.matrix.matrix import is_Matrix from sage.misc.all import cached_method, tmp_filename -from sage.misc.misc import SAGE_SHARE +from sage.env import SAGE_SHARE from sage.modules.all import vector, span from sage.misc.superseded import deprecated_function_alias, deprecation from sage.plot.plot3d.index_face_set import IndexFaceSet diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index cc8795f22fb..c1e8e6c5d88 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -916,7 +916,7 @@ def Hrep_generator(self): EXAMPLES:: sage: p = polytopes.n_cube(3) - sage: p.Hrep_generator().next() + sage: next(p.Hrep_generator()) An inequality (0, 0, -1) x + 1 >= 0 """ for H in self.Hrepresentation(): @@ -1004,9 +1004,9 @@ def Vrep_generator(self): sage: p = polytopes.cyclic_polytope(3,4) sage: vg = p.Vrep_generator() - sage: vg.next() + sage: next(vg) A vertex at (0, 0, 0) - sage: vg.next() + sage: next(vg) A vertex at (1, 1, 1) """ for V in self.Vrepresentation(): @@ -1099,7 +1099,7 @@ def equation_generator(self): sage: p = polytopes.regular_polygon(8,base_ring=RDF) sage: p3 = Polyhedron(vertices = [x+[0] for x in p.vertices()], base_ring=RDF) - sage: p3.equation_generator().next() + sage: next(p3.equation_generator()) An equation (0.0, 0.0, 1.0) x + 0.0 == 0 """ for H in self.Hrepresentation(): @@ -1182,13 +1182,13 @@ def vertex_generator(self): A vertex at (1, 0) A vertex at (1, 1) sage: v_gen = triangle.vertex_generator() - sage: v_gen.next() # the first vertex + sage: next(v_gen) # the first vertex A vertex at (0, 1) - sage: v_gen.next() # the second vertex + sage: next(v_gen) # the second vertex A vertex at (1, 0) - sage: v_gen.next() # the third vertex + sage: next(v_gen) # the third vertex A vertex at (1, 1) - sage: try: v_gen.next() # there are only three vertices + sage: try: next(v_gen) # there are only three vertices ... except StopIteration: print "STOP" STOP sage: type(v_gen) @@ -1327,7 +1327,7 @@ def line_generator(self): EXAMPLES:: sage: pr = Polyhedron(rays = [[1,0],[-1,0],[0,1]], vertices = [[-1,-1]]) - sage: pr.line_generator().next().vector() + sage: next(pr.line_generator()).vector() (1, 0) """ for V in self.Vrepresentation(): @@ -2368,10 +2368,10 @@ def dilation(self, scalar): EXAMPLES:: sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,6)]) - sage: p.vertex_generator().next() + sage: next(p.vertex_generator()) A vertex at (2, 4, 8) sage: p2 = p.dilation(2) - sage: p2.vertex_generator().next() + sage: next(p2.vertex_generator()) A vertex at (4, 8, 16) sage: p.dilation(2) == p * 2 True diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index aaa17837477..cb5d6ff147a 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -103,7 +103,7 @@ sage: trunc_quadr = Polyhedron(vertices=[[1,0],[0,1]], rays=[[1,0],[0,1]]) sage: trunc_quadr A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices and 2 rays - sage: v = trunc_quadr.vertex_generator().next() # the first vertex in the internal enumeration + sage: v = next(trunc_quadr.vertex_generator()) # the first vertex in the internal enumeration sage: v A vertex at (0, 1) sage: v.vector() @@ -122,7 +122,7 @@ sage: v.polyhedron() A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices and 2 rays - sage: r = trunc_quadr.ray_generator().next() + sage: r = next(trunc_quadr.ray_generator()) sage: r A ray in the direction (0, 1) sage: r.vector() diff --git a/src/sage/geometry/polyhedron/face.py b/src/sage/geometry/polyhedron/face.py index 39914ef6fb1..61ed02770cd 100644 --- a/src/sage/geometry/polyhedron/face.py +++ b/src/sage/geometry/polyhedron/face.py @@ -175,7 +175,7 @@ def ray_generator(self): sage: pi = Polyhedron(ieqs = [[1,1,0],[1,0,1]]) sage: face = pi.faces(1)[0] - sage: face.ray_generator().next() + sage: next(face.ray_generator()) A ray in the direction (1, 0) """ for V in self.ambient_Vrepresentation(): @@ -208,7 +208,7 @@ def line_generator(self): sage: pr = Polyhedron(rays = [[1,0],[-1,0],[0,1]], vertices = [[-1,-1]]) sage: face = pr.faces(1)[0] - sage: face.line_generator().next() + sage: next(face.line_generator()) A line in the direction (1, 0) """ for V in self.ambient_Vrepresentation(): diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index 30618f34f56..ca8c03c34aa 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -444,7 +444,7 @@ def twenty_four_cell(self): EXAMPLES:: sage: p24 = polytopes.twenty_four_cell() - sage: v = p24.vertex_generator().next() + sage: v = next(p24.vertex_generator()) sage: for adj in v.neighbors(): print adj A vertex at (-1/2, -1/2, -1/2, 1/2) A vertex at (-1/2, -1/2, 1/2, -1/2) diff --git a/src/sage/geometry/polyhedron/palp_database.py b/src/sage/geometry/polyhedron/palp_database.py index 4c9b965d17e..3d0a7bb73d3 100644 --- a/src/sage/geometry/polyhedron/palp_database.py +++ b/src/sage/geometry/polyhedron/palp_database.py @@ -66,22 +66,22 @@ class PALPreader(SageObject): [(3, 4), (3, 10), (3, 5), (3, 9), (3, 7), (4, 6), (4, 8), (4, 9), (4, 5), (4, 5), (4, 9), (4, 7), (5, 8), (5, 6), (5, 7), (6, 7)] - sage: iter(PALPreader(2, output='list')).next() + sage: next(iter(PALPreader(2, output='list'))) [[1, 0], [0, 1], [-1, -1]] sage: type(_) - sage: iter(PALPreader(2, output='Polyhedron')).next() + sage: next(iter(PALPreader(2, output='Polyhedron'))) A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices sage: type(_) - sage: iter(PALPreader(2, output='PPL')).next() + sage: next(iter(PALPreader(2, output='PPL'))) A 2-dimensional lattice polytope in ZZ^2 with 3 vertices sage: type(_) - sage: iter(PALPreader(2, output='PointCollection')).next() + sage: next(iter(PALPreader(2, output='PointCollection'))) [ 1, 0], [ 0, 1], [-1, -1] @@ -198,7 +198,7 @@ def _iterate_list(self, start, stop, step): sage: from sage.geometry.polyhedron.palp_database import PALPreader sage: polygons = PALPreader(2) sage: iter = polygons._iterate_list(0,4,2) - sage: iter.next() + sage: next(iter) [[1, 0], [0, 1], [-1, -1]] """ if start is None: @@ -257,7 +257,7 @@ def _iterate_Polyhedron(self, start, stop, step): sage: from sage.geometry.polyhedron.palp_database import PALPreader sage: polygons = PALPreader(2) sage: iter = polygons._iterate_Polyhedron(0,4,2) - sage: iter.next() + sage: next(iter) A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices """ parent = self._polyhedron_parent @@ -283,7 +283,7 @@ def _iterate_PPL(self, start, stop, step): sage: from sage.geometry.polyhedron.palp_database import PALPreader sage: polygons = PALPreader(2) sage: iter = polygons._iterate_PPL(0,4,2) - sage: iter.next() + sage: next(iter) A 2-dimensional lattice polytope in ZZ^2 with 3 vertices """ for vertices in self._iterate_list(start, stop, step): @@ -307,7 +307,7 @@ def _iterate_PointCollection(self, start, stop, step): sage: from sage.geometry.polyhedron.palp_database import PALPreader sage: polygons = PALPreader(2) sage: iter = polygons._iterate_PointCollection(0,4,2) - sage: iter.next() + sage: next(iter) [ 1, 0], [ 0, 1], [-1, -1] @@ -339,7 +339,7 @@ def _iterate(self, output=None): sage: func > sage: iter = func(0,1,1) - sage: iter.next() + sage: next(iter) [[1, 0], [0, 1], [-1, -1]] """ if output is None: @@ -390,7 +390,7 @@ def __getitem__(self, item): return iterator(item.start, item.stop, item.step) else: try: - return iterator(item, item+1, 1).next() + return next(iterator(item, item+1, 1)) except StopIteration: raise IndexError('Index out of range.') @@ -416,7 +416,7 @@ class Reflexive4dHodge(PALPreader): sage: from sage.geometry.polyhedron.palp_database import Reflexive4dHodge sage: ref = Reflexive4dHodge(1,101) # optional - polytopes_db_4d - sage: iter(ref).next().Vrepresentation() # optional - polytopes_db_4d + sage: next(iter(ref)).Vrepresentation() # optional - polytopes_db_4d (A vertex at (-1, -1, -1, -1), A vertex at (0, 0, 0, 1), A vertex at (0, 0, 1, 0), A vertex at (0, 1, 0, 0), A vertex at (1, 0, 0, 0)) """ diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 728e4932623..9641820f067 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -235,7 +235,7 @@ def some_elements(self): self.element_class(self, None, None) ] @cached_method - def zero_element(self): + def zero(self): r""" Return the polyhedron consisting of the origin, which is the neutral element for Minkowski addition. @@ -243,7 +243,7 @@ def zero_element(self): EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: p = Polyhedra(QQ, 4).zero_element(); p + sage: p = Polyhedra(QQ, 4).zero(); p A 0-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex sage: p+p == p True @@ -426,7 +426,7 @@ def convert_base_ring(lstlst): Hrep = [ polyhedron.inequality_generator(), polyhedron.equation_generator() ] return self.element_class(self, None, Hrep, **kwds) if nargs==1 and args[0]==0: - return self.zero_element() + return self.zero() raise ValueError('Cannot convert to polyhedron object.') def base_extend(self, base_ring, backend=None): @@ -664,7 +664,7 @@ def _make_Inequality(self, polyhedron, data): EXAMPLES:: sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)]) # indirect doctest - sage: p.inequality_generator().next() + sage: next(p.inequality_generator()) An inequality (0, 0, -1) x + 3 >= 0 """ try: @@ -691,7 +691,7 @@ def _make_Equation(self, polyhedron, data): EXAMPLES:: sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)]) # indirect doctest - sage: p.equation_generator().next() + sage: next(p.equation_generator()) An equation (0, 44, -25) x - 13 == 0 """ try: @@ -718,7 +718,7 @@ def _make_Vertex(self, polyhedron, data): EXAMPLES:: sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest - sage: p.vertex_generator().next() + sage: next(p.vertex_generator()) A vertex at (1, 2, 3) """ try: @@ -745,7 +745,7 @@ def _make_Ray(self, polyhedron, data): EXAMPLES:: sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest - sage: p.ray_generator().next() + sage: next(p.ray_generator()) A ray in the direction (140, 144, 147) """ try: @@ -772,7 +772,7 @@ def _make_Line(self, polyhedron, data): EXAMPLES:: sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)], lines=[(5/6,6/7,7/8)]) # indirect doctest - sage: p.line_generator().next() + sage: next(p.line_generator()) A line in the direction (140, 144, 147) """ try: diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index baed522eb18..d88fcd7f4a7 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -624,7 +624,7 @@ def schlegel(self, projection_direction=None, height=1.1): center = self.parent_polyhedron.center() if projection_direction is None: if self.parent_polyhedron.is_full_dimensional(): - projection_direction = self.parent_polyhedron.inequality_generator().next().A() + projection_direction = next(self.parent_polyhedron.inequality_generator()).A() else: from sage.rings.arith import primes_first_n projection_direction = primes_first_n(self.polyhedron_ambient_dim) @@ -882,7 +882,7 @@ def adjacent_vertices(i): polygons = [] if polyhedron.n_lines() == 1: - aline = polyhedron.line_generator().next() + aline = next(polyhedron.line_generator()) for shift in [aline(), -aline()]: for i in range(len(coords)): polygons.append( [ coords[i-1],coords[i], @@ -921,7 +921,7 @@ def _init_solid_3d(self, polyhedron): def defining_equation(): # corresponding to a polygon if polyhedron.dim() < 3: - yield polyhedron.equation_generator().next() + yield next(polyhedron.equation_generator()) else: for ineq in polyhedron.inequality_generator(): yield ineq @@ -960,7 +960,7 @@ def adjacent_vertices(i): if polyhedron.n_lines()==1: assert len(faces)>0, "no vertices?" - aline = polyhedron.line_generator().next() + aline = next(polyhedron.line_generator()) for shift in [aline(), -aline()]: for coords in faces: assert len(coords)==2, "There must be two points." diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py index ad003898153..e05087db68e 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py @@ -303,8 +303,8 @@ def find_isomorphism(self, polytope): return self._find_isomorphism_degenerate(polytope) polytope_origin = polytope_vertices[0] - origin_P = C_Polyhedron(Generator_System_iterator( - polytope.minimized_generators()).next()) + origin_P = C_Polyhedron(next(Generator_System_iterator( + polytope.minimized_generators()))) neighbors = [] for c in polytope.minimized_constraints(): @@ -399,7 +399,7 @@ def sub_polytopes(self): def plot(self): """ - Plot the lattice polygon + Plot the lattice polygon. OUTPUT: @@ -409,11 +409,12 @@ def plot(self): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: P = LatticePolytope_PPL((1,0), (0,1), (0,0), (2,2)) - sage: P.plot() # not tested + sage: P.plot() + Graphics object consisting of 6 graphics primitives sage: LatticePolytope_PPL([0], [1]).plot() - Graphics object consisting of 2 graphics primitives + Graphics object consisting of 3 graphics primitives sage: LatticePolytope_PPL([0]).plot() - Graphics object consisting of 1 graphics primitive + Graphics object consisting of 2 graphics primitives """ from sage.plot.point import point2d from sage.plot.polygon import polygon2d @@ -422,7 +423,8 @@ def plot(self): if self.space_dimension() == 1: vertices = [vector(ZZ, (v[0], 0)) for v in vertices] points = [vector(ZZ, (p[0], 0)) for p in points] - point_plot = sum(point2d(p, pointsize=100, color='red') for p in points) + point_plot = sum(point2d(p, pointsize=100, color='red') + for p in points) polygon_plot = polygon2d(vertices, alpha=0.2, color='green', zorder=-1, thickness=2) return polygon_plot + point_plot diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 5d8922e2ccc..24661741a9d 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -38,7 +38,7 @@ suitable fan refinements. We can compute them using :meth:`~LatticePolytope_PPL.fibration_generator` :: - sage: F = P.fibration_generator(2).next() + sage: F = next(P.fibration_generator(2)) sage: F.vertices() ((1, 0, 0, 0), (0, 1, 0, 0), (-3, -2, 0, 0)) @@ -182,7 +182,7 @@ def LatticePolytope_PPL(*args): else: gs.insert(point(Linear_Expression(v, 0))) if not gs.empty(): - dim = Generator_System_iterator(gs).next().space_dimension() + dim = next(Generator_System_iterator(gs)).space_dimension() polytope_class = _class_for_LatticePolytope(dim) return polytope_class(gs) @@ -523,7 +523,7 @@ def vertices_saturating(self, constraint): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: p = LatticePolytope_PPL((0,0),(0,1),(1,0)) - sage: ieq = iter(p.constraints()).next(); ieq + sage: ieq = next(iter(p.constraints())); ieq x0>=0 sage: p.vertices_saturating(ieq) ((0, 0), (0, 1)) @@ -828,7 +828,7 @@ def base_projection(self, fiber): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: poly = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) - sage: fiber = poly.fibration_generator(2).next() + sage: fiber = next(poly.fibration_generator(2)) sage: poly.base_projection(fiber) Finitely generated module V/W over Integer Ring with invariants (0, 0) """ @@ -855,7 +855,7 @@ def base_projection_matrix(self, fiber): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: poly = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) - sage: fiber = poly.fibration_generator(2).next() + sage: fiber = next(poly.fibration_generator(2)) sage: poly.base_projection_matrix(fiber) [0 0 1 0] [0 0 0 1] @@ -892,7 +892,7 @@ def base_rays(self, fiber, points): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: poly = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) - sage: fiber = poly.fibration_generator(2).next() + sage: fiber = next(poly.fibration_generator(2)) sage: poly.base_rays(fiber, poly.integral_points_not_interior_to_facets()) ((-1, -1), (0, 1), (1, 0)) diff --git a/src/sage/geometry/polyhedron/representation.py b/src/sage/geometry/polyhedron/representation.py index 09729c07dfa..34c684b7a6e 100644 --- a/src/sage/geometry/polyhedron/representation.py +++ b/src/sage/geometry/polyhedron/representation.py @@ -98,7 +98,7 @@ def __cmp__(self, other): EXAMPLES:: sage: triangle = Polyhedron([(0,0), (1,0), (0,1)]) - sage: ieq = triangle.inequality_generator().next(); ieq + sage: ieq = next(triangle.inequality_generator()); ieq An inequality (1, 0) x + 0 >= 0 sage: ieq == copy(ieq) True @@ -142,7 +142,7 @@ def vector(self, base_ring=None): EXAMPLES:: sage: s = polytopes.cuboctahedron() - sage: v = s.vertex_generator().next() + sage: v = next(s.vertex_generator()) sage: v A vertex at (-1/2, -1/2, 0) sage: v.vector() @@ -209,7 +209,7 @@ def index(self): EXAMPLES:: sage: s = Polyhedron(vertices=[[1],[-1]]) - sage: first_vertex = s.vertex_generator().next() + sage: first_vertex = next(s.vertex_generator()) sage: first_vertex.index() 0 sage: first_vertex == s.Vrepresentation(0) @@ -496,7 +496,7 @@ def eval(self, Vobj): EXAMPLES:: sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]]) - sage: ineq = triangle.inequality_generator().next() + sage: ineq = next(triangle.inequality_generator()) sage: ineq An inequality (2, -1) x + 1 >= 0 sage: [ ineq.eval(v) for v in triangle.vertex_generator() ] @@ -521,7 +521,7 @@ def incident(self): EXAMPLES:: sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]]) - sage: ineq = triangle.inequality_generator().next() + sage: ineq = next(triangle.inequality_generator()) sage: ineq An inequality (2, -1) x + 1 >= 0 sage: [ v for v in ineq.incident()] @@ -560,7 +560,7 @@ def type(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: repr_obj = p.inequality_generator().next() + sage: repr_obj = next(p.inequality_generator()) sage: repr_obj.type() 0 sage: repr_obj.type() == repr_obj.INEQUALITY @@ -584,7 +584,7 @@ def is_inequality(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: a = p.inequality_generator().next() + sage: a = next(p.inequality_generator()) sage: a.is_inequality() True """ @@ -597,7 +597,7 @@ def _repr_(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: a = p.inequality_generator().next() + sage: a = next(p.inequality_generator()) sage: a._repr_() 'An inequality (-1, 1, 0) x + 0 >= 0' sage: Polyhedron(ieqs=[(1,-1),(-1,2)]).Hrepresentation() @@ -629,7 +629,7 @@ def contains(self, Vobj): EXAMPLES:: sage: p = polytopes.cross_polytope(3) - sage: i1 = p.inequality_generator().next() + sage: i1 = next(p.inequality_generator()) sage: [i1.contains(q) for q in p.vertex_generator()] [True, True, True, True, True, True] sage: p2 = 3*polytopes.n_cube(3) @@ -656,7 +656,7 @@ def interior_contains(self, Vobj): EXAMPLES:: sage: p = polytopes.cross_polytope(3) - sage: i1 = p.inequality_generator().next() + sage: i1 = next(p.inequality_generator()) sage: [i1.interior_contains(q) for q in p.vertex_generator()] [False, True, True, False, False, True] sage: p2 = 3*polytopes.n_cube(3) @@ -704,7 +704,7 @@ def type(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: repr_obj = p.equation_generator().next() + sage: repr_obj = next(p.equation_generator()) sage: repr_obj.type() 1 sage: repr_obj.type() == repr_obj.INEQUALITY @@ -728,7 +728,7 @@ def is_equation(self): TESTS:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: a = p.equation_generator().next() + sage: a = next(p.equation_generator()) sage: a.is_equation() True """ @@ -741,7 +741,7 @@ def _repr_(self): TESTS:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: a = p.equation_generator().next() + sage: a = next(p.equation_generator()) sage: a._repr_() 'An equation (0, 0, 1) x + 0 == 0' sage: Polyhedron().Hrepresentation(0) @@ -769,10 +769,10 @@ def contains(self, Vobj): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: v = p.vertex_generator().next() + sage: v = next(p.vertex_generator()) sage: v A vertex at (0, 0, 0) - sage: a = p.equation_generator().next() + sage: a = next(p.equation_generator()) sage: a An equation (0, 0, 1) x + 0 == 0 sage: a.contains(v) @@ -793,10 +793,10 @@ def interior_contains(self, Vobj): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: v = p.vertex_generator().next() + sage: v = next(p.vertex_generator()) sage: v A vertex at (0, 0, 0) - sage: a = p.equation_generator().next() + sage: a = next(p.equation_generator()) sage: a An equation (0, 0, 1) x + 0 == 0 sage: a.interior_contains(v) @@ -818,7 +818,7 @@ def __init__(self, polyhedron_parent): TESTS:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: a = p.inequality_generator().next() + sage: a = next(p.inequality_generator()) sage: a An inequality (-1, 1, 0) x + 0 >= 0 sage: TestSuite(a).run(skip='_test_pickling') @@ -868,7 +868,7 @@ def is_V(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]]) - sage: v = p.vertex_generator().next() + sage: v = next(p.vertex_generator()) sage: v.is_V() True """ @@ -883,11 +883,11 @@ def is_vertex(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]]) - sage: v = p.vertex_generator().next() + sage: v = next(p.vertex_generator()) sage: v.is_vertex() True sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]]) - sage: r1 = p.ray_generator().next() + sage: r1 = next(p.ray_generator()) sage: r1.is_vertex() False """ @@ -902,10 +902,10 @@ def is_ray(self): EXAMPLES:: sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]]) - sage: r1 = p.ray_generator().next() + sage: r1 = next(p.ray_generator()) sage: r1.is_ray() True - sage: v1 = p.vertex_generator().next() + sage: v1 = next(p.vertex_generator()) sage: v1 A vertex at (-1, -1, 0, -1) sage: v1.is_ray() @@ -922,10 +922,10 @@ def is_line(self): EXAMPLES:: sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]]) - sage: line1 = p.line_generator().next() + sage: line1 = next(p.line_generator()) sage: line1.is_line() True - sage: v1 = p.vertex_generator().next() + sage: v1 = next(p.vertex_generator()) sage: v1.is_line() False """ @@ -938,8 +938,8 @@ def neighbors(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]]) - sage: v = p.vertex_generator().next() - sage: v.neighbors().next() + sage: v = next(p.vertex_generator()) + sage: next(v.neighbors()) A vertex at (0, 3) """ adjacency_matrix = self.polyhedron().vertex_adjacency_matrix() @@ -954,9 +954,9 @@ def adjacent(self): TESTS:: sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]]) - sage: v = p.vertex_generator().next() - sage: a = v.neighbors().next() - sage: b = v.adjacent().next() + sage: v = next(p.vertex_generator()) + sage: a = next(v.neighbors()) + sage: b = next(v.adjacent()) sage: a==b True """ @@ -969,10 +969,10 @@ def is_incident(self, Hobj): EXAMPLES:: sage: p = polytopes.n_cube(3) - sage: h1 = p.inequality_generator().next() + sage: h1 = next(p.inequality_generator()) sage: h1 An inequality (0, 0, -1) x + 1 >= 0 - sage: v1 = p.vertex_generator().next() + sage: v1 = next(p.vertex_generator()) sage: v1 A vertex at (-1, -1, -1) sage: v1.is_incident(h1) @@ -987,8 +987,8 @@ def __mul__(self, Hobj): TESTS:: sage: p = polytopes.n_cube(3) - sage: h1 = p.inequality_generator().next() - sage: v1 = p.vertex_generator().next() + sage: h1 = next(p.inequality_generator()) + sage: v1 = next(p.vertex_generator()) sage: v1.__mul__(h1) 2 """ @@ -1002,7 +1002,7 @@ def incident(self): EXAMPLES:: sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]]) - sage: ineq = triangle.inequality_generator().next() + sage: ineq = next(triangle.inequality_generator()) sage: ineq An inequality (2, -1) x + 1 >= 0 sage: [ v for v in ineq.incident()] @@ -1040,7 +1040,7 @@ def type(self): EXAMPLES:: sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) - sage: repr_obj = p.vertex_generator().next() + sage: repr_obj = next(p.vertex_generator()) sage: repr_obj.type() 2 sage: repr_obj.type() == repr_obj.INEQUALITY @@ -1064,7 +1064,7 @@ def is_vertex(self): EXAMPLES:: sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]]) - sage: a = p.vertex_generator().next() + sage: a = next(p.vertex_generator()) sage: a.is_vertex() True """ @@ -1081,7 +1081,7 @@ def _repr_(self): TESTS:: sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]]) - sage: v = p.vertex_generator().next() + sage: v = next(p.vertex_generator()) sage: v.__repr__() 'A vertex at (1, 0)' """ @@ -1094,8 +1094,8 @@ def evaluated_on(self, Hobj): EXAMPLES:: sage: p = polytopes.n_cube(3) - sage: v = p.vertex_generator().next() - sage: h = p.inequality_generator().next() + sage: v = next(p.vertex_generator()) + sage: h = next(p.inequality_generator()) sage: v A vertex at (-1, -1, -1) sage: h @@ -1140,7 +1140,7 @@ def type(self): EXAMPLES:: sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]]) - sage: repr_obj = p.ray_generator().next() + sage: repr_obj = next(p.ray_generator()) sage: repr_obj.type() 3 sage: repr_obj.type() == repr_obj.INEQUALITY @@ -1164,7 +1164,7 @@ def is_ray(self): EXAMPLES:: sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]]) - sage: a = p.ray_generator().next() + sage: a = next(p.ray_generator()) sage: a.is_ray() True """ @@ -1177,7 +1177,7 @@ def _repr_(self): TESTS:: sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]]) - sage: a = p.ray_generator().next() + sage: a = next(p.ray_generator()) sage: a._repr_() 'A ray in the direction (0, 1)' """ @@ -1190,8 +1190,8 @@ def evaluated_on(self, Hobj): EXAMPLES:: sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]]) - sage: a = p.ray_generator().next() - sage: h = p.inequality_generator().next() + sage: a = next(p.ray_generator()) + sage: h = next(p.inequality_generator()) sage: a.evaluated_on(h) 0 """ @@ -1217,7 +1217,7 @@ def type(self): EXAMPLES:: sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]]) - sage: repr_obj = p.line_generator().next() + sage: repr_obj = next(p.line_generator()) sage: repr_obj.type() 4 sage: repr_obj.type() == repr_obj.INEQUALITY @@ -1240,7 +1240,7 @@ def is_line(self): TESTS:: sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]]) - sage: a = p.line_generator().next() + sage: a = next(p.line_generator()) sage: a.is_line() True """ @@ -1253,7 +1253,7 @@ def _repr_(self): TESTS:: sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]]) - sage: a = p.line_generator().next() + sage: a = next(p.line_generator()) sage: a.__repr__() 'A line in the direction (0, 1, 0)' """ @@ -1266,8 +1266,8 @@ def evaluated_on(self, Hobj): EXAMPLES:: sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]]) - sage: a = p.line_generator().next() - sage: h = p.inequality_generator().next() + sage: a = next(p.line_generator()) + sage: h = next(p.inequality_generator()) sage: a.evaluated_on(h) 0 """ diff --git a/src/sage/geometry/toric_lattice_element.pyx b/src/sage/geometry/toric_lattice_element.pyx index c8fe9b2f74c..04c8d4cb32f 100644 --- a/src/sage/geometry/toric_lattice_element.pyx +++ b/src/sage/geometry/toric_lattice_element.pyx @@ -94,9 +94,7 @@ Or you can create a homomorphism from one lattice to any other:: # http://www.gnu.org/licenses/ #***************************************************************************** - -include 'sage/ext/cdefs.pxi' -include 'sage/ext/stdsage.pxi' # Needed for PY_NEW +from sage.libs.gmp.mpz cimport * from sage.geometry.toric_plotter import ToricPlotter from sage.modules.vector_integer_dense cimport Vector_integer_dense @@ -174,7 +172,7 @@ cdef class ToricLatticeElement(Vector_integer_dense): # without any further documentation as well... cdef _new_c(self): cdef ToricLatticeElement y - y = PY_NEW(ToricLatticeElement) + y = ToricLatticeElement.__new__(ToricLatticeElement) y._init(self._degree, self._parent) return y @@ -450,7 +448,7 @@ def unpickle_v1(parent, entries, degree, is_mutable): lattice(1, 2, 3) """ cdef ToricLatticeElement v - v = PY_NEW(ToricLatticeElement) + v = ToricLatticeElement.__new__(ToricLatticeElement) v._init(degree, parent) cdef Integer z for i from 0 <= i < degree: diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index ad7e296c3a5..5fad44d811a 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -346,11 +346,11 @@ def __iter__(self): sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) sage: triangulation = pc.triangulate() sage: iter = triangulation.__iter__() - sage: iter.next() + sage: next(iter) (1, 3, 4) - sage: iter.next() + sage: next(iter) (2, 3, 4) - sage: iter.next() + sage: next(iter) Traceback (most recent call last): ... StopIteration @@ -390,7 +390,7 @@ def __len__(self): sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) - sage: triangulation = pc.triangulations().next() + sage: triangulation = next(pc.triangulations()) sage: triangulation.__len__() 2 sage: len(triangulation) # equivalent @@ -408,7 +408,7 @@ def _repr_(self): sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1],[2,2]]) sage: t = pc.triangulations() - sage: t.next()._repr_() + sage: next(t)._repr_() '(<1,4,5>, <2,4,5>)' """ #s = 'A triangulation' diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 9074bad0b7d..089541e0bfe 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -269,8 +269,8 @@ def _have_TOPCOM(cls): return PointConfiguration._have_TOPCOM_cached try: - out = PointConfiguration._TOPCOM_exec('points2placingtriang', - '[[0,1],[1,1]]', verbose=False).next() + out = next(PointConfiguration._TOPCOM_exec('points2placingtriang', + '[[0,1],[1,1]]', verbose=False)) PointConfiguration._have_TOPCOM_cached = True assert out=='{{0,1}}',\ 'TOPCOM ran but did not produce the correct output!' @@ -684,7 +684,7 @@ def _TOPCOM_triangulations(self, verbose=True): sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) sage: iter = p._TOPCOM_triangulations(verbose=True) - sage: iter.next() # optional - TOPCOM + sage: next(iter) # optional - TOPCOM #### TOPCOM input #### # points2triangs # [[0,0,1],[0,1,1],[1,0,1],[1,1,1],[-1,-1,1]] @@ -747,7 +747,7 @@ def _TOPCOM_triangulate(self, verbose=True): else: command += "placingtriang" - return self._TOPCOM_communicate(command, verbose).next() + return next(self._TOPCOM_communicate(command, verbose)) def restrict_to_regular_triangulations(self, regular=True): @@ -929,13 +929,13 @@ def triangulations(self, verbose=False): sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) sage: iter = p.triangulations() - sage: iter.next() + sage: next(iter) (<1,3,4>, <2,3,4>) - sage: iter.next() + sage: next(iter) (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>) - sage: iter.next() + sage: next(iter) (<1,2,3>, <1,2,4>) - sage: iter.next() + sage: next(iter) (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) sage: p.triangulations_list() [(<1,3,4>, <2,3,4>), @@ -953,13 +953,13 @@ def triangulations(self, verbose=False): sage: p.set_engine('TOPCOM') # optional - TOPCOM sage: iter = p.triangulations() # optional - TOPCOM - sage: iter.next() # optional - TOPCOM + sage: next(iter) # optional - TOPCOM (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: iter.next() # optional - TOPCOM + sage: next(iter) # optional - TOPCOM (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>) - sage: iter.next() # optional - TOPCOM + sage: next(iter) # optional - TOPCOM (<1,2,3>, <1,2,4>) - sage: iter.next() # optional - TOPCOM + sage: next(iter) # optional - TOPCOM (<1,3,4>, <2,3,4>) sage: p.triangulations_list() # optional - TOPCOM [(<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>), @@ -1059,7 +1059,7 @@ def triangulate(self, verbose=False): return self.placing_triangulation() try: - return self.triangulations(verbose).next() + return next(self.triangulations(verbose)) except StopIteration: # there is no triangulation pass @@ -1966,7 +1966,7 @@ def facets_of_simplex(simplex): # identify visible facets visible_facets = [] for facet in facets: - origin = iter(facet).next() + origin = next(iter(facet)) normal = facet_normals[facet] v = point.reduced_affine_vector() - origin.reduced_affine_vector() if v*normal>0: diff --git a/src/sage/graphs/base/static_dense_graph.pxd b/src/sage/graphs/base/static_dense_graph.pxd index aeec83609a1..8e6531a134f 100644 --- a/src/sage/graphs/base/static_dense_graph.pxd +++ b/src/sage/graphs/base/static_dense_graph.pxd @@ -1,3 +1,4 @@ -include "sage/misc/binary_matrix.pxi" +from sage.data_structures.binary_matrix cimport binary_matrix_t + cdef dict dense_graph_init(binary_matrix_t m, g, translation = ?) diff --git a/src/sage/graphs/base/static_dense_graph.pyx b/src/sage/graphs/base/static_dense_graph.pyx index 11e98fe212d..fe0f8d2e5bd 100644 --- a/src/sage/graphs/base/static_dense_graph.pyx +++ b/src/sage/graphs/base/static_dense_graph.pyx @@ -40,6 +40,7 @@ Index Functions --------- """ +include "sage/data_structures/binary_matrix.pxi" cdef dict dense_graph_init(binary_matrix_t m, g, translation=False): r""" @@ -59,8 +60,7 @@ cdef dict dense_graph_init(binary_matrix_t m, g, translation=False): cdef int is_undirected = isinstance(g, Graph) cdef int n = g.order() - binary_matrix_init(m,n,n) - binary_matrix_fill(m,0) + binary_matrix_init(m, n, n) # If the vertices are 0...n-1, let's avoid an unnecessary dictionary if g.vertices() == range(n): @@ -68,16 +68,16 @@ cdef dict dense_graph_init(binary_matrix_t m, g, translation=False): d_translation = {i:i for i in range(n)} for i,j in g.edge_iterator(labels = False): - binary_matrix_set1(m,i,j) + binary_matrix_set1(m, i, j) if is_undirected: - binary_matrix_set1(m,j,i) + binary_matrix_set1(m, j, i) else: d_translation = {v:i for i,v in enumerate(g.vertices())} for u,v in g.edge_iterator(labels = False): - binary_matrix_set1(m,d_translation[u],d_translation[v]) + binary_matrix_set1(m, d_translation[u], d_translation[v]) if is_undirected: - binary_matrix_set1(m,d_translation[v],d_translation[u]) + binary_matrix_set1(m, d_translation[v], d_translation[u]) if translation: return d_translation @@ -171,6 +171,7 @@ def is_strongly_regular(g, parameters = False): """ g._scream_if_not_simple() cdef binary_matrix_t m + cdef bitset_t b_tmp cdef int n = g.order() cdef int inter cdef int i,j,l, k @@ -186,6 +187,8 @@ def is_strongly_regular(g, parameters = False): if not all(d == k for d in degree): return False + bitset_init(b_tmp, n) + # m i now our copy of the graph dense_graph_init(m, g) @@ -197,9 +200,8 @@ def is_strongly_regular(g, parameters = False): # The intersection of the common neighbors of i and j is a AND of # their respective rows. A popcount then returns its cardinality. - inter = 0 - for l in range(m.width): - inter += __builtin_popcountl(m.rows[i][l] & m.rows[j][l]) + bitset_and(b_tmp, m.rows[i], m.rows[j]) + inter = bitset_len(b_tmp) # Check that this cardinality is correct according to the values of lambda and mu if binary_matrix_get(m,i,j): @@ -207,15 +209,18 @@ def is_strongly_regular(g, parameters = False): llambda = inter elif llambda != inter: binary_matrix_free(m) + bitset_free(b_tmp) return False else: if mu == -1: mu = inter elif mu != inter: binary_matrix_free(m) + bitset_free(b_tmp) return False binary_matrix_free(m) + bitset_free(b_tmp) if parameters: return (n,k,llambda,mu) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index 35e80339cdc..cf0283b028b 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -927,7 +927,7 @@ def matching_polynomial(self, algorithm="Godsil", name=None): Compute the matching polynomial of a line with `60` vertices:: sage: from sage.functions.orthogonal_polys import chebyshev_U - sage: g = graphs.trees(60).next() + sage: g = next(graphs.trees(60)) sage: chebyshev_U(60, x/2) == BipartiteGraph(g).matching_polynomial(algorithm='rook') True diff --git a/src/sage/graphs/chrompoly.pyx b/src/sage/graphs/chrompoly.pyx index 64222899fbc..b521c28ffdb 100644 --- a/src/sage/graphs/chrompoly.pyx +++ b/src/sage/graphs/chrompoly.pyx @@ -19,7 +19,7 @@ REFERENCE: from sage.rings.integer_ring import ZZ from sage.rings.integer cimport Integer -from sage.misc.misc import prod +from sage.misc.all import prod include 'sage/ext/interrupt.pxi' include 'sage/ext/cdefs.pxi' include 'sage/ext/stdsage.pxi' @@ -89,8 +89,14 @@ def chromatic_polynomial(G, return_tree_basis = False): return x*(x-1)**(G.num_verts()-1) cdef int nverts, nedges, i, j, u, v, top, bot, num_chords, next_v - cdef int *queue, *chords1, *chords2, *bfs_reorder, *parent - cdef mpz_t m, coeff, *tot, *coeffs + cdef int *queue + cdef int *chords1 + cdef int *chords2 + cdef int *bfs_reorder + cdef int *parent + cdef mpz_t m, coeff + cdef mpz_t *tot + cdef mpz_t *coeffs G = G.relabel(inplace=False) G.remove_multiple_edges() G.remove_loops() diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index 55723a07fac..575dce5694e 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -858,7 +858,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if loops is None: loops = True elif loops is False: - u = (u for u,neighb in data.iteritems() if u in neighb).next() + u = next(u for u,neighb in data.iteritems() if u in neighb) raise ValueError("The digraph was built with loops=False but input data has a loop at {}.".format(u)) break if loops is None: loops = False @@ -882,7 +882,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if not loops and any(u in neighb for u,neighb in data.iteritems()): if loops is False: - u = (u for u,neighb in data.iteritems() if u in neighb).next() + u = next(u for u,neighb in data.iteritems() if u in neighb) raise ValueError("The digraph was built with loops=False but input data has a loop at {}.".format(u)) loops = True if loops is None: @@ -892,7 +892,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if not multiedges and any(len(set(neighb)) != len(neighb) for neighb in data.itervalues()): if multiedges is False: - uv = ((u,v) for u,neighb in data.iteritems() for v in neighb if neighb.count(v) > 1).next() + uv = next((u,v) for u,neighb in data.iteritems() for v in neighb if neighb.count(v) > 1) raise ValueError("Non-multidigraph got several edges (%s,%s)"%(u,v)) multiedges = True if multiedges is None: @@ -1712,7 +1712,7 @@ def feedback_edge_set(self, constraint_generation= True, value_only=False, solve sage: g = graphs.RandomGNP(5,.3) sage: dg = DiGraph(g) sage: feedback = dg.feedback_edge_set() - sage: (u,v,l) = g.edge_iterator().next() + sage: (u,v,l) = next(g.edge_iterator()) sage: (u,v) in feedback or (v,u) in feedback True @@ -2195,7 +2195,7 @@ def _all_paths_iterator(self, vertex, ending_vertices=None, sage: g = DiGraph({'a' : ['a', 'b'], 'b' : ['c'], 'c' : ['d'], 'd' : ['c']}, loops=True) sage: pi = g._all_paths_iterator('a') - sage: for _ in range(5): print pi.next() + sage: for _ in range(5): print next(pi) ['a', 'a'] ['a', 'b'] ['a', 'a', 'a'] @@ -2205,7 +2205,7 @@ def _all_paths_iterator(self, vertex, ending_vertices=None, :: sage: pi = g._all_paths_iterator('b') - sage: for _ in range(5): print pi.next() + sage: for _ in range(5): print next(pi) ['b', 'c'] ['b', 'c', 'd'] ['b', 'c', 'd', 'c'] @@ -2227,14 +2227,14 @@ def _all_paths_iterator(self, vertex, ending_vertices=None, It is possible to specify the allowed ending vertices:: sage: pi = g._all_paths_iterator('a', ending_vertices=['c']) - sage: for _ in range(5): print pi.next() + sage: for _ in range(5): print next(pi) ['a', 'b', 'c'] ['a', 'a', 'b', 'c'] ['a', 'a', 'a', 'b', 'c'] ['a', 'b', 'c', 'd', 'c'] ['a', 'a', 'a', 'a', 'b', 'c'] sage: pi = g._all_paths_iterator('a', ending_vertices=['a', 'b']) - sage: for _ in range(5): print pi.next() + sage: for _ in range(5): print next(pi) ['a', 'a'] ['a', 'b'] ['a', 'a', 'a'] @@ -2340,7 +2340,7 @@ def all_paths_iterator(self, starting_vertices=None, ending_vertices=None, sage: g = DiGraph({'a' : ['a', 'b'], 'b' : ['c'], 'c' : ['d'], 'd' : ['c']}, loops=True) sage: pi = g.all_paths_iterator() - sage: for _ in range(7): print pi.next() + sage: for _ in range(7): print next(pi) ['a', 'a'] ['a', 'b'] ['b', 'c'] @@ -2352,14 +2352,14 @@ def all_paths_iterator(self, starting_vertices=None, ending_vertices=None, It is possible to precise the allowed starting and/or ending vertices:: sage: pi = g.all_paths_iterator(starting_vertices=['a']) - sage: for _ in range(5): print pi.next() + sage: for _ in range(5): print next(pi) ['a', 'a'] ['a', 'b'] ['a', 'a', 'a'] ['a', 'a', 'b'] ['a', 'b', 'c'] sage: pi = g.all_paths_iterator(starting_vertices=['a'], ending_vertices=['b']) - sage: for _ in range(5): print pi.next() + sage: for _ in range(5): print next(pi) ['a', 'b'] ['a', 'a', 'b'] ['a', 'a', 'a', 'b'] @@ -2412,7 +2412,7 @@ def all_paths_iterator(self, starting_vertices=None, ending_vertices=None, paths = [] for vi in vertex_iterators.values(): try: - path = vi.next() + path = next(vi) paths.append((len(path), path)) except(StopIteration): pass @@ -2426,7 +2426,7 @@ def all_paths_iterator(self, starting_vertices=None, ending_vertices=None, yield shortest_path # We update the path iterator to its next available path if it exists try: - path = vertex_iterators[shortest_path[0]].next() + path = next(vertex_iterators[shortest_path[0]]) heappush(paths, (len(path), path)) except(StopIteration): pass @@ -2538,14 +2538,14 @@ def _all_cycles_iterator_vertex(self, vertex, starting_vertices=None, simple=Fal sage: g = DiGraph({'a' : ['a', 'b'], 'b' : ['c'], 'c' : ['d'], 'd' : ['c']}, loops=True) sage: it = g._all_cycles_iterator_vertex('a', simple=False, max_length=None) - sage: for i in range(5): print it.next() + sage: for i in range(5): print next(it) ['a', 'a'] ['a', 'a', 'a'] ['a', 'a', 'a', 'a'] ['a', 'a', 'a', 'a', 'a'] ['a', 'a', 'a', 'a', 'a', 'a'] sage: it = g._all_cycles_iterator_vertex('c', simple=False, max_length=None) - sage: for i in range(5): print it.next() + sage: for i in range(5): print next(it) ['c', 'd', 'c'] ['c', 'd', 'c', 'd', 'c'] ['c', 'd', 'c', 'd', 'c', 'd', 'c'] @@ -2553,7 +2553,7 @@ def _all_cycles_iterator_vertex(self, vertex, starting_vertices=None, simple=Fal ['c', 'd', 'c', 'd', 'c', 'd', 'c', 'd', 'c', 'd', 'c'] sage: it = g._all_cycles_iterator_vertex('d', simple=False, max_length=None) - sage: for i in range(5): print it.next() + sage: for i in range(5): print next(it) ['d', 'c', 'd'] ['d', 'c', 'd', 'c', 'd'] ['d', 'c', 'd', 'c', 'd', 'c', 'd'] @@ -2657,7 +2657,7 @@ def all_cycles_iterator(self, starting_vertices=None, simple=False, sage: g = DiGraph({'a' : ['a', 'b'], 'b' : ['c'], 'c' : ['d'], 'd' : ['c']}, loops=True) sage: it = g.all_cycles_iterator() - sage: for _ in range(7): print it.next() + sage: for _ in range(7): print next(it) ['a', 'a'] ['a', 'a', 'a'] ['c', 'd', 'c'] @@ -2681,7 +2681,7 @@ def all_cycles_iterator(self, starting_vertices=None, simple=False, sage: g = DiGraph({'a' : ['a', 'b'], 'b' : ['c'], 'c' : ['d'], 'd' : ['c']}, loops=True) sage: it = g.all_cycles_iterator(starting_vertices=['b', 'c']) - sage: for _ in range(3): print it.next() + sage: for _ in range(3): print next(it) ['c', 'd', 'c'] ['c', 'd', 'c', 'd', 'c'] ['c', 'd', 'c', 'd', 'c', 'd', 'c'] @@ -2741,7 +2741,7 @@ def all_cycles_iterator(self, starting_vertices=None, simple=False, cycles = [] for vi in vertex_iterators.values(): try: - cycle = vi.next() + cycle = next(vi) cycles.append((len(cycle), cycle)) except(StopIteration): pass @@ -2756,7 +2756,7 @@ def all_cycles_iterator(self, starting_vertices=None, simple=False, # We update the cycle iterator to its next available cycle if it # exists try: - cycle = vertex_iterators[shortest_cycle[0]].next() + cycle = next(vertex_iterators[shortest_cycle[0]]) heappush(cycles, (len(cycle), cycle)) except(StopIteration): pass @@ -3235,7 +3235,7 @@ def strongly_connected_components(self): vertices = set(self.vertices()) scc = [] while vertices: - tmp = self.strongly_connected_component_containing_vertex(vertices.__iter__().next()) + tmp = self.strongly_connected_component_containing_vertex(next(vertices.__iter__())) vertices.difference_update(set(tmp)) scc.append(tmp) return scc diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index fcdf32f0622..e2dbaac1d7f 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -485,7 +485,7 @@ def tournaments_nauty(self, n, gen = sp.stdout while True: try: - s = gen.next() + s = next(gen) except StopIteration: raise StopIteration("Exhausted list of graphs from nauty geng") diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 3754b237bbb..c849bb83abb 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -143,8 +143,7 @@ Functions # http://www.gnu.org/licenses/ ############################################################################## -include "sage/data_structures/bitset.pxi" -include "sage/misc/binary_matrix.pxi" +include "sage/data_structures/binary_matrix.pxi" from libc.stdint cimport uint64_t, uint32_t, INT32_MAX, UINT32_MAX from sage.graphs.base.c_graph cimport CGraph from sage.graphs.base.c_graph cimport vertex_label @@ -538,13 +537,16 @@ def is_distance_regular(G, parameters = False): if distance_matrix[i] > diameter and distance_matrix[i] != infinity: diameter = distance_matrix[i] + cdef bitset_t b_tmp + bitset_init(b_tmp, n) + # b_distance_matrix[d*n+v] is the set of vertices at distance d from v. cdef binary_matrix_t b_distance_matrix try: binary_matrix_init(b_distance_matrix,n*(diameter+2),n) - binary_matrix_fill(b_distance_matrix, 0) except MemoryError: sage_free(distance_matrix) + bitset_free(b_tmp) raise # Fills b_distance_matrix @@ -552,8 +554,8 @@ def is_distance_regular(G, parameters = False): for v in range(u,n): d = distance_matrix[u*n+v] if d != infinity: - binary_matrix_set1(b_distance_matrix, d*n+u,v) - binary_matrix_set1(b_distance_matrix, d*n+v,u) + binary_matrix_set1(b_distance_matrix, d*n+u, v) + binary_matrix_set1(b_distance_matrix, d*n+v, u) cdef list bi = [-1 for i in range(diameter +1)] cdef list ci = [-1 for i in range(diameter +1)] @@ -570,11 +572,10 @@ def is_distance_regular(G, parameters = False): # Computations of b_d and c_d for u,v. We intersect sets stored in # b_distance_matrix. - b = 0 - c = 0 - for l in range(b_distance_matrix.width): - b += __builtin_popcountl(b_distance_matrix.rows[(d+1)*n+u][l] & b_distance_matrix.rows[1*n+v][l]) - c += __builtin_popcountl(b_distance_matrix.rows[(d-1)*n+u][l] & b_distance_matrix.rows[1*n+v][l]) + bitset_and(b_tmp, b_distance_matrix.rows[(d+1)*n+u], b_distance_matrix.rows[n+v]) + b = bitset_len(b_tmp) + bitset_and(b_tmp, b_distance_matrix.rows[(d-1)*n+u], b_distance_matrix.rows[n+v]) + c = bitset_len(b_tmp) # Consistency of b_d and c_d if bi[d] == -1: @@ -584,10 +585,12 @@ def is_distance_regular(G, parameters = False): elif bi[d] != b or ci[d] != c: sage_free(distance_matrix) binary_matrix_free(b_distance_matrix) + bitset_free(b_tmp) return False sage_free(distance_matrix) binary_matrix_free(b_distance_matrix) + bitset_free(b_tmp) if parameters: bi[0] = k @@ -1556,7 +1559,8 @@ def floyd_warshall(gg, paths = True, distances = False): prec[v_int][u_int] = v_int # The algorithm itself. - cdef unsigned short *dv, *dw + cdef unsigned short *dv + cdef unsigned short *dw cdef int dvw cdef int val diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 5dbf44f8931..9656217b7f3 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -440,20 +440,6 @@ def RandomHolmeKim(n, m, p, seed=None): import networkx return Graph(networkx.powerlaw_cluster_graph(n, m, p, seed=seed)) -def RandomInterval(n): - """ - :meth:`RandomInterval` is deprecated. Use :meth:`RandomIntervalGraph` instead. - - TEST:: - - sage: g = graphs.RandomInterval(8) - doctest:...: DeprecationWarning: RandomInterval() is deprecated. Use RandomIntervalGraph() instead. - See http://trac.sagemath.org/13283 for details. - """ - from sage.misc.superseded import deprecation - deprecation(13283, "RandomInterval() is deprecated. Use RandomIntervalGraph() instead.") - return RandomIntervalGraph(n) - def RandomIntervalGraph(n): """ Returns a random interval graph. diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index cb63e926c1c..63457f49f0b 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -3923,7 +3923,7 @@ def SylvesterGraph(): True """ g = HoffmanSingletonGraph() - e = g.edge_iterator(labels = False).next() + e = next(g.edge_iterator(labels = False)) g.delete_vertices(g.neighbors(e[0]) + g.neighbors(e[1])) g.relabel() ordering = [0, 1, 2, 4, 5, 9, 16, 35, 15, 18, 20, 30, 22, 6, 33, 32, 14, @@ -3963,7 +3963,7 @@ def SimsGewirtzGraph(): """ g = HigmanSimsGraph() - e = g.edge_iterator(labels = False).next() + e = next(g.edge_iterator(labels = False)) g.delete_vertices(g.neighbors(e[0]) + g.neighbors(e[1])) g.relabel() ordering = [0, 2, 3, 4, 6, 7, 8, 17, 1, 41, 49, 5, 22, 26, 11, 27, 15, 47, diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index ba17c3a8a72..ef9cbc7e562 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -1939,13 +1939,6 @@ def _check_embedding_validity(self, embedding=None): sage: G._check_embedding_validity(d) True - TESTS:: - - sage: G.check_embedding_validity(d) - doctest:...: DeprecationWarning: check_embedding_validity is deprecated. Please use _check_embedding_validity instead. - See http://trac.sagemath.org/15551 for details. - True - """ if embedding is None: embedding = getattr(self, '_embedding', None) @@ -1967,8 +1960,6 @@ def _check_embedding_validity(self, embedding=None): return False return True - check_embedding_validity = deprecated_function_alias(15551, _check_embedding_validity) - def has_loops(self): """ Returns whether there are loops in the (di)graph. @@ -2516,13 +2507,6 @@ def _check_pos_validity(self, pos=None, dim = 2): sage: G = graphs.PetersenGraph() sage: G._check_pos_validity(p) True - - TESTS:: - - sage: G.check_pos_validity(p) - doctest:...: DeprecationWarning: check_pos_validity is deprecated. Please use _check_pos_validity instead. - See http://trac.sagemath.org/15551 for details. - True """ if pos is None: pos = self.get_pos(dim = dim) @@ -2537,8 +2521,6 @@ def _check_pos_validity(self, pos=None, dim = 2): return False return True - check_pos_validity = deprecated_function_alias(15551,_check_pos_validity) - def set_pos(self, pos, dim = 2): """ Sets the position dictionary, a dictionary specifying the @@ -2961,14 +2943,14 @@ def eulerian_orientation(self): if len(odd)>0: v=odd.pop() else: - v=g.edge_iterator(labels=None).next()[0] + v = next(g.edge_iterator(labels=None))[0] odd.append(v) # Stops when there is no edge left while True: # If there is an edge adjacent to the current one if g.degree(v)>0: - e = g.edge_iterator(v).next() + e = next(g.edge_iterator(v)) g.delete_edge(e) if e[0]!=v: e=(e[1],e[0],e[2]) @@ -2984,7 +2966,7 @@ def eulerian_orientation(self): v=odd.pop() # Else jumps to an ever vertex which is not isolated elif g.size()>0: - v=g.edge_iterator().next()[0] + v = next(g.edge_iterator())[0] odd.append(v) # If there is none, we are done ! else: @@ -3100,9 +3082,9 @@ def eulerian_circuit(self, return_vertices=False, labels=True, path=False): edges.append(e if labels else (e[0], e[1])) else: if self.is_directed(): - next_edge = g.outgoing_edge_iterator(v).next() + next_edge = next(g.outgoing_edge_iterator(v)) else: - next_edge = g.edge_iterator(v).next() + next_edge = next(g.edge_iterator(v)) if next_edge[0] == v: # in the undirected case we want to # save the direction of traversal @@ -3197,7 +3179,7 @@ def min_spanning_tree(self, return kruskal(self, wfunction=weight_function, check=check) elif algorithm == "Prim_fringe": if starting_vertex is None: - v = self.vertex_iterator().next() + v = next(self.vertex_iterator()) else: v = starting_vertex tree = set([v]) @@ -3221,7 +3203,7 @@ def min_spanning_tree(self, return edges elif algorithm == "Prim_edge": if starting_vertex is None: - v = self.vertex_iterator().next() + v = next(self.vertex_iterator()) else: v = starting_vertex sorted_edges = sorted(self.edges(), key=weight_function) @@ -3333,7 +3315,7 @@ def spanning_trees_count(self, root_vertex=None): return M2.determinant() else: if root_vertex is None: - root_vertex=self.vertex_iterator().next() + root_vertex=next(self.vertex_iterator()) if root_vertex not in self.vertices(): raise ValueError("Vertex (%s) not in the graph."%root_vertex) @@ -4280,16 +4262,6 @@ def faces(self, embedding = None): Traceback (most recent call last): ... ValueError: No embedding is provided and the graph is not planar. - - TESTS: - - :trac:`15551` deprecated the ``trace_faces`` name:: - - sage: T.trace_faces({0: [1, 3, 2], 1: [0, 2, 3], 2: [0, 3, 1], 3: [0, 1, 2]}) - doctest:...: DeprecationWarning: trace_faces is deprecated. Please use faces instead. - See http://trac.sagemath.org/15551 for details. - [[(0, 1), (1, 2), (2, 0)], [(3, 2), (2, 1), (1, 3)], [(2, 3), (3, 0), (0, 2)], [(0, 3), (3, 1), (1, 0)]] - """ # Which embedding should we use ? if embedding is None: @@ -4336,8 +4308,6 @@ def faces(self, embedding = None): if (len(path) != 0): faces.append(path) return faces - trace_faces = deprecated_function_alias(15551, faces) - ### Connectivity def is_connected(self): @@ -4369,7 +4339,7 @@ def is_connected(self): try: return self._backend.is_connected() except AttributeError: - v = self.vertex_iterator().next() + v = next(self.vertex_iterator()) conn_verts = list(self.depth_first_search(v, ignore_direction=True)) return len(conn_verts) == self.num_verts() @@ -4533,7 +4503,7 @@ def blocks_and_cut_vertices(self): if not self: # empty graph return [],[] - start = self.vertex_iterator().next() # source + start = next(self.vertex_iterator()) # source if len(self) == 1: # only one vertex return [[start]],[] @@ -4575,7 +4545,7 @@ def blocks_and_cut_vertices(self): try: # We consider the next of its neighbors - w = neighbors[v].next() + w = next(neighbors[v]) # If we never met w before, we remember the direction of edge # vw, and add w to the stack. @@ -4838,7 +4808,7 @@ def is_cut_vertex(self, u, weak=False): return False neighbors_func = [self.neighbor_iterator] - start = self.neighbor_iterator(u).next() + start = next(self.neighbor_iterator(u)) CC = set(self.vertex_iterator()) else: @@ -4856,7 +4826,7 @@ def is_cut_vertex(self, u, weak=False): # in the reverse order. If both allow to reach all neighbors of u, # then u is not a cut vertex neighbors_func = [self.neighbor_out_iterator, self.neighbor_in_iterator] - start = self.neighbor_out_iterator(u).next() + start = next(self.neighbor_out_iterator(u)) CC.discard(u) CC.discard(start) @@ -5147,7 +5117,7 @@ def edge_disjoint_spanning_trees(self,k, root=None, solver = None, verbose = 0): edges = p.new_variable(binary=True) if root is None: - root = self.vertex_iterator().next() + root = next(self.vertex_iterator()) # r_edges is a relaxed variable grater than edges. It is used to # check the presence of cycles @@ -5969,6 +5939,11 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: g.longest_path(algorithm="backtrack").edges() [(0, 1, None), (1, 2, None), (2, 3, None), (3, 4, None), (4, 9, None), (5, 7, None), (5, 8, None), (6, 8, None), (6, 9, None)] + .. PLOT:: + + g = graphs.PetersenGraph() + sphinx_plot(g.plot(edge_colors={"red":g.longest_path().edges()})) + Let us compute longest paths on random graphs with random weights. Each time, we ensure the resulting graph is indeed a path:: @@ -6725,7 +6700,7 @@ def traveling_salesman_problem(self, use_edge_labels = False, solver = None, con r = p.new_variable(nonnegative=True) eps = 1/(2*Integer(g.order())) - x = g.vertex_iterator().next() + x = next(g.vertex_iterator()) if g.is_directed(): @@ -7003,7 +6978,7 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, constrai sage: feedback = dcycle.feedback_vertex_set() sage: len(feedback) 3 - sage: (u,v,l) = cycle.edge_iterator().next() + sage: (u,v,l) = next(cycle.edge_iterator()) sage: u in feedback or v in feedback True @@ -8678,8 +8653,8 @@ def random_vertex(self, **kwds): from sage.misc.prandom import randint it = self.vertex_iterator(**kwds) for i in xrange(0, randint(0, self.order() - 1)): - it.next() - return it.next() + next(it) + return next(it) def random_edge(self,**kwds): r""" @@ -8709,8 +8684,8 @@ def random_edge(self,**kwds): from sage.misc.prandom import randint it = self.edge_iterator(**kwds) for i in xrange(0, randint(0, self.size() - 1)): - it.next() - return it.next() + next(it) + return next(it) def vertex_boundary(self, vertices1, vertices2=None): """ @@ -9253,7 +9228,7 @@ def add_edges(self, edges): it = iter(edges) try: - e0 = it.next() + e0 = next(it) except StopIteration: return @@ -10268,7 +10243,7 @@ def degree(self, vertices=None, labels=False): if labels: return dict(self.degree_iterator(vertices,labels)) elif vertices in self and not labels: - return self.degree_iterator(vertices,labels).next() + return next(self.degree_iterator(vertices,labels)) else: return list(self.degree_iterator(vertices,labels)) @@ -10448,7 +10423,7 @@ def is_regular(self, k = None): 9-regular. In fact, we can now find the degree easily as follows:: - sage: G.degree_iterator().next() + sage: next(G.degree_iterator()) 7 The house graph is not regular:: @@ -10466,7 +10441,7 @@ def is_regular(self, k = None): deg_it = self.degree_iterator() if k is None: - k = deg_it.next() + k = next(deg_it) for d in deg_it: if d != k: @@ -10891,11 +10866,16 @@ def _subgraph_by_deleting(self, vertices=None, edges=None, inplace=False, [3, 4, 5] sage: h.get_vertices() {3: 'v3', 4: 'v4', 5: 'v5'} + + :trac:`17683`:: + + sage: graphs.PetersenGraph().copy(immutable=True).subgraph([1,2]) + Subgraph of (Petersen graph): Graph on 2 vertices """ if inplace: G = self else: - G = self.copy() + G = self.copy(immutable=False) G.name("Subgraph of (%s)"%self.name()) G.delete_vertices([v for v in G if v not in vertices]) @@ -10922,6 +10902,8 @@ def _subgraph_by_deleting(self, vertices=None, edges=None, inplace=False, G.delete_edges(edges_to_delete) if not inplace: + if getattr(self, '_immutable', False): + return G.copy(immutable=True) return G def subgraph_search(self, G, induced=False): @@ -11428,7 +11410,7 @@ def is_chordal(self, certificate = False, algorithm = "B"): g.delete_vertex(v) continue - x = t_peo.neighbor_out_iterator(v).next() + x = next(t_peo.neighbor_out_iterator(v)) S = self.neighbors(x)+[x] if not frozenset(g.neighbors(v)).issubset(S): @@ -11474,7 +11456,7 @@ def is_chordal(self, certificate = False, algorithm = "B"): if (t_peo.out_degree(v)>0 and not frozenset([v1 for v1 in g.neighbors(v) if pos_in_peo[v1] > pos_in_peo[v]]).issubset( - neighbors_subsets[t_peo.neighbor_out_iterator(v).next()])): + neighbors_subsets[next(t_peo.neighbor_out_iterator(v))])): # Do we need to return a hole ? if certificate: @@ -11712,13 +11694,21 @@ def is_interval(self, certificate = False): sage: g2.is_isomorphic(g) True + Enumerate all small interval graphs:: + + sage: n = 8 + sage: count = [0]*(n+1) + sage: for g in graphs(n, augment='vertices',property= lambda x:x.is_interval()): # not tested -- 50s + ....: count[g.order()] += 1 # not tested -- 50s + sage: count # not tested -- 50s + [1, 1, 2, 4, 10, 27, 92, 369, 1807] + .. SEEALSO:: - :mod:`Interval Graph Recognition `. - :meth:`PQ ` -- Implementation of PQ-Trees. - """ self._scream_if_not_simple() @@ -11747,8 +11737,6 @@ def is_interval(self, certificate = False): peo = cc.lex_BFS() - - while peo: v = peo.pop() clique = frozenset( [v] + cc.neighbors(v)) @@ -12599,7 +12587,7 @@ def girth(self): 5 sage: graphs.HeawoodGraph().girth() 6 - sage: graphs.trees(9).next().girth() + sage: next(graphs.trees(9)).girth() +Infinity @@ -12897,7 +12885,7 @@ def all_paths(self, start, end): s=None while (s is None) and not done: try: - s=act_path_iter[-1].next() # try to get the next neighbor/successor, ... + s=next(act_path_iter[-1]) # try to get the next neighbor/successor, ... except (StopIteration): # ... if there is none ... act_path.pop() # ... go one step back act_path_iter.pop() diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx index 3ed96a1958f..042e7da37f1 100644 --- a/src/sage/graphs/generic_graph_pyx.pyx +++ b/src/sage/graphs/generic_graph_pyx.pyx @@ -18,7 +18,7 @@ AUTHORS: include "sage/ext/interrupt.pxi" include 'sage/ext/cdefs.pxi' include 'sage/ext/stdsage.pxi' -include "sage/misc/binary_matrix.pxi" +include "sage/data_structures/binary_matrix.pxi" # import from Python standard library from sage.misc.prandom import random @@ -1315,14 +1315,12 @@ def transitive_reduction_acyclic(G): # A point is reachable from u if it is one of its neighbours, or if it is # reachable from one of its neighbours. binary_matrix_init(closure, n, n) - binary_matrix_fill(closure, 0) for uu in linear_extension: u = v_to_int[uu] for vv in G.neighbors_out(uu): v = v_to_int[vv] binary_matrix_set1(closure, u, v) - for i in range(closure.width): - closure.rows[u][i] |= closure.rows[v][i] + bitset_or(closure.rows[u], closure.rows[u], closure.rows[v]) # Build the transitive reduction of G # @@ -1334,8 +1332,7 @@ def transitive_reduction_acyclic(G): u = v_to_int[uu] for vv in G.neighbors_out(uu): v = v_to_int[vv] - for i in range(closure.width): - closure.rows[u][i] &= ~closure.rows[v][i] + bitset_difference(closure.rows[u], closure.rows[u], closure.rows[v]) for vv in G.neighbors_out(uu): v = v_to_int[vv] if binary_matrix_get(closure, u, v): diff --git a/src/sage/graphs/genus.pyx b/src/sage/graphs/genus.pyx index 990e6db0c4e..b2b04ec6dbc 100644 --- a/src/sage/graphs/genus.pyx +++ b/src/sage/graphs/genus.pyx @@ -199,7 +199,8 @@ cdef class simple_connected_genus_backtracker: """ cdef int i,j,du,dv,u,v - cdef int *w, *s + cdef int *w + cdef int *s # set this to prevent segfaulting on dealloc in case anything goes wrong. self.visited = NULL @@ -330,7 +331,8 @@ cdef class simple_connected_genus_backtracker: """ - cdef int i,j, v, *w + cdef int i, j, v + cdef int *w cdef int *face_map = self.face_freeze cdef list darts_to_verts diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 7e87ecb4767..4b510b0d6b1 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -1452,7 +1452,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if not loops and any(u in neighb for u,neighb in data.iteritems()): if loops is False: - u = (u for u,neighb in data.iteritems() if u in neighb).next() + u = next(u for u,neighb in data.iteritems() if u in neighb) raise ValueError("The graph was built with loops=False but input data has a loop at {}.".format(u)) loops = True if loops is None: @@ -1486,7 +1486,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, if loops is None: loops = True elif loops is False: - u = (u for u,neighb in data.iteritems() if u in neighb).next() + u = next(u for u,neighb in data.iteritems() if u in neighb) raise ValueError("The graph was built with loops=False but input data has a loop at {}.".format(u)) break if loops is None: @@ -1495,7 +1495,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, for u in data: if len(set(data[u])) != len(data[u]): if multiedges is False: - v = (v for v in data[u] if data[u].count(v) > 1).next() + v = next((v for v in data[u] if data[u].count(v) > 1)) raise ValueError("Non-multigraph got several edges (%s,%s)"%(u,v)) if multiedges is None: multiedges = True @@ -1664,7 +1664,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, elif format == 'elliptic_curve_congruence': from sage.rings.arith import lcm, prime_divisors from sage.rings.fast_arith import prime_range - from sage.misc.misc import prod + from sage.misc.all import prod for i in xrange(self.order()): for j in xrange(i): E = curves[i] @@ -2044,7 +2044,7 @@ def vertices_to_edges(x): # graph. We *know* it exists as there are too many edges around. n = self.order() seen = {} - u = self.vertex_iterator().next() + u = next(self.vertex_iterator()) seen[u] = u stack = [(u, v) for v in self.neighbor_iterator(u)] while stack: @@ -3094,7 +3094,7 @@ def is_edge_transitive(self): return True A = self.automorphism_group() - e = self.edge_iterator(labels=False).next() + e = next(self.edge_iterator(labels=False)) e = [A._domain_to_gap[e[0]], A._domain_to_gap[e[1]]] return gap("OrbitLength("+str(A._gap_())+",Set(" + str(e) + "),OnSets);") == self.size() @@ -3136,7 +3136,7 @@ def is_arc_transitive(self): return True A = self.automorphism_group() - e = self.edge_iterator(labels=False).next() + e = next(self.edge_iterator(labels=False)) e = [A._domain_to_gap[e[0]], A._domain_to_gap[e[1]]] return gap("OrbitLength("+str(A._gap_())+",Set(" + str(e) + "),OnTuples);") == 2*self.size() @@ -3386,7 +3386,7 @@ def strong_orientation(self): # in which it has been used. All the other edges are oriented # backward - v = self.vertex_iterator().next() + v = next(self.vertex_iterator()) seen = {} i=1 @@ -3394,17 +3394,17 @@ def strong_orientation(self): seen[v] = i # indicates the stack of edges to explore - next = self.edges_incident(v) + next_ = self.edges_incident(v) - while next: - e = next.pop(-1) + while next_: + e = next_.pop(-1) # We assume e[0] to be a `seen` vertex e = e if seen.get(e[0],False) != False else (e[1],e[0],e[2]) # If we discovered a new vertex if seen.get(e[1],False) == False: d.add_edge(e) - next.extend([ee for ee in self.edges_incident(e[1]) if (((e[0],e[1]) != (ee[0],ee[1])) and ((e[0],e[1]) != (ee[1],ee[0])))]) + next_.extend([ee for ee in self.edges_incident(e[1]) if (((e[0],e[1]) != (ee[0],ee[1])) and ((e[0],e[1]) != (ee[1],ee[0])))]) i+=1 seen[e[1]]=i @@ -3892,6 +3892,11 @@ def coloring(self, algorithm="DLX", hex_colors=False, verbose = 0): sage: G.plot(vertex_colors=H) Graphics object consisting of 16 graphics primitives + .. PLOT:: + + g = Graph("Fooba") + sphinx_plot(g.plot(partition=g.coloring())) + TESTS:: sage: G.coloring(algorithm="foo") @@ -3980,6 +3985,11 @@ def matching(self, value_only=False, algorithm="Edmonds", use_edge_labels=True, sage: g.matching(algorithm="LP", value_only=True) 9.0 + .. PLOT:: + + g = graphs.PappusGraph() + sphinx_plot(g.plot(edge_colors={"red":g.matching()})) + TESTS: If ``algorithm`` is set to anything different from ``"Edmonds"`` or @@ -5698,6 +5708,11 @@ def independent_set(self, algorithm = "Cliquer", value_only = False, reduction_r sage: C = graphs.PetersenGraph() sage: len(C.independent_set(algorithm = "MILP")) 4 + + .. PLOT:: + + g = graphs.PetersenGraph() + sphinx_plot(g.plot(partition=[g.independent_set()])) """ my_cover = self.vertex_cover(algorithm=algorithm, value_only=value_only, reduction_rules=reduction_rules, solver=solver, verbosity=verbosity) if value_only: @@ -5774,6 +5789,11 @@ def vertex_cover(self, algorithm = "Cliquer", value_only = False, sage: g.vertex_cover(value_only=True) 9 + .. PLOT:: + + g = graphs.PappusGraph() + sphinx_plot(g.plot(partition=[g.vertex_cover()])) + TESTS: The two algorithms should return the same result:: @@ -6606,7 +6626,7 @@ def _gomory_hu_tree(self, vertices=None, method="FF"): g = g1_tree.union(g2_tree) # An edge to connect them, with the appropriate label - g.add_edge(g1_tree.vertex_iterator().next(), g2_tree.vertex_iterator().next(), flow) + g.add_edge(next(g1_tree.vertex_iterator()), next(g2_tree.vertex_iterator()), flow) if pos: g.set_pos(pos) diff --git a/src/sage/graphs/graph_coloring.py b/src/sage/graphs/graph_coloring.py index 6d74d61aaa8..ecbc022fb56 100644 --- a/src/sage/graphs/graph_coloring.py +++ b/src/sage/graphs/graph_coloring.py @@ -530,7 +530,7 @@ class :class:`MixedIntegerLinearProgram # The first vertex is colored with 1. It costs nothing to say # it, and it can help. - p.add_constraint(color[g.vertex_iterator().next(),0], max=1, min=1) + p.add_constraint(color[next(g.vertex_iterator()),0], max=1, min=1) try: if value_only: @@ -1031,7 +1031,7 @@ class :class:`MixedIntegerLinearProgram [p.add_constraint(p.sum([color[R(e),i] for i in xrange(k)]), max=1, min=1) for e in g.edge_iterator(labels=False)] # anything is good as an objective value as long as it is satisfiable - e = g.edge_iterator(labels=False).next() + e = next(g.edge_iterator(labels=False)) p.set_objective(color[R(e),0]) try: if value_only: diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index 49dbf69f404..c6889ab9fc7 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -51,7 +51,7 @@ from sage.rings.integer import Integer from sqlite3 import dbapi2 as sqlite # if anyone would like to explain why dbapi2... from sage.databases.sql_db import SQLDatabase, SQLQuery -from sage.misc.misc import SAGE_SHARE +from sage.env import SAGE_SHARE from sage.graphs.graph import Graph dblocation = os.path.join(SAGE_SHARE,'graphs','graphs.db') @@ -498,7 +498,7 @@ def query_iterator(self): sage: Q = GraphQuery(display_cols=['graph6'],num_vertices=7, diameter=5) sage: it = iter(Q) sage: while True: - ... try: print it.next().graph6_string() + ... try: print next(it).graph6_string() ... except StopIteration: break F?`po F?gqg diff --git a/src/sage/graphs/graph_decompositions/vertex_separation.pyx b/src/sage/graphs/graph_decompositions/vertex_separation.pyx index d1efc0ecbbd..e64bab3fd7d 100644 --- a/src/sage/graphs/graph_decompositions/vertex_separation.pyx +++ b/src/sage/graphs/graph_decompositions/vertex_separation.pyx @@ -41,6 +41,7 @@ This is a result of Kinnersley [Kin92]_ and Bodlaender [Bod98]_. :meth:`path_decomposition` | Returns the pathwidth of the given graph and the ordering of the vertices resulting in a corresponding path decomposition :meth:`vertex_separation` | Returns an optimal ordering of the vertices and its cost for vertex-separation :meth:`vertex_separation_MILP` | Computes the vertex separation of `G` and the optimal ordering of its vertices using an MILP formulation + :meth:`vertex_separation_BAB` | Computes the vertex separation of `G` and the optimal ordering of its vertices using a branch and bound algorithm :meth:`lower_bound` | Returns a lower bound on the vertex separation of `G` :meth:`is_valid_ordering` | Test if the linear vertex ordering `L` is valid for (di)graph `G` :meth:`width_of_path_decomposition` | Returns the width of the path decomposition induced by the linear ordering `L` of the vertices of `G` @@ -168,6 +169,58 @@ The vertex separation of `G` is given by the value of `z`, and the order of vertex `v` in the optimal layout is given by the smallest `t` for which `y_v^t==1`. + +Branch and Bound algorithm for the vertex separation +---------------------------------------------------- + +We describe below the principle of a branch and bound algorithm (BAB) for +determining an optimal ordering for the vertex separation of `G`, as proposed in +[CMN14]_. + +**Greedy steps:** + +Let us denote `{\cal L}(S)` the set of all possible orderings of the vertices in +`S`, and let `{\cal L}_P(S)\subseteq {\cal L}(S)` be the orderings starting with +a prefix `P`. Let also `c(L)` be the cost of the ordering `L\in{\cal L}(V)` as +defined above. + +Given a digraph `D=(V,A)`, a set `S\subset V`, and a prefix `P`, it has been +proved in [CMN14]_ that `\min_{L\in{\cal L}_P(V)} c(L) = \min_{L\in{\cal +L}_{P+v}(V)} c(L)` holds in two (non exhaustive) cases: + +.. MATH:: + + \text{or} \begin{cases} + N^+(v)\subseteq S\cup N^+(S)\\ + v\in N^+(S)\text{ and }N^+(v)\setminus(S\cup N^+(S)) = \{w\} + \end{cases} + +In other words, if we find a vertex `v` satisfying above conditions, the best +possible ordering with prefix `P` has the same cost as the best possible +ordering with prefix `P+v`. So we can greedily extend the prefix with vertices +satisfying the conditions which results in a significant reduction of the search +space. + +**The algorithm:** + +Given the current prefix `P` and the current upper bound `UB` (either an input +upper bound or the cost of the best solution found so far), apply the following +steps: + +- Extend the prefix `P` into a prefix `P'` using the greedy steps as described + above. + +- Sort the vertices `v\in V\setminus P'` by increasing values of `|N^+(P+v)|`, + and prune the vertices with a value larger or equal to `UB`. Let `\Delta` be + the resulting sorted list. + +- Repeat with prefix `P'+v` for all `v\in\Delta` and keep the best found + solution. + +If a lower bound is passed to the algorithm, it will stop as soon as a solution +with cost equal to that lower bound is found. + + REFERENCES ---------- @@ -181,6 +234,11 @@ REFERENCES Michal Pioro, IEEE/OSA Journal of Optical Communication and Networking 2(12):1010-1021, 2010. +.. [CMN14] *Experimental Evaluation of a Branch and Bound Algorithm for + computing Pathwidth*, David Coudert, Dorian Mazauric, and Nicolas Nisse. In + Symposium on Experimental Algorithms (SEA), volume 8504 of LNCS, Copenhagen, + Denmark, pages 46-58, June 2014, + http://hal.inria.fr/hal-00943549/document AUTHORS ------- @@ -189,6 +247,7 @@ AUTHORS - David Coudert (2012-04): MILP formulation and tests functions +- David Coudert (2015-01): BAB formulation and tests functions METHODS @@ -200,6 +259,8 @@ include 'sage/ext/cdefs.pxi' include 'sage/ext/interrupt.pxi' include 'fast_digraph.pyx' from libc.stdint cimport uint8_t, int8_t +include "sage/data_structures/binary_matrix.pxi" +from sage.graphs.base.static_dense_graph cimport dense_graph_init #***************************************************************************** # Copyright (C) 2011 Nathann Cohen @@ -890,3 +951,405 @@ def vertex_separation_MILP(G, integrality = False, solver = None, verbosity = 0) vs = int(round( tabz['z'] )) return vs, seq + + +########################################## +# Branch and Bound for vertex separation # +########################################## + +def vertex_separation_BAB(G, cut_off=None, upper_bound=None): + r""" + Branch and Bound algorithm for the vertex separation. + + This method implements the branch and bound algorithm for the vertex + separation of directed graphs and the pathwidth of undirected graphs + proposed in [CMN14]_. The implementation is valid for both Graph and + DiGraph. See the documentation of the + :mod:`~sage.graphs.graph_decompositions.vertex_separation` module. + + INPUTS: + + - ``G`` -- a Graph or a DiGraph. + + - ``cut_off`` -- (default: None) bound to consider in the branch and bound + algorithm. This allows us to stop the search as soon as a solution with + width at most ``cut_off`` is found, if any. If this bound cannot be + reached, the best solution found is returned, unless a too low + ``upper_bound`` is given. + + - ``upper_bound`` -- (default: None) if specified, the algorithm searches + for a solution with ``width < upper_bound``. It helps cutting branches. + However, if the given upper bound is too low, the algorithm may not be + able to find a solution. + + OUTPUTS: + + - ``width`` -- the computed vertex separation + + - ``seq`` -- an ordering of the vertices of width ``width``. + + + EXAMPLES: + + The algorithm is valid for the vertex separation:: + + sage: from sage.graphs.graph_decompositions import vertex_separation as VS + sage: D = digraphs.RandomDirectedGNP(15, .2) + sage: vb, seqb = VS.vertex_separation_BAB(D) + sage: vd, seqd = VS.vertex_separation(D) + sage: vb == vd + True + sage: vb == VS.width_of_path_decomposition(D, seqb) + True + + The vertex separation of a `N\times N` grid is `N`:: + + sage: from sage.graphs.graph_decompositions import vertex_separation as VS + sage: G = graphs.Grid2dGraph(4,4) + sage: vs, seq = VS.vertex_separation_BAB(G); vs + 4 + sage: vs == VS.width_of_path_decomposition(G, seq) + True + + The vertex separation of a `N\times M` grid with `N Allocate and initialize some data structures + + # We use a binary matrix to store the (di)graph. This way the neighborhoud + # of a vertex is stored in one bitset. + cdef binary_matrix_t H + cdef dict vertex_to_int = dense_graph_init(H, G, translation = True) + cdef int i + cdef dict int_to_vertex = dict((i, v) for v,i in vertex_to_int.iteritems()) + + # We need 2 bitsets here + 3 per call to vertex_separation_BAB_C, so overall + # 3*n + 2. We use another binary matrix as a pool of bitsets. + cdef binary_matrix_t bm_pool + binary_matrix_init(bm_pool, 3*n+2, n) + + cdef int * prefix = sage_malloc(n * sizeof(int)) + cdef int * positions = sage_malloc(n * sizeof(int)) + if prefix==NULL or positions==NULL: + sage_free(prefix) + sage_free(positions) + binary_matrix_free(H) + binary_matrix_free(bm_pool) + raise MemoryError("Unable to allocate data strutures.") + + cdef list best_seq = range(n) + for i in range(n): + prefix[i] = i + positions[i] = i + + cdef int width = upper_bound + cdef list order = list() + + try: + # ==> Call the cython method + sig_on() + width = vertex_separation_BAB_C(H = H, + n = n, + prefix = prefix, + positions = positions, + best_seq = best_seq, + level = 0, + b_prefix = bm_pool.rows[3*n], + b_prefix_and_neighborhood = bm_pool.rows[3*n+1], + cut_off = cut_off, + upper_bound = upper_bound, + current_cost = 0, + bm_pool = bm_pool ) + + sig_off() + + # ==> Build the final ordering + order = [int_to_vertex[best_seq[i]] for i in range(n)] + + finally: + sage_free(prefix) + sage_free(positions) + binary_matrix_free(H) + binary_matrix_free(bm_pool) + + return (width if width Test termination + + if level==n: + if current_cost < upper_bound: + for i in range(n): + best_seq[i] = prefix[i] + + return current_cost + + cdef int delta_i, j, v, select_it + cdef list delta = list() + cdef int loc_level = level + + # ==> Allocate local data structures + + cdef bitset_s *loc_b_prefix = bm_pool.rows[3*level] + cdef bitset_s *loc_b_pref_and_neigh = bm_pool.rows[3*level+1] + cdef bitset_s *b_tmp = bm_pool.rows[3*level+2] + bitset_copy(loc_b_prefix, b_prefix) + bitset_copy(loc_b_pref_and_neigh, b_prefix_and_neighborhood) + + # ==> Greedy steps + # + # We extend the current prefix with all vertices u such that either + # (i) All out-neighbors of u are in the prefix or in its out-neighborhood + # (ii) or u is an out-neighbor of the prefix and all but one of its + # out-neighbors are in the prefix or in its out-neighborhood. + + select_it = 0 + i = loc_level + while i Test termination + # + if loc_level==n: + if current_cost < upper_bound: + for i in range(n): + best_seq[i] = prefix[i] + + return current_cost + + + # ==> Sort and Prune + # + # We compute for each remaining vertex v a lower bound on the width of any + # ordering with prefix prefix+v + for i from loc_level <= i < n: + j = prefix[i] + bitset_union(b_tmp, loc_b_pref_and_neigh, H.rows[j]) + bitset_difference(b_tmp, b_tmp, loc_b_prefix) + bitset_discard(b_tmp, j) + delta_i = bitset_len(b_tmp) + if delta_i < upper_bound: + delta.append( (delta_i, j) ) + + delta.sort() + + + # ==> Recursion + + for delta_i, i in delta: + + delta_i = max(current_cost, delta_i) + + if delta_i >= upper_bound: + break + + # We extend the current prefix with vertex i and explore the branch + bitset_union(b_tmp, loc_b_pref_and_neigh, H.rows[i]) + bitset_discard(b_tmp, i) + _my_invert_positions(prefix, positions, positions[i], loc_level) + bitset_add(loc_b_prefix, i) + + cost_i = vertex_separation_BAB_C(H = H, + n = n, + prefix = prefix, + positions = positions, + best_seq = best_seq, + level = loc_level+1, + b_prefix = loc_b_prefix, + b_prefix_and_neighborhood = b_tmp, + cut_off = cut_off, + upper_bound = upper_bound, + current_cost = delta_i, + bm_pool = bm_pool ) + + bitset_discard(loc_b_prefix, i) + + if cost_i < upper_bound: + upper_bound = cost_i + if upper_bound <= cut_off: + # We are satisfied with current solution. + break + + return upper_bound diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index b6c4df81ba6..ada4cd179bc 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -623,7 +623,7 @@ class GraphGenerators(): ########################################################################### def __call__(self, vertices=None, property=lambda x: True, augment='edges', - size=None, deg_seq=None, degree_sequence=None, loops=False, implementation='c_graph', + size=None, degree_sequence=None, loops=False, implementation='c_graph', sparse=True, copy = True): """ Accesses the generator of isomorphism class representatives. @@ -673,12 +673,6 @@ def __call__(self, vertices=None, property=lambda x: True, augment='edges', from sage.misc.superseded import deprecation from copy import copy as copyfun - if deg_seq is not None: - deprecation(11927, "The argument name deg_seq is deprecated. It will be " - "removed in a future release of Sage. So, please use " - "degree_sequence instead.") - if degree_sequence is None: - degree_sequence=deg_seq if degree_sequence is not None: if vertices is None: raise NotImplementedError @@ -798,11 +792,11 @@ def nauty_geng(self, options="", debug=False): to contain it. :: sage: gen = graphs.nauty_geng("2") # optional nauty - sage: gen.next() # optional nauty + sage: next(gen) # optional nauty Graph on 2 vertices - sage: gen.next() # optional nauty + sage: next(gen) # optional nauty Graph on 2 vertices - sage: gen.next() # optional nauty + sage: next(gen) # optional nauty Traceback (most recent call last): ... StopIteration: Exhausted list of graphs from nauty geng @@ -828,7 +822,7 @@ def nauty_geng(self, options="", debug=False): successful initiation. :: sage: gen = graphs.nauty_geng("4", debug=True) # optional nauty - sage: print gen.next() # optional nauty + sage: print next(gen) # optional nauty >A nauty-geng -d0D3 n=4 e=0-6 """ import subprocess @@ -843,7 +837,7 @@ def nauty_geng(self, options="", debug=False): gen = sp.stdout while True: try: - s = gen.next() + s = next(gen) except StopIteration: raise StopIteration("Exhausted list of graphs from nauty geng") G = graph.Graph(s[:-1], format='graph6') @@ -1100,9 +1094,9 @@ def fullerenes(self, order, ipr=False): Buckminster Fullerene: :: sage: gen = graphs.fullerenes(60, ipr=True) # optional buckygen - sage: gen.next() # optional buckygen + sage: next(gen) # optional buckygen Graph on 60 vertices - sage: gen.next() # optional buckygen + sage: next(gen) # optional buckygen Traceback (most recent call last): ... StopIteration @@ -1111,7 +1105,7 @@ def fullerenes(self, order, ipr=False): graph. :: sage: gen = graphs.fullerenes(20) # optional buckygen - sage: g = gen.next() # optional buckygen + sage: g = next(gen) # optional buckygen sage: g.is_isomorphic(graphs.DodecahedralGraph()) # optional buckygen True sage: g.get_embedding() # optional buckygen @@ -1209,9 +1203,9 @@ def fusenes(self, hexagon_count, benzenoids=False): a graph on just 10 vertices: :: sage: gen = graphs.fusenes(2) # optional benzene - sage: gen.next() # optional benzene + sage: next(gen) # optional benzene Graph on 10 vertices - sage: gen.next() # optional benzene + sage: next(gen) # optional benzene Traceback (most recent call last): ... StopIteration @@ -1495,7 +1489,7 @@ def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, graph. :: sage: gen = graphs.triangulations(6, only_eulerian=True) # optional plantri - sage: g = gen.next() # optional plantri + sage: g = next(gen) # optional plantri sage: g.is_isomorphic(graphs.OctahedralGraph()) # optional plantri True @@ -1519,7 +1513,7 @@ def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, The minimum connectivity can be at most the minimum degree:: - sage: gen = graphs.triangulations(10, minimum_degree=3, minimum_connectivity=5).next() # optional plantri + sage: gen = next(graphs.triangulations(10, minimum_degree=3, minimum_connectivity=5)) # optional plantri Traceback (most recent call last): ... ValueError: Minimum connectivity can be at most the minimum degree. @@ -1646,10 +1640,10 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None The cube is the only 3-connected planar quadrangulation on 8 vertices:: sage: gen = graphs.quadrangulations(8, minimum_connectivity=3) # optional plantri - sage: g = gen.next() # optional plantri + sage: g = next(gen) # optional plantri sage: g.is_isomorphic(graphs.CubeGraph(3)) # optional plantri True - sage: gen.next() # optional plantri + sage: next(gen) # optional plantri Traceback (most recent call last): ... StopIteration @@ -1908,7 +1902,6 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None RandomGNM = staticmethod(sage.graphs.generators.random.RandomGNM) RandomGNP = staticmethod(sage.graphs.generators.random.RandomGNP) RandomHolmeKim = staticmethod(sage.graphs.generators.random.RandomHolmeKim) - RandomInterval = staticmethod(sage.graphs.generators.random.RandomInterval) # deprecated RandomIntervalGraph = staticmethod(sage.graphs.generators.random.RandomIntervalGraph) RandomLobster = staticmethod(sage.graphs.generators.random.RandomLobster) RandomNewmanWattsStrogatz = staticmethod(sage.graphs.generators.random.RandomNewmanWattsStrogatz) diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py index 79f25372b86..a98c86cbd21 100644 --- a/src/sage/graphs/hypergraph_generators.py +++ b/src/sage/graphs/hypergraph_generators.py @@ -91,14 +91,14 @@ def nauty(self, number_of_sets, number_of_vertices, The Fano Plane, as the only 3-uniform hypergraph with 7 sets and 7 vertices:: - sage: fano = hypergraphs.nauty(7,7, uniform = 3, max_intersection =1).next() # optional - nauty + sage: fano = next(hypergraphs.nauty(7, 7, uniform=3, max_intersection=1)) # optional - nauty sage: print fano # optional - nauty ((0, 1, 2), (0, 3, 4), (0, 5, 6), (1, 3, 5), (2, 4, 5), (2, 3, 6), (1, 4, 6)) The Fano Plane, as the only 3-regular hypergraph with 7 sets and 7 vertices:: - sage: fano = hypergraphs.nauty(7,7, regular = 3, max_intersection =1).next() # optional - nauty + sage: fano = next(hypergraphs.nauty(7, 7, regular=3, max_intersection=1)) # optional - nauty sage: print fano # optional - nauty ((0, 1, 2), (0, 3, 4), (0, 5, 6), (1, 3, 5), (2, 4, 5), (2, 3, 6), (1, 4, 6)) """ @@ -150,7 +150,7 @@ def nauty(self, number_of_sets, number_of_vertices, total = number_of_sets + number_of_vertices while True: try: - s = gen.next() + s = next(gen) except StopIteration: raise StopIteration("Exhausted list of graphs from nauty geng") diff --git a/src/sage/graphs/independent_sets.pxd b/src/sage/graphs/independent_sets.pxd index f8d6a4432e4..1ccf3837af1 100644 --- a/src/sage/graphs/independent_sets.pxd +++ b/src/sage/graphs/independent_sets.pxd @@ -1,5 +1,6 @@ from libc.stdint cimport uint32_t, uint64_t -include "sage/misc/binary_matrix.pxi" +from sage.data_structures.binary_matrix cimport * + cdef class IndependentSets: cdef binary_matrix_t g diff --git a/src/sage/graphs/independent_sets.pyx b/src/sage/graphs/independent_sets.pyx index 5dd49d24891..033c30a0b56 100644 --- a/src/sage/graphs/independent_sets.pyx +++ b/src/sage/graphs/independent_sets.pyx @@ -15,25 +15,15 @@ Classes and methods """ -include "sage/data_structures/bitset.pxi" +include "sage/data_structures/binary_matrix.pxi" from sage.misc.cachefunc import cached_method from sage.graphs.base.static_dense_graph cimport dense_graph_init -cdef inline bint bitset_are_disjoint(mp_limb_t* b1, mp_limb_t* b2, mp_size_t width): - r""" - Tests whether two bitsets of length width*sizeof(unsigned int) have an empty - intersection. - """ - cdef mp_size_t i - for i in range(width): - if b1[i]&b2[i]: - return False - return True cdef inline int ismaximal(binary_matrix_t g, int n, bitset_t s): cdef int i for i in range(n): - if (not bitset_in(s,i)) and bitset_are_disjoint((g.rows[i]), s.bits, g.width): + if (not bitset_in(s,i)) and bitset_are_disjoint(g.rows[i], s): return False return True @@ -245,7 +235,7 @@ cdef class IndependentSets: if bitset_in(current_set,i): # We have found an independent set ! - if bitset_are_disjoint((self.g.rows[i]), current_set.bits, self.g.width): + if bitset_are_disjoint(self.g.rows[i], current_set): # Saving that set bitset_copy(tmp, current_set) @@ -391,7 +381,7 @@ cdef class IndependentSets: bitset_add(s, i) # Checking that the set s is independent - if not bitset_are_disjoint((self.g.rows[i]), s.bits, self.g.width): + if not bitset_are_disjoint(self.g.rows[i], s): return False if self.maximal and not ismaximal(self.g, self.n,s): diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index a0e9623f63a..5d2b46cb5a1 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -373,7 +373,7 @@ class is included in another one, we have to check whether there is in the from sage.structure.sage_object import SageObject from sage.structure.unique_representation import CachedRepresentation, UniqueRepresentation from sage.misc.unknown import Unknown -from sage.misc.misc import SAGE_SHARE +from sage.env import SAGE_SHARE #***************************************************************************** # Copyright (C) 2011 Nathann Cohen @@ -833,8 +833,7 @@ def _parse_db(self, directory): EXAMPLE:: - sage: import os - sage: from sage.misc.misc import SAGE_SHARE + sage: from sage.env import SAGE_SHARE sage: graph_classes._parse_db(os.path.join(SAGE_SHARE,'graphs')) """ import xml.etree.cElementTree as ET diff --git a/src/sage/graphs/matchpoly.pyx b/src/sage/graphs/matchpoly.pyx index 84f18a1279e..c967093d0b0 100644 --- a/src/sage/graphs/matchpoly.pyx +++ b/src/sage/graphs/matchpoly.pyx @@ -34,7 +34,7 @@ Methods from sage.rings.polynomial.polynomial_ring import polygen from sage.rings.integer_ring import ZZ from sage.rings.integer cimport Integer -from sage.misc.misc import prod +from sage.misc.all import prod include 'sage/ext/interrupt.pxi' include 'sage/ext/cdefs.pxi' include 'sage/ext/stdsage.pxi' @@ -210,7 +210,10 @@ def matching_polynomial(G, complement=True, name=None): """ cdef int nverts, nedges, i, j, cur - cdef int *edges1, *edges2, *edges_mem, **edges + cdef int *edges1 + cdef int *edges2 + cdef int *edges_mem + cdef int **edges cdef fmpz_poly_t pol if G.has_multiple_edges(): @@ -362,7 +365,10 @@ cdef void delete_and_add(int **edges, int nverts, int nedges, int totverts, int matching polynomial. """ cdef int i, j, k, edge1, edge2, new_edge1, new_edge2, new_nedges - cdef int *edges1, *edges2, *new_edges1, *new_edges2 + cdef int *edges1 + cdef int *edges2 + cdef int *new_edges1 + cdef int *new_edges2 cdef fmpz * coeff if nverts == 3: diff --git a/src/sage/graphs/pq_trees.py b/src/sage/graphs/pq_trees.py index c85a19e4dab..504a80ac9a2 100644 --- a/src/sage/graphs/pq_trees.py +++ b/src/sage/graphs/pq_trees.py @@ -194,6 +194,11 @@ def __init__(self, seq): sage: from sage.graphs.pq_trees import P, Q sage: p = Q([[1,2], [2,3], P([[2,4], [2,8], [2,9]])]) + + :trac:`17787`:: + + sage: Graph('GvGNp?').is_interval() + False """ from sage.sets.set import Set @@ -242,64 +247,8 @@ def __contains__(self, v): False sage: 9 in p True - - """ - for i in self: - if v in i: - return True - False - - def split(self, v): - r""" - Returns the subsequences of children containing and not - containing ``v`` - - INPUT: - - - ``v`` -- an element of the ground set - - OUTPUT: - - Two lists, the first containing the children of ``self`` - containing ``v``, and the other containing the other children. - - .. NOTE:: - - This command is meant to be used on a partial tree, once it - has be "set continuous" on an element ``v`` and aligned it - to the right. Hence, none of the list should be empty (an - exception is raised if that happens, as it would reveal a - bug in the algorithm) and the sum ``contains + - does_not_contain`` should be equal to the sequence of - children of ``self``. - - EXAMPLE:: - - sage: from sage.graphs.pq_trees import P, Q - sage: p = Q([[1,2], [2,3], P([[2,4], [2,8], [2,9]])]) - sage: p.reverse() - sage: contains, does_not_contain = p.split(1) - sage: contains - [{1, 2}] - sage: does_not_contain - [('P', [{9, 2}, {8, 2}, {2, 4}]), {2, 3}] - sage: does_not_contain + contains == p._children - True - """ - contains = [] - does_not_contain = [] - - for i in self: - if v in i: - contains.append(i) - else: - does_not_contain.append(i) - - if not contains or not does_not_contain: - raise ValueError("None of the sets should be empty !") - - return contains, does_not_contain + return any(v in i for i in self) def __iter__(self): r""" @@ -419,18 +368,39 @@ def simplify(self, v, left = False, right = False): raise ValueError("Exactly one of left or right must be specified") if self.is_Q(): - return self._children + l = [] + for c in self._children: + if (isinstance(c,PQ) and # Is c partial? + v in c and # (does c contain sets with + any(v not in cc for cc in c)): # and without v ?) + l.extend(c.simplify(v,right=right,left=left)) + else: + l.append(c) + return l else: + empty = [] + full = [] - contains, does_not_contain = self.split(v) + partial = [] - A = new_P(does_not_contain) - B = new_P(contains) + for c in self._children: + if v in c: + if (isinstance(c,PQ) and # Is c partial? (does c contain + any(v not in cc for cc in c)): # sets with and without v ?) + partial = c.simplify(v,right=right,left=left) + else: + full.append(c) + else: + empty.append(c) + if empty: + empty = [new_P(empty)] + if full: + full = [new_P(full)] if right: - return [A, B] + return empty+partial+full else: - return [B, A] + return full+partial+empty def flatten(self): r""" diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py index 0c72fc58f09..ead0e0117f8 100644 --- a/src/sage/groups/abelian_gps/abelian_group.py +++ b/src/sage/groups/abelian_gps/abelian_group.py @@ -209,7 +209,7 @@ from sage.rings.arith import divisors, gcd from sage.groups.abelian_gps.abelian_group_element import AbelianGroupElement from sage.misc.cachefunc import cached_method -from sage.misc.misc import prod +from sage.misc.all import prod from sage.misc.mrange import mrange, cartesian_product_iterator from sage.rings.arith import lcm from sage.groups.group import AbelianGroup as AbelianGroupBase diff --git a/src/sage/groups/abelian_gps/abelian_group_morphism.py b/src/sage/groups/abelian_gps/abelian_group_morphism.py index 2663a7b98b7..c9689fe98d1 100644 --- a/src/sage/groups/abelian_gps/abelian_group_morphism.py +++ b/src/sage/groups/abelian_gps/abelian_group_morphism.py @@ -25,7 +25,7 @@ from sage.categories.morphism import * from sage.categories.homset import * -from sage.misc.misc import prod +from sage.misc.all import prod def is_AbelianGroupMorphism(f): return isinstance(f, AbelianGroupMorphism); diff --git a/src/sage/groups/abelian_gps/dual_abelian_group_element.py b/src/sage/groups/abelian_gps/dual_abelian_group_element.py index f7bfb1dbb88..02842f1dc79 100644 --- a/src/sage/groups/abelian_gps/dual_abelian_group_element.py +++ b/src/sage/groups/abelian_gps/dual_abelian_group_element.py @@ -56,7 +56,7 @@ from sage.rings.integer import Integer from sage.rings.infinity import infinity from sage.rings.arith import * -from sage.misc.misc import prod +from sage.misc.all import prod from sage.rings.complex_field import is_ComplexField from sage.groups.abelian_gps.element_base import AbelianGroupElementBase from functools import reduce @@ -91,7 +91,7 @@ def add_strings(x, z=0): return z if not isinstance(x, list): m = x.__iter__() - y = m.next() + y = next(m) return reduce(operator.add, m, y) else: return reduce(operator.add, x[1:], x[0]) diff --git a/src/sage/groups/abelian_gps/values.py b/src/sage/groups/abelian_gps/values.py index 51a976d23ce..62e4836516c 100644 --- a/src/sage/groups/abelian_gps/values.py +++ b/src/sage/groups/abelian_gps/values.py @@ -71,7 +71,7 @@ ########################################################################## -from sage.misc.misc import prod +from sage.misc.all import prod from sage.rings.integer import Integer from sage.categories.morphism import Morphism from sage.groups.abelian_gps.abelian_group import AbelianGroup_class, _normalize diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index d969e971a6a..148e7f58751 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -128,6 +128,7 @@ # http://www.gnu.org/licenses/ ############################################################################## +import types from sage.groups.group import Group from sage.groups.libgap_wrapper import ParentLibGAP, ElementLibGAP @@ -146,6 +147,7 @@ from sage.rings.integer_ring import IntegerRing from sage.functions.generalized import sign from sage.matrix.constructor import matrix +from sage.groups.generic import structure_description class FinitelyPresentedGroupElement(FreeGroupElement): """ @@ -1079,7 +1081,7 @@ def direct_product(self, H, reduced=False, new_names=True): GAP_gens = fp_product.FreeGeneratorsOfFpGroup() if new_names: name_itr = _lexi_gen() # Python generator for lexicographical variable names - gen_names = [name_itr.next() for i in GAP_gens] + gen_names = [next(name_itr) for i in GAP_gens] else: gen_names= [str(g) for g in self.gens()] + [str(g) for g in H.gens()] # Build the direct product in Sage for better variable names @@ -1261,7 +1263,7 @@ def semidirect_product(self, H, hom, check=True, reduced=False): # lists for readability of variable names GAP_gens = prod.FreeGeneratorsOfFpGroup() name_itr = _lexi_gen() # Python generator for lexicographical variable names - ret_F = FreeGroup([name_itr.next() for i in GAP_gens]) + ret_F = FreeGroup([next(name_itr) for i in GAP_gens]) ret_rls = tuple([ret_F(rel_word.TietzeWordAbstractWord(GAP_gens).sage()) for rel_word in prod.RelatorsOfFpGroup()]) ret_fpg = FinitelyPresentedGroup(ret_F, ret_rls) @@ -1479,3 +1481,4 @@ def rewriting_system(self): """ return RewritingSystem(self) +FinitelyPresentedGroup.structure_description = types.MethodType(structure_description, None, FinitelyPresentedGroup) diff --git a/src/sage/groups/finitely_presented_named.py b/src/sage/groups/finitely_presented_named.py index 6f30295b5ce..31214fc9751 100644 --- a/src/sage/groups/finitely_presented_named.py +++ b/src/sage/groups/finitely_presented_named.py @@ -189,7 +189,7 @@ def FinitelyGeneratedAbelianPresentation(int_list): col_sp = diagonal_matrix(int_list).column_space() invariants = FGP_Module(ZZ**(len(int_list)), col_sp).invariants() name_gen = _lexi_gen() - F = FreeGroup([name_gen.next() for i in invariants]) + F = FreeGroup([next(name_gen) for i in invariants]) ret_rls = [F([i+1])**invariants[i] for i in range(len(invariants)) if invariants[i]!=0] # Build commutator relations @@ -327,7 +327,7 @@ def SymmetricPresentation(n): GAP_fp_rep = libgap.Image(libgap.IsomorphismFpGroupByGenerators(perm_rep, perm_rep.gens())) image_gens = GAP_fp_rep.FreeGeneratorsOfFpGroup() name_itr = _lexi_gen() # Python generator object for variable names - F = FreeGroup([name_itr.next() for x in perm_rep.gens()]) + F = FreeGroup([next(name_itr) for x in perm_rep.gens()]) ret_rls = tuple([F(rel_word.TietzeWordAbstractWord(image_gens).sage()) for rel_word in GAP_fp_rep.RelatorsOfFpGroup()]) return FinitelyPresentedGroup(F,ret_rls) @@ -400,7 +400,7 @@ def AlternatingPresentation(n): GAP_fp_rep = libgap.Image(libgap.IsomorphismFpGroupByGenerators(perm_rep, perm_rep.gens())) image_gens = GAP_fp_rep.FreeGeneratorsOfFpGroup() name_itr = _lexi_gen() # Python generator object for variable names - F = FreeGroup([name_itr.next() for x in perm_rep.gens()]) + F = FreeGroup([next(name_itr) for x in perm_rep.gens()]) ret_rls = tuple([F(rel_word.TietzeWordAbstractWord(image_gens).sage()) for rel_word in GAP_fp_rep.RelatorsOfFpGroup()]) return FinitelyPresentedGroup(F,ret_rls) diff --git a/src/sage/groups/free_group.py b/src/sage/groups/free_group.py index 115b7a2b478..4d23b3c69fe 100644 --- a/src/sage/groups/free_group.py +++ b/src/sage/groups/free_group.py @@ -113,23 +113,23 @@ def _lexi_gen(zeroes=False): OUTPUT: Python generator object which outputs a character from the alphabet on each - ``.next()`` call in lexicographical order. The integer `i` is appended + ``next()`` call in lexicographical order. The integer `i` is appended to the output string on the `i^{th}` iteration through the alphabet. EXAMPLES:: sage: from sage.groups.free_group import _lexi_gen sage: itr = _lexi_gen() - sage: F = FreeGroup([itr.next() for i in [1..10]]); F + sage: F = FreeGroup([next(itr) for i in [1..10]]); F Free Group on generators {a, b, c, d, e, f, g, h, i, j} sage: it = _lexi_gen() - sage: [it.next() for i in range(10)] + sage: [next(it) for i in range(10)] ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] sage: itt = _lexi_gen(True) - sage: [itt.next() for i in range(10)] + sage: [next(itt) for i in range(10)] ['a0', 'b0', 'c0', 'd0', 'e0', 'f0', 'g0', 'h0', 'i0', 'j0'] sage: test = _lexi_gen() - sage: ls = [test.next() for i in range(3*26)] + sage: ls = [next(test) for i in range(3*26)] sage: ls[2*26:3*26] ['a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2', 'i2', 'j2', 'k2', 'l2', 'm2', 'n2', 'o2', 'p2', 'q2', 'r2', 's2', 't2', 'u2', 'v2', 'w2', 'x2', 'y2', 'z2'] @@ -138,7 +138,7 @@ def _lexi_gen(zeroes=False): sage: from sage.groups.free_group import _lexi_gen sage: test = _lexi_gen() - sage: ls = [test.next() for i in range(500)] + sage: ls = [next(test) for i in range(500)] sage: ls[234], ls[260] ('a9', 'a10') diff --git a/src/sage/groups/generic.py b/src/sage/groups/generic.py index cde865e47c7..4422118aae3 100644 --- a/src/sage/groups/generic.py +++ b/src/sage/groups/generic.py @@ -107,7 +107,7 @@ from copy import copy -import sage.misc.misc as misc +import sage.misc.all as misc import sage.rings.integer_ring as integer_ring import sage.rings.integer @@ -1148,7 +1148,7 @@ def _order_from_multiple_helper(Q, L, S): L2 = L[k:] # recursive calls o1 = _order_from_multiple_helper( - multiple(Q, sage.misc.misc.prod([p**e for p,e in L2]), operation), + multiple(Q, misc.prod([p**e for p,e in L2]), operation), L1, sum_left) o2 = _order_from_multiple_helper( @@ -1328,3 +1328,90 @@ def merge_points(P1,P2, operation='+', g1 = multiple(g1,m1,operation=operation) g2 = multiple(g2,m2,operation=operation) return (op(g1,g2), m) + +def structure_description(G, latex=False): + r""" + Return a string that tries to describe the structure of ``G``. + + This methods wraps GAP's ``StructureDescription`` method. + + Requires the *optional* ``database_gap`` package. + + For full details, including the form of the returned string and the + algorithm to build it, see `GAP's documentation + `_. + + INPUT: + + - ``latex`` -- a boolean (default: ``False``). If ``True`` return a + LaTeX formatted string. + + OUTPUT: + + - string + + .. WARNING:: + + From GAP's documentation: The string returned by + ``StructureDescription`` is **not** an isomorphism invariant: + non-isomorphic groups can have the same string value, and two + isomorphic groups in different representations can produce different + strings. + + EXAMPLES:: + + sage: G = CyclicPermutationGroup(6) + sage: G.structure_description() # optional - database_gap + 'C6' + sage: G.structure_description(latex=True) # optional - database_gap + 'C_{6}' + sage: G2 = G.direct_product(G, maps=False) + sage: LatexExpr(G2.structure_description(latex=True)) # optional - database_gap + C_{6} \times C_{6} + + This method is mainly intended for small groups or groups with few + normal subgroups. Even then there are some surprises:: + + sage: D3 = DihedralGroup(3) + sage: D3.structure_description() # optional - database_gap + 'S3' + + We use the Sage notation for the degree of dihedral groups:: + + sage: D4 = DihedralGroup(4) + sage: D4.structure_description() # optional - database_gap + 'D4' + + Works for finitely presented groups (:trac:`17573`):: + + sage: F. = FreeGroup() + sage: G=F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1] + sage: G.structure_description() # optional - database_gap + 'C7' + + And matrix groups (:trac:`17573`):: + + sage: groups.matrix.GL(4,2).structure_description() # optional - database_gap + 'A8' + """ + import re + from sage.misc.package import is_package_installed + def correct_dihedral_degree(match): + return "%sD%d" % (match.group(1), int(match.group(2))/2) + + try: + description = G._gap_().StructureDescription().__str__() + except RuntimeError: + if not is_package_installed('database_gap'): + raise RuntimeError("You must install the optional database_gap package first.") + raise + + description = re.sub(r"(\A|\W)D(\d+)", correct_dihedral_degree, description) + if not latex: + return description + description = description.replace("x", r"\times").replace(":", r"\rtimes") + description = re.sub(r"([A-Za-z]+)([0-9]+)", r"\g<1>_{\g<2>}", description) + description = re.sub(r"O([+-])", r"O^{\g<1>}", description) + + return description + diff --git a/src/sage/groups/group.pyx b/src/sage/groups/group.pyx index ee61e07e8ab..0939dcaa6e8 100644 --- a/src/sage/groups/group.pyx +++ b/src/sage/groups/group.pyx @@ -227,7 +227,7 @@ cdef class Group(Parent): sage: G.an_element() f0*f1*f2*f3 """ - from sage.misc.misc import prod + from sage.misc.all import prod return prod(self.gens()) def random_element(self, bound=None): diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 935edbd57d9..bfedd76dbae 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -452,7 +452,7 @@ def __iter__(self): sage: F = GF(3) sage: gens = [matrix(F,2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])] sage: G = MatrixGroup(gens) - sage: iter(G).next() + sage: next(iter(G)) [1 0] [0 1] """ diff --git a/src/sage/groups/matrix_gps/group_element.py b/src/sage/groups/matrix_gps/group_element.py index 1b9a3d01810..f5e57eb9ba8 100644 --- a/src/sage/groups/matrix_gps/group_element.py +++ b/src/sage/groups/matrix_gps/group_element.py @@ -67,7 +67,7 @@ from sage.structure.element import MultiplicativeGroupElement from sage.matrix.matrix import Matrix, is_Matrix from sage.structure.factorization import Factorization -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent from sage.libs.gap.element import GapElement, GapElement_List from sage.misc.cachefunc import cached_method from sage.groups.libgap_wrapper import ElementLibGAP diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index b0185ea01ce..a40675cb775 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -47,6 +47,7 @@ # http://www.gnu.org/licenses/ ############################################################################## +import types from sage.rings.all import ZZ from sage.rings.integer import is_Integer from sage.rings.ring import is_Ring @@ -59,6 +60,7 @@ from sage.structure.sage_object import SageObject from sage.misc.decorators import rename_keyword from sage.misc.cachefunc import cached_method +from sage.groups.generic import structure_description from sage.groups.group import Group from sage.groups.libgap_wrapper import ParentLibGAP @@ -167,46 +169,6 @@ def as_matrix_group(self): from sage.groups.matrix_gps.finitely_generated import MatrixGroup return MatrixGroup(self.gens()) - def field_of_definition(self, **kwds): - """ - Return a field that contains all the matrices in this matrix - group. - - EXAMPLES:: - - sage: G = SU(3,GF(5)) - sage: G.base_ring() - Finite Field in a of size 5^2 - sage: G.field_of_definition() - doctest:...: DeprecationWarning: Use base_ring() instead. - See http://trac.sagemath.org/14014 for details. - Finite Field in a of size 5^2 - sage: G = GO(4,GF(7),1) - sage: G.field_of_definition() - Finite Field of size 7 - sage: G.base_ring() - Finite Field of size 7 - """ - from sage.misc.superseded import deprecation - deprecation(14014, 'Use base_ring() instead.') - return self.base_ring() - - def base_field(self): - """ - Deprecated alias of :meth:`base_ring` - - EXAMPLES:: - - sage: G = SU(3,GF(5)) - sage: G.base_field() - doctest:...: DeprecationWarning: Use base_ring() instead. - See http://trac.sagemath.org/14014 for details. - Finite Field in a of size 5^2 - """ - from sage.misc.superseded import deprecation - deprecation(14014, 'Use base_ring() instead.') - return self.base_ring() - def _repr_(self): """ Return a string representation. @@ -611,7 +573,7 @@ def __iter__(self): EXAMPLES:: sage: i = iter(GL(6,5)) - sage: [ i.next() for j in range(8) ] + sage: [ next(i) for j in range(8) ] [ [1 0 0 0 0 0] [4 0 0 0 0 1] [0 4 0 0 0 0] [0 4 0 0 0 0] [0 1 0 0 0 0] [4 0 0 0 0 0] [0 0 4 0 0 0] [0 0 4 0 0 0] @@ -732,3 +694,4 @@ def list(self): raise NotImplementedError('group must be finite') return tuple(iter(self)) +MatrixGroup_gap.structure_description = types.MethodType(structure_description, None, MatrixGroup_gap) diff --git a/src/sage/groups/perm_gps/cubegroup.py b/src/sage/groups/perm_gps/cubegroup.py index e636880c934..49a7a3b69e3 100644 --- a/src/sage/groups/perm_gps/cubegroup.py +++ b/src/sage/groups/perm_gps/cubegroup.py @@ -565,21 +565,6 @@ def __repr__(self): """ return "The Rubik's cube group with generators R,L,F,B,U,D in SymmetricGroup(48)." - def group(self): - r""" - This is deprecated in trac:`11360`. Use the :class:`CubeGroup` instead. - - EXAMPLES:: - - sage: CubeGroup().group() - doctest:...: DeprecationWarning: group() is deprecated. Use the CubeGroup instead. - See http://trac.sagemath.org/11360 for details. - The Rubik's cube group with generators R,L,F,B,U,D in SymmetricGroup(48). - """ - from sage.misc.superseded import deprecation - deprecation(11360, 'group() is deprecated. Use the CubeGroup instead.') - return self - def B(self): """ Return the generator `B` in Singmaster notation. diff --git a/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx b/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx index ef962a63e00..e11e1c21d45 100644 --- a/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +++ b/src/sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx @@ -432,18 +432,24 @@ cdef aut_gp_and_can_lab *get_aut_gp_and_can_lab(void *S, pointer to a aut_gp_and_can_lab struct """ - cdef PartitionStack *current_ps, *first_ps, *label_ps + cdef PartitionStack *current_ps + cdef PartitionStack *first_ps + cdef PartitionStack *label_ps cdef int first_meets_current = -1 cdef int label_meets_current cdef int current_kids_are_same = 1 cdef int first_kids_are_same - cdef int *current_indicators, *first_indicators, *label_indicators + cdef int *current_indicators + cdef int *first_indicators + cdef int *label_indicators cdef int first_and_current_indicator_same cdef int label_and_current_indicator_same = -1 cdef int compared_current_and_label_indicators - cdef OrbitPartition *orbits_of_subgroup, *orbits_of_permutation, *orbits_of_supergroup + cdef OrbitPartition *orbits_of_subgroup + cdef OrbitPartition *orbits_of_permutation + cdef OrbitPartition *orbits_of_supergroup cdef int subgroup_primary_orbit_size = 0 cdef int minimal_in_primary_orbit @@ -453,10 +459,15 @@ cdef aut_gp_and_can_lab *get_aut_gp_and_can_lab(void *S, cdef bitset_t *vertices_to_split cdef bitset_t *vertices_have_been_reduced - cdef int *permutation, *label_perm, *id_perm, *cells_to_refine_by + cdef int *permutation + cdef int *label_perm + cdef int *id_perm + cdef int *cells_to_refine_by cdef int *vertices_determining_current_stack cdef int *perm_stack - cdef StabilizerChain *group = NULL, *old_group, *tmp_gp + cdef StabilizerChain *group = NULL + cdef StabilizerChain *old_group + cdef StabilizerChain *tmp_gp cdef int i, j, k, ell, b cdef bint discrete, automorphism, update_label diff --git a/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx b/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx index 86958f94787..7542b362edf 100644 --- a/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +++ b/src/sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx @@ -173,8 +173,11 @@ cdef void *canonical_generator_next(void *can_gen_data, int *degree, bint *mem_e # degree ignored! cdef canonical_generator_data *cgd = can_gen_data cdef iterator *cur_iter - cdef void *next_candidate, *parent_cand, *aug - cdef int i, next_cand_deg, *isom, parent_cand_deg + cdef void *next_candidate + cdef void *parent_cand + cdef void *aug + cdef int i, next_cand_deg, parent_cand_deg + cdef int *isom cdef PartitionStack *part cdef bint augmentation_is_canonical cdef aut_gp_and_can_lab *output diff --git a/src/sage/groups/perm_gps/partn_ref/data_structures_pyx.pxi b/src/sage/groups/perm_gps/partn_ref/data_structures_pyx.pxi index a7abb388f6c..d056a182c5e 100644 --- a/src/sage/groups/perm_gps/partn_ref/data_structures_pyx.pxi +++ b/src/sage/groups/perm_gps/partn_ref/data_structures_pyx.pxi @@ -665,10 +665,12 @@ def PS_represent(partition, splits): Done. """ - cdef int i, n = sum([len(cell) for cell in partition]), *gamma + cdef int i, n = sum([len(cell) for cell in partition]) + cdef int *gamma cdef bitset_t b print "Allocating PartitionStack..." - cdef PartitionStack *PS = PS_new(n, 1), *PS2 + cdef PartitionStack *PS = PS_new(n, 1) + cdef PartitionStack *PS2 if PS is NULL: print "Allocation failed!" return @@ -763,7 +765,9 @@ cdef StabilizerChain *SC_new(int n, bint init_gens=True): cdef int i cdef StabilizerChain *SC = \ sage_calloc(1, sizeof(StabilizerChain)) - cdef int *array1, *array2, *array3 + cdef int *array1 + cdef int *array2 + cdef int *array3 cdef bint mem_err = 0 if SC is NULL: return NULL @@ -918,7 +922,8 @@ cdef inline int SC_realloc_gens(StabilizerChain *SC, int level, int size): Returns 1 in case of an allocation failure. """ - cdef int *temp, n = SC.degree + cdef int *temp + cdef int n = SC.degree temp = sage_realloc( SC.generators[level], n * size * sizeof(int) ) if temp is NULL: return 1 @@ -1213,7 +1218,8 @@ cdef inline SC_compose_up_to_base(StabilizerChain *SC, int level, int x, int *pe with x, until the base is reached. The composition is stored to perm. """ cdef int b = SC.base_orbits[level][0], n = SC.degree - cdef int *label, label_no + cdef int *label + cdef int label_no while x != b: label_no = SC.labels[level][x] if label_no < 0: @@ -1248,7 +1254,8 @@ cdef int SC_re_tree(StabilizerChain *SC, int level, int *perm, int x): 0 - No errors. 1 - Allocation failure. """ - cdef int *gen, *gen_inv + cdef int *gen + cdef int *gen_inv cdef int i, b, gen_index, error, n = SC.degree # make sure we have room for the new generator: @@ -1515,7 +1522,8 @@ cdef bint SC_is_giant(int n, int num_perms, int *perms, float p, bitset_t suppor """ cdef int i, j, num_steps, m = 1, support_root cdef unsigned long q - cdef int *gen, *perm = sage_malloc(n*sizeof(int)) + cdef int *gen + cdef int *perm = sage_malloc(n*sizeof(int)) cdef OrbitPartition *OP = OP_new(n) if OP is NULL or perm is NULL: OP_dealloc(OP) @@ -1715,7 +1723,10 @@ def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, """ if gap: from sage.all import PermutationGroup, PermutationGroupElement, shuffle - cdef StabilizerChain *SC, *SCC, *SCCC, *SC_nb + cdef StabilizerChain *SC + cdef StabilizerChain *SCC + cdef StabilizerChain *SCCC + cdef StabilizerChain *SC_nb cdef Integer order, order2 cdef int i, j, m, SC_says cdef bitset_t giant_support @@ -1979,7 +1990,8 @@ cdef int sort_by_function(PartitionStack *PS, int start, int *degrees): """ cdef int n = PS.degree cdef int i, j, max, max_location - cdef int *counts = degrees + n, *output = degrees + 2*n + 1 + cdef int *counts = degrees + n + cdef int *output = degrees + 2*n + 1 for i from 0 <= i <= n: counts[i] = 0 i = 0 @@ -2054,7 +2066,9 @@ cdef int refine_by_orbits(PartitionStack *PS, StabilizerChain *SC, int *perm_sta their minimal cell representatives in the orbit of the group. """ cdef int start, level, gen_index, i, j, k, x, n = SC.degree - cdef int *gen, *min_cell_reps = SC.perm_scratch, *perm = perm_stack + n*PS.depth + cdef int *gen + cdef int *min_cell_reps = SC.perm_scratch + cdef int *perm = perm_stack + n*PS.depth cdef OrbitPartition *OP = SC.OP_scratch cdef int invariant = 1 OP_clear(OP) diff --git a/src/sage/groups/perm_gps/partn_ref/double_coset.pyx b/src/sage/groups/perm_gps/partn_ref/double_coset.pyx index a625673015b..2c84e58c9e1 100644 --- a/src/sage/groups/perm_gps/partn_ref/double_coset.pyx +++ b/src/sage/groups/perm_gps/partn_ref/double_coset.pyx @@ -317,14 +317,17 @@ cdef int double_coset(void *S1, void *S2, PartitionStack *partition1, int *order 1 if S1 and S2 are isomorphic, otherwise 0. """ - cdef PartitionStack *current_ps, *first_ps, *left_ps + cdef PartitionStack *current_ps + cdef PartitionStack *first_ps + cdef PartitionStack *left_ps cdef int first_meets_current = -1 cdef int current_kids_are_same = 1 cdef int first_kids_are_same cdef int *indicators - cdef OrbitPartition *orbits_of_subgroup, *orbits_of_supergroup + cdef OrbitPartition *orbits_of_subgroup + cdef OrbitPartition *orbits_of_supergroup cdef int subgroup_primary_orbit_size = 0 cdef int minimal_in_primary_orbit @@ -335,10 +338,14 @@ cdef int double_coset(void *S1, void *S2, PartitionStack *partition1, int *order cdef bitset_t *vertices_to_split cdef bitset_t *vertices_have_been_reduced - cdef int *permutation, *id_perm, *cells_to_refine_by + cdef int *permutation + cdef int *id_perm + cdef int *cells_to_refine_by cdef int *vertices_determining_current_stack cdef int *perm_stack - cdef StabilizerChain *group, *old_group, *tmp_gp + cdef StabilizerChain *group + cdef StabilizerChain *old_group + cdef StabilizerChain *tmp_gp cdef int i, j, k, ell, b cdef bint discrete, automorphism, update_label diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx index fb209b28304..ace975fae69 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_binary.pyx @@ -302,7 +302,8 @@ cdef class LinearBinaryCodeStruct(BinaryCodeStruct): """ cdef int i, n = self.degree - cdef int *output, *ordering + cdef int *output + cdef int *ordering cdef PartitionStack *part part = PS_new(n, 1) ordering = sage_malloc(self.degree * sizeof(int)) @@ -562,7 +563,8 @@ cdef class NonlinearBinaryCodeStruct(BinaryCodeStruct): """ cdef int i, n = self.degree - cdef int *output, *ordering + cdef int *output + cdef int *ordering cdef PartitionStack *part part = PS_new(n, 1) ordering = sage_malloc(n * sizeof(int)) @@ -811,7 +813,10 @@ cdef int compare_nonlinear_codes(int *gamma_1, int *gamma_2, void *S1, void *S2, cdef bitset_s *B_2_0 = &BCS1.scratch_bitsets[2*BCS1.nwords] # nwords of len degree cdef bitset_s *B_2_1 = &BCS1.scratch_bitsets[3*BCS1.nwords] # nwords of len degree cdef bitset_s *dividers = &BCS1.scratch_bitsets[4*BCS1.nwords] # 1 of len nwords - cdef bitset_s *B_1_this, *B_1_other, *B_2_this, *B_2_other + cdef bitset_s *B_1_this + cdef bitset_s *B_1_other + cdef bitset_s *B_2_this + cdef bitset_s *B_2_other for i from 0 <= i < BCS1.nwords: bitset_copy(&B_1_0[i], &BCS1.words[i]) bitset_copy(&B_2_0[i], &BCS2.words[i]) diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx index f584d2aa24a..6c6e49f0eed 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_graphs.pyx @@ -50,7 +50,8 @@ def isomorphic(G1, G2, partn, ordering2, dig, use_indicator_function, sparse=Fal """ cdef PartitionStack *part - cdef int *output, *ordering + cdef int *output + cdef int *ordering cdef CGraph G cdef GraphStruct GS1 = GraphStruct() cdef GraphStruct GS2 = GraphStruct() @@ -1468,7 +1469,8 @@ cdef iterator *allocate_dg_vert_gen(int degree, int depth): Allocates the iterator for generating graphs. """ cdef iterator *dg_vert_gen = sage_malloc(sizeof(iterator)) - cdef canonical_generator_data *cgd = allocate_cgd(depth, degree), *cgd2 + cdef canonical_generator_data *cgd = allocate_cgd(depth, degree) + cdef canonical_generator_data *cgd2 if dg_vert_gen is NULL or cgd is NULL: sage_free(dg_vert_gen) deallocate_cgd(cgd) diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_lists.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_lists.pyx index f8de0fa0057..0e930101e4c 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_lists.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_lists.pyx @@ -30,7 +30,8 @@ def is_isomorphic(self, other): """ cdef int i, n = len(self) cdef PartitionStack *part - cdef int *output, *ordering + cdef int *output + cdef int *ordering part = PS_new(n, 1) ordering = sage_malloc((len(self)) * sizeof(int)) output = sage_malloc((len(self)) * sizeof(int)) diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx index 3486683e023..f04a08d3afb 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_matrices.pyx @@ -218,7 +218,8 @@ cdef class MatrixStruct: """ cdef int i, j, n = self.degree - cdef int *output, *ordering + cdef int *output + cdef int *ordering cdef PartitionStack *part cdef NonlinearBinaryCodeStruct S_temp for i from 0 <= i < self.nsymbols: diff --git a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx index 41465b580d3..44a95ee427d 100644 --- a/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx +++ b/src/sage/groups/perm_gps/partn_ref/refinement_sets.pyx @@ -570,7 +570,8 @@ cdef void *apply_subset_aug(void *parent, void *aug, void *child, int *degree, b Adds the element represented by ``aug`` to ``parent``, storing the result to ``child``. """ - cdef subset *set1 = child, *par_set = parent + cdef subset *set1 = child + cdef subset *par_set = parent cdef bitset_s parbits = par_set.bits cdef int add_pt = ( aug)[0], n = parbits.size bitset_copy(&set1.bits, &parbits) diff --git a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pxd b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pxd index 6e56d109721..4ebe7c9286a 100644 --- a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pxd +++ b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pxd @@ -33,7 +33,8 @@ cdef class _BestValStore: cdef class LabelledBranching: cdef int n cdef int count - cdef int *father, *act_perm + cdef int *father + cdef int *act_perm cpdef GapElement group, ClosureGroup cdef bint has_empty_intersection(self, PartitionStack * part) cpdef add_gen(self, GapElement_Permutation gen) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 476d9d71625..9389710ce52 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -127,6 +127,7 @@ from sage.misc.randstate import current_randstate import sage.groups.old as group +import types from sage.rings.all import QQ, Integer from sage.interfaces.expect import is_ExpectElement @@ -140,7 +141,7 @@ from sage.categories.all import FiniteEnumeratedSets from sage.groups.conjugacy_classes import ConjugacyClassGAP from sage.functions.other import factorial - +from sage.groups.generic import structure_description def load_hap(): """ @@ -1658,81 +1659,6 @@ def group_primitive_id(self): raise RuntimeError("You must install the optional database_gap package first.") raise - @cached_method - def structure_description(self, latex=False): - r""" - Return a string that tries to describe the structure of ``self``. - - This methods wraps GAP's ``StructureDescription`` method. - - Requires the *optional* ``database_gap`` package. - - For full details, including the form of the returned string and the - algorithm to build it, see `GAP's documentation - `_. - - INPUT: - - - ``latex`` -- a boolean (default: ``False``). If ``True`` return a - LaTeX formatted string. - - OUTPUT: - - - string - - .. WARNING:: - - From GAP's documentation: The string returned by - ``StructureDescription`` is **not** an isomorphism invariant: - non-isomorphic groups can have the same string value, and two - isomorphic groups in different representations can produce different - strings. - - EXAMPLES:: - - sage: G = CyclicPermutationGroup(6) - sage: G.structure_description() # optional - database_gap - 'C6' - sage: G.structure_description(latex=True) # optional - database_gap - 'C_{6}' - sage: G2 = G.direct_product(G, maps=False) - sage: LatexExpr(G2.structure_description(latex=True)) # optional - database_gap - C_{6} \times C_{6} - - This method is mainly intended for small groups or groups with few - normal subgroups. Even then there are some surprises:: - - sage: D3 = DihedralGroup(3) - sage: D3.structure_description() # optional - database_gap - 'S3' - - We use the Sage notation for the degree of dihedral groups:: - - sage: D4 = DihedralGroup(4) - sage: D4.structure_description() # optional - database_gap - 'D4' - - """ - import re - def correct_dihedral_degree(match): - return "%sD%d" % (match.group(1), int(match.group(2))/2) - - try: - description = self._gap_().StructureDescription().str() - except RuntimeError: - if not is_package_installed('database_gap'): - raise RuntimeError("You must install the optional database_gap package first.") - raise - - description = re.sub(r"(\A|\W)D(\d+)", correct_dihedral_degree, description) - if not latex: - return description - description = description.replace("x", r"\times").replace(":", r"\rtimes") - description = re.sub(r"([A-Za-z]+)([0-9]+)", r"\g<1>_{\g<2>}", description) - description = re.sub(r"O([+-])", r"O^{\g<1>}", description) - - return description - def center(self): """ Return the subgroup of elements that commute with every element @@ -2439,7 +2365,7 @@ def as_finitely_presented_group(self, reduced=False): image_fp = libgap.Image( libgap.IsomorphismFpGroupByGenerators(self, self.gens())) image_gens = image_fp.FreeGeneratorsOfFpGroup() name_itr = _lexi_gen() # Python generator object for variable names - F = FreeGroup([name_itr.next() for x in image_gens]) + F = FreeGroup([next(name_itr) for x in image_gens]) # Convert GAP relators to Sage relators using the Tietze word of each defining relation. ret_rls = tuple([F(rel_word.TietzeWordAbstractWord(image_gens).sage()) @@ -4075,6 +4001,8 @@ def upper_central_series(self): UCS = self._gap_().UpperCentralSeriesOfGroup() return [self.subgroup(gap_group=group) for group in UCS] +PermutationGroup_generic.structure_description = types.MethodType(structure_description, None, PermutationGroup_generic) + class PermutationGroup_subgroup(PermutationGroup_generic): """ Subgroup subclass of ``PermutationGroup_generic``, so instance methods diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 75064cc07d8..ccc6e83c9db 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -503,7 +503,8 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return make_permgroup_element_v2, (self._parent, self.domain(), self._parent.domain()) cdef PermutationGroupElement _new_c(self): - cdef PermutationGroupElement other = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef PermutationGroupElement other = t.__new__(t) if HAS_DICTIONARY(self): other.__class__ = self.__class__ other._parent = self._parent diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index cdfc77b4534..73422094efe 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -1762,7 +1762,7 @@ class TransitiveGroupsAll(DisjointUnionEnumeratedSets): +Infinity sage: p = L.__iter__() # optional - database_gap - sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) # optional - database_gap + sage: (next(p), next(p), next(p), next(p), next(p), next(p), next(p), next(p)) # optional - database_gap (Transitive group number 1 of degree 0, Transitive group number 1 of degree 1, Transitive group number 1 of degree 2, Transitive group number 1 of degree 3, Transitive group number 2 of degree 3, Transitive group number 1 of degree 4, Transitive group number 2 of degree 4, Transitive group number 3 of degree 4) TESTS:: @@ -2142,8 +2142,8 @@ class PrimitiveGroupsAll(DisjointUnionEnumeratedSets): +Infinity sage: p = L.__iter__() # optional - database_gap - sage: (p.next(), p.next(), p.next(), p.next(), # optional - database_gap - ... p.next(), p.next(), p.next(), p.next()) + sage: (next(p), next(p), next(p), next(p), # optional - database_gap + ... next(p), next(p), next(p), next(p)) (Trivial group, Trivial group, S(2), A(3), S(3), A(4), S(4), C(5)) TESTS:: @@ -2576,7 +2576,7 @@ def ramification_module_decomposition_hurwitz_curve(self): raise ValueError("Degree must be 2.") F = self.base_ring() q = F.order() - from sage.misc.misc import SAGE_EXTCODE + from sage.env import SAGE_EXTCODE gapcode = SAGE_EXTCODE + '/gap/joyner/hurwitz_crv_rr_sp.gap' gap.eval('Read("'+gapcode+'")') mults = gap.eval("ram_module_hurwitz("+str(q)+")") @@ -2620,7 +2620,7 @@ def ramification_module_decomposition_modular_curve(self): raise ValueError("Degree must be 2.") F = self.base_ring() q = F.order() - from sage.misc.misc import SAGE_EXTCODE + from sage.env import SAGE_EXTCODE gapcode = SAGE_EXTCODE + '/gap/joyner/modular_crv_rr_sp.gap' gap.eval('Read("'+gapcode+'")') mults = gap.eval("ram_module_X("+str(q)+")") diff --git a/src/sage/groups/perm_gps/symgp_conjugacy_class.py b/src/sage/groups/perm_gps/symgp_conjugacy_class.py index 52bbbed5ca8..b2d387d2355 100644 --- a/src/sage/groups/perm_gps/symgp_conjugacy_class.py +++ b/src/sage/groups/perm_gps/symgp_conjugacy_class.py @@ -227,9 +227,9 @@ def conjugacy_class_iterator(part, S=None): It is also possible to specify any underlying set:: sage: it = conjugacy_class_iterator([2,2,2], 'abcdef') - sage: it.next() + sage: next(it) [('a', 'c'), ('b', 'e'), ('d', 'f')] - sage: it.next() + sage: next(it) [('a', 'c'), ('b', 'd'), ('e', 'f')] """ n = sum(part) diff --git a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx index fb314e8aeb2..1fc982da25c 100644 --- a/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx +++ b/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx @@ -137,7 +137,7 @@ cdef class SemimonomialTransformation(MultiplicativeGroupElement): cdef _new_c(self): # Create a copy of self. cdef SemimonomialTransformation x - x = PY_NEW(SemimonomialTransformation) + x = SemimonomialTransformation.__new__(SemimonomialTransformation) x._parent = self._parent x.v = self.v x.perm = self.perm diff --git a/src/sage/gsl/interpolation.pxd b/src/sage/gsl/interpolation.pxd index 1af4a1cb65b..029f28296b1 100644 --- a/src/sage/gsl/interpolation.pxd +++ b/src/sage/gsl/interpolation.pxd @@ -3,7 +3,8 @@ include 'sage/ext/interrupt.pxi' include 'gsl.pxi' cdef class Spline: - cdef double *x, *y + cdef double *x + cdef double *y cdef gsl_interp_accel *acc cdef gsl_spline *spline cdef int started diff --git a/src/sage/homology/chain_complex.py b/src/sage/homology/chain_complex.py index bee8cde04e2..2c56a290fdc 100644 --- a/src/sage/homology/chain_complex.py +++ b/src/sage/homology/chain_complex.py @@ -246,7 +246,7 @@ def ChainComplex(data=None, **kwds): try: zero = grading_group.identity() except AttributeError: - zero = grading_group.zero_element() + zero = grading_group.zero() if base_ring is None: base_ring = ZZ data_dict = dict() @@ -394,7 +394,7 @@ def _repr_(self): return 'Trivial chain' if n == 1: - deg, vec = self._vec.iteritems().next() + deg, vec = next(self._vec.iteritems()) return 'Chain({0}:{1})'.format(deg, vec) return 'Chain with {0} nonzero terms over {1}'.format( diff --git a/src/sage/homology/simplicial_complex_homset.py b/src/sage/homology/simplicial_complex_homset.py index 56b86f42fe6..46d3aed15d4 100644 --- a/src/sage/homology/simplicial_complex_homset.py +++ b/src/sage/homology/simplicial_complex_homset.py @@ -173,7 +173,7 @@ def an_element(self): """ X_vertices = self._domain.vertices().set() try: - i = self._codomain.vertices().set().__iter__().next() + i = next(self._codomain.vertices().set().__iter__()) except StopIteration: if len(X_vertices) == 0: return dict() diff --git a/src/sage/interacts/library_cython.pyx b/src/sage/interacts/library_cython.pyx index 7da6fb81fcf..e85d5d882f0 100644 --- a/src/sage/interacts/library_cython.pyx +++ b/src/sage/interacts/library_cython.pyx @@ -16,7 +16,7 @@ AUTHORS: # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.misc.misc import prod +from sage.misc.all import prod include 'sage/ext/interrupt.pxi' include 'sage/ext/cdefs.pxi' diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index c85e37719b7..b446f6e6bd8 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -177,7 +177,8 @@ import os, re from expect import Expect, ExpectElement, FunctionElement, ExpectFunction -from sage.misc.misc import verbose, DOT_SAGE +from sage.misc.all import verbose +from sage.env import DOT_SAGE from pexpect import EOF from sage.misc.multireplace import multiple_replace diff --git a/src/sage/interfaces/chomp.py b/src/sage/interfaces/chomp.py index df4e3a18e17..6878a2b2b36 100644 --- a/src/sage/interfaces/chomp.py +++ b/src/sage/interfaces/chomp.py @@ -131,7 +131,7 @@ def __call__(self, program, complex, subcomplex=None, **kwds): sage: CHomP()('homcubes', T) # indirect doctest, optional - CHomP {0: 0, 1: Z x Z, 2: Z} """ - from sage.misc.misc import tmp_filename + from sage.misc.temporary_file import tmp_filename from sage.homology.all import CubicalComplex, cubical_complexes from sage.homology.all import SimplicialComplex, Simplex from sage.homology.cubical_complex import Cube diff --git a/src/sage/interfaces/ecm.py b/src/sage/interfaces/ecm.py index 247b177eda2..5b9b735dfd8 100644 --- a/src/sage/interfaces/ecm.py +++ b/src/sage/interfaces/ecm.py @@ -43,7 +43,7 @@ from sage.structure.sage_object import SageObject from sage.rings.integer_ring import ZZ -from sage.misc.misc import verbose, tmp_filename +from sage.misc.all import verbose, tmp_filename from sage.misc.decorators import rename_keyword diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 1e61635ee72..19ff5c3c14b 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -62,7 +62,8 @@ from sage.structure.element import RingElement import sage.misc.sage_eval -from sage.misc.misc import SAGE_EXTCODE, verbose, SAGE_TMP_INTERFACE, LOCAL_IDENTIFIER +from sage.misc.misc import verbose, SAGE_TMP_INTERFACE +from sage.env import SAGE_EXTCODE, LOCAL_IDENTIFIER from sage.misc.object_multiplexer import Multiplex BAD_SESSION = -2 diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index 3e9f93ac0d9..21023b686a9 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -178,7 +178,7 @@ import expect from expect import Expect, ExpectElement, FunctionElement, ExpectFunction from sage.env import SAGE_LOCAL, SAGE_EXTCODE, DOT_SAGE -from sage.misc.misc import is_64_bit, is_in_string +from sage.misc.misc import is_in_string import re import os import pexpect @@ -649,15 +649,13 @@ def _keyboard_interrupt(self): 2 sage: import sage.tests.interrupt sage: try: - ... sage.tests.interrupt.interrupt_after_delay() - ... while True: SymmetricGroup(7).conjugacy_classes_subgroups() - ... except KeyboardInterrupt: - ... pass - Interrupting Gap... + ....: sage.tests.interrupt.interrupt_after_delay() + ....: while True: SymmetricGroup(7).conjugacy_classes_subgroups() + ....: except KeyboardInterrupt: + ....: pass sage: gap(2) 2 """ - print "Interrupting %s..."%self self.quit() raise KeyboardInterrupt("Ctrl-c pressed while running %s"%self) diff --git a/src/sage/interfaces/gap3.py b/src/sage/interfaces/gap3.py index 8a14e9e49b7..c15d2c9b73d 100644 --- a/src/sage/interfaces/gap3.py +++ b/src/sage/interfaces/gap3.py @@ -262,10 +262,9 @@ class Gap3(Gap_generic): sage: gap3(2) #optional - gap3 2 sage: try: - ... gap3._keyboard_interrupt() - ... except KeyboardInterrupt: - ... pass #optional - gap3 - Interrupting Gap3... + ....: gap3._keyboard_interrupt() + ....: except KeyboardInterrupt: + ....: pass sage: gap3(2) #optional - gap3 2 diff --git a/src/sage/interfaces/giac.py b/src/sage/interfaces/giac.py index 55ecfc70e99..da737b1c1ea 100644 --- a/src/sage/interfaces/giac.py +++ b/src/sage/interfaces/giac.py @@ -190,7 +190,7 @@ import pexpect -from sage.misc.misc import verbose, DOT_SAGE +from sage.env import DOT_SAGE from sage.misc.pager import pager COMMANDS_CACHE = '%s/giac_commandlist_cache.sobj'%DOT_SAGE diff --git a/src/sage/interfaces/jmoldata.py b/src/sage/interfaces/jmoldata.py index 7154448f499..7a76f796298 100644 --- a/src/sage/interfaces/jmoldata.py +++ b/src/sage/interfaces/jmoldata.py @@ -21,7 +21,7 @@ from sage.structure.sage_object import SageObject -from sage.misc.misc import SAGE_LOCAL, DOT_SAGE, sage_makedirs +from sage.env import SAGE_LOCAL from sage.misc.temporary_file import tmp_filename import subprocess diff --git a/src/sage/interfaces/lie.py b/src/sage/interfaces/lie.py index 7c91dd89be8..dba35e88d22 100644 --- a/src/sage/interfaces/lie.py +++ b/src/sage/interfaces/lie.py @@ -285,7 +285,8 @@ ########################################################################## from expect import Expect, ExpectElement, ExpectFunction, FunctionElement, AsciiArtString -from sage.misc.misc import verbose, DOT_SAGE, SAGE_LOCAL +from sage.misc.all import verbose, prod +from sage.env import DOT_SAGE, SAGE_LOCAL COMMANDS_CACHE = '%s/lie_commandlist_cache.sobj'%DOT_SAGE @@ -777,7 +778,6 @@ def _sage_(self): import sage.matrix.constructor return sage.matrix.constructor.matrix( eval( str(self).replace('\n','').strip()) ) elif t == 'pol': - import sage.misc.misc from sage.rings.all import PolynomialRing, QQ #Figure out the number of variables @@ -808,7 +808,7 @@ def _sage_(self): xpos = term.find('X') coef = eval(term[:xpos].strip()) exps = eval(term[xpos+1:].strip()) - monomial = sage.misc.misc.prod(map(lambda i: x[i]**exps[i] , range(nvars))) + monomial = prod(map(lambda i: x[i]**exps[i] , range(nvars))) pol += coef * monomial return pol diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py index 474f73d2232..5b1e17a6387 100644 --- a/src/sage/interfaces/macaulay2.py +++ b/src/sage/interfaces/macaulay2.py @@ -214,7 +214,6 @@ def _read_in_file_command(self, filename): TESTS:: - sage: from sage.misc.misc import tmp_filename sage: filename = tmp_filename() sage: f = open(filename, "w") sage: f.write("sage_test = 7;") diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index 4ba9bd4db46..6e6445787ba 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -221,10 +221,11 @@ SAGE_REF = "_sage_ref" SAGE_REF_RE = re.compile('%s\d+'%SAGE_REF) +from sage.env import SAGE_EXTCODE, DOT_SAGE import sage.misc.misc import sage.misc.sage_eval -INTRINSIC_CACHE = '%s/magma_intrinsic_cache.sobj'%sage.misc.misc.DOT_SAGE +INTRINSIC_CACHE = '%s/magma_intrinsic_cache.sobj' % DOT_SAGE EXTCODE_DIR = None @@ -243,7 +244,7 @@ def extcode_dir(): if not EXTCODE_DIR: import shutil tmp = sage.misc.temporary_file.tmp_dir() - shutil.copytree('%s/magma/'%sage.misc.misc.SAGE_EXTCODE, tmp + '/data') + shutil.copytree('%s/magma/'%SAGE_EXTCODE, tmp + '/data') EXTCODE_DIR = "%s/data/"%tmp return EXTCODE_DIR @@ -1507,7 +1508,7 @@ def ideal(self, L): x*y^3 ] """ - P = iter(L).next().parent() + P = next(iter(L)).parent() Pn = self(P).name() k = P.base_ring() if k.degree() > 1: @@ -2235,9 +2236,9 @@ def __iter__(self): Full Vector space of degree 2 over GF(3) sage: w = V.__iter__(); w # optional - magma - sage: w.next() # optional - magma + sage: next(w) # optional - magma (0 0) - sage: w.next() # optional - magma + sage: next(w) # optional - magma (1 0) sage: list(w) # optional - magma [(2 0), (0 1), (1 1), (2 1), (0 2), (1 2), (2 2)] @@ -2924,3 +2925,75 @@ def flush(self): """ import sys sys.stdout.flush() + +class MagmaGBDefaultContext: + """ + Context to force preservation of verbosity options for Magma's + Groebner basis computation. + """ + def __init__(self, magma=None): + """ + INPUT: + + - ``magma`` - (default: ``magma_default``) + + EXAMPLE:: + + sage: from sage.interfaces.magma import MagmaGBDefaultContext + sage: magma.SetVerbose('Groebner',1) # optional - magma + sage: with MagmaGBDefaultContext(): magma.GetVerbose('Groebner') # optional - magma + 0 + """ + if magma is None: + from sage.interfaces.all import magma as magma_default + magma = magma_default + + self.magma = magma + + def __enter__(self): + """ + EXAMPLE:: + + sage: from sage.interfaces.magma import MagmaGBDefaultContext + sage: magma.SetVerbose('Groebner',1) # optional - magma + sage: with MagmaGBDefaultContext(): magma.GetVerbose('Groebner') # optional - magma + 0 + """ + self.groebner_basis_verbose = self.magma.GetVerbose('Groebner') + self.magma.SetVerbose('Groebner',0) + + def __exit__(self, typ, value, tb): + """ + EXAMPLE:: + + sage: from sage.interfaces.magma import MagmaGBDefaultContext + sage: magma.SetVerbose('Groebner',1) # optional - magma + sage: with MagmaGBDefaultContext(): magma.GetVerbose('Groebner') # optional - magma + 0 + sage: magma.GetVerbose('Groebner') # optional - magma + 1 + """ + self.magma.SetVerbose('Groebner',self.groebner_basis_verbose) + +def magma_gb_standard_options(func): + """ + Decorator to force default options for Magma. + + EXAMPLE:: + + sage: P. = PolynomialRing(GF(127)) + sage: J = sage.rings.ideal.Cyclic(P).homogenize() + sage: from sage.misc.sageinspect import sage_getsource + sage: "mself" in sage_getsource(J._groebner_basis_magma) + True + + """ + from sage.misc.decorators import sage_wraps + @sage_wraps(func) + def wrapper(*args, **kwds): + """ + Execute function in ``MagmaGBDefaultContext``. + """ + with MagmaGBDefaultContext(): + return func(*args, **kwds) + return wrapper diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 1ae66b0b52b..d9ca69d564f 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -241,7 +241,7 @@ import pexpect -from sage.misc.misc import verbose, DOT_SAGE +from sage.env import DOT_SAGE from sage.misc.pager import pager COMMANDS_CACHE = '%s/maple_commandlist_cache.sobj'%DOT_SAGE diff --git a/src/sage/interfaces/mathematica.py b/src/sage/interfaces/mathematica.py index 7591327b81b..8121167edca 100644 --- a/src/sage/interfaces/mathematica.py +++ b/src/sage/interfaces/mathematica.py @@ -403,7 +403,7 @@ def __init__(self, maxread=100, script_subdirectory=None, logfile=None, server=N Expect.__init__(self, name = 'mathematica', prompt = 'In[[0-9]+]:=', - command = "math", + command = "math-readline", maxread = maxread, server = server, server_tmpdir = server_tmpdir, @@ -895,33 +895,11 @@ def _sage_doc_(self): def reduce_load(X): return mathematica(X) -# Cleverly run Mathematica with the benefit of readline, which -# is something the usual commercial mathematica doesn't provide! -# See -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/363500 - import os, sys def mathematica_console(readline=True): if not readline: os.system('math') return - f1 = os.popen('math ', 'w') - f1.flush() - try: - while True: - sys.stdout.write('') - try: - line = raw_input(' ') - f1.writelines(line+'\n') - f1.flush() - except KeyboardInterrupt: - f1.close() - break - except EOFError: - pass - sys.stdout.write('\n') - -#def mathematica_console(): -# os.system('mathematica') - - + else: + os.system('math-readline') + return diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index d723ac2f400..761986c5693 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -438,6 +438,13 @@ sage: maxima._eval_line('((((((((((0) + ((1) / ((n0) ^ (0)))) + ((1) / ((n1) ^ (1)))) + ((1) / ((n2) ^ (2)))) + ((1) / ((n3) ^ (3)))) + ((1) / ((n4) ^ (4)))) + ((1) / ((n5) ^ (5)))) + ((1) / ((n6) ^ (6)))) + ((1) / ((n7) ^ (7)))) + ((1) / ((n8) ^ (8)))) + ((1) / ((n9) ^ (9)));') '1/n9^9+1/n8^8+1/n7^7+1/n6^6+1/n5^5+1/n4^4+1/n3^3+1/n2^2+1/n1+1' + +Test that Maxima gracefully handles this syntax error (:trac:`17667`):: + + sage: maxima.eval("1 == 1;") + Traceback (most recent call last): + ... + TypeError: ...incorrect syntax: = is not a prefix operator... """ #***************************************************************************** diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 0944ef36219..6eefd9eed5e 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -50,7 +50,7 @@ import os, re, sys, subprocess -from sage.misc.misc import DOT_SAGE +from sage.env import DOT_SAGE COMMANDS_CACHE = '%s/maxima_commandlist_cache.sobj'%DOT_SAGE from sage.misc.multireplace import multiple_replace diff --git a/src/sage/interfaces/mupad.py b/src/sage/interfaces/mupad.py index 828a49f5c11..9e372520bce 100644 --- a/src/sage/interfaces/mupad.py +++ b/src/sage/interfaces/mupad.py @@ -94,7 +94,7 @@ FunctionElement, AsciiArtString) -from sage.misc.misc import verbose, DOT_SAGE +from sage.env import DOT_SAGE COMMANDS_CACHE = '%s/mupad_commandlist_cache.sobj'%DOT_SAGE PROMPT = ">>" diff --git a/src/sage/interfaces/phc.py b/src/sage/interfaces/phc.py index 13edbc0b4bc..239c04c160f 100644 --- a/src/sage/interfaces/phc.py +++ b/src/sage/interfaces/phc.py @@ -33,7 +33,7 @@ import os -import sage.misc.misc +from sage.misc.all import tmp_filename from sage.rings.real_mpfr import RR from sage.rings.all import CC from sage.rings.integer import Integer @@ -420,8 +420,8 @@ def _output_from_command_list(self, command_list, polys, verbose = False): sage: a = phc._output_from_command_list(['phc -m','4','n','n','n'], start_sys) # optional -- phc """ # Get temporary file names (these will be in SAGE_HOME/.sage/tmp/pid) - input_filename = sage.misc.misc.tmp_filename() - output_filename = sage.misc.misc.tmp_filename() + input_filename = tmp_filename() + output_filename = tmp_filename() # Get the input polynomial text input = self._input_file(polys) @@ -602,7 +602,7 @@ def _path_track_file(self, start_filename_or_string, polys, input_ring, c_skew = """ # Probably unnecessarily redundant from the start_from function if start_filename_or_string.find('THE SOLUTIONS') != -1: - start_filename = sage.misc.misc.tmp_filename() + start_filename = tmp_filename() start_file = open(start_filename, 'w') start_file.write(start_filename_or_string) start_file.close() @@ -774,11 +774,11 @@ def start_from(self, start_filename_or_string, polys, input_ring, path_track_fil sage: len(sol.solutions()) # optional -- phc 30 """ - input_filename = sage.misc.misc.tmp_filename() - output_filename = sage.misc.misc.tmp_filename() + input_filename = tmp_filename() + output_filename = tmp_filename() if start_filename_or_string.find('THE SOLUTIONS') != -1: - start_filename = sage.misc.misc.tmp_filename() + start_filename = tmp_filename() start_file = open(start_filename,'w') start_file.write(start_filename_or_string) start_file.close() @@ -869,9 +869,9 @@ def blackbox(self, polys, input_ring, verbose = False): """ # Get three temporary file names (these will be in SAGE_HOME/.sage/tmp/pid) - input_filename = sage.misc.misc.tmp_filename() + input_filename = tmp_filename() output_filename = input_filename + ".phc" - log_filename = sage.misc.misc.tmp_filename() + log_filename = tmp_filename() # Get the input polynomial text input = self._input_file(polys) diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 33fdaeaa6fa..72364d7d41b 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -522,7 +522,6 @@ Check the qepcad configuration file:: - sage: from sage.misc.misc import SAGE_LOCAL sage: open('%s/default.qepcadrc'%SAGE_LOCAL).readlines()[-1] 'SINGULAR .../local/bin\n' @@ -540,7 +539,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -import sage.misc.misc +from sage.env import SAGE_LOCAL import pexpect import re import sys @@ -560,7 +559,6 @@ def _qepcad_cmd(memcells=None): EXAMPLES:: sage: from sage.interfaces.qepcad import _qepcad_cmd - sage: from sage.misc.misc import SAGE_LOCAL sage: s = _qepcad_cmd() sage: s == 'env qe=%s qepcad '%SAGE_LOCAL True @@ -572,7 +570,7 @@ def _qepcad_cmd(memcells=None): memcells_arg = '+N%s' % memcells else: memcells_arg = '' - return "env qe=%s qepcad %s"%(sage.misc.misc.SAGE_LOCAL, memcells_arg) + return "env qe=%s qepcad %s"%(SAGE_LOCAL, memcells_arg) _command_info_cache = None @@ -597,7 +595,7 @@ def _update_command_info(): cache = {} - with open('%s/bin/qepcad.help'%sage.misc.misc.SAGE_LOCAL) as help: + with open('%s/bin/qepcad.help'%SAGE_LOCAL) as help: assert(help.readline().strip() == '@') while True: diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py index 9b52618d015..597b3db1ac4 100644 --- a/src/sage/interfaces/r.py +++ b/src/sage/interfaces/r.py @@ -212,7 +212,7 @@ ########################################################################## from expect import Expect, ExpectElement, ExpectFunction, FunctionElement -from sage.misc.misc import DOT_SAGE +from sage.env import DOT_SAGE import re import sage.rings.integer diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index 576fcc73e3d..d4f107537e3 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -304,6 +304,8 @@ 'ring testgf9 = (9,x),(a,b,c,d,e,f),(M((1,2,3,0)),wp(2,3),lp);' """ + + #We could also do these calculations without using the singular #interface (behind the scenes the interface is used by Sage): # sage: x, y = PolynomialRing(RationalField(), 2, names=['x','y']).gens() @@ -2410,3 +2412,166 @@ def flush(self): sage: s3.flush() """ sys.stdout.flush() + +class SingularGBDefaultContext: + """ + Within this context all Singular Groebner basis calculations are + reduced automatically. + + AUTHORS: + + - Martin Albrecht + - Simon King + """ + def __init__(self, singular=None): + """ + Within this context all Singular Groebner basis calculations + are reduced automatically. + + INPUT: + + - ``singular`` - Singular instance (default: default instance) + + EXAMPLE:: + + sage: from sage.interfaces.singular import SingularGBDefaultContext + sage: P. = PolynomialRing(QQ,3, order='lex') + sage: I = sage.rings.ideal.Katsura(P,3) + sage: singular.option('noredTail') + sage: singular.option('noredThrough') + sage: Is = I._singular_() + sage: gb = Is.groebner() + sage: gb + 84*c^4-40*c^3+c^2+c, + 7*b+210*c^3-79*c^2+3*c, + a+2*b+2*c-1 + + :: + + sage: with SingularGBDefaultContext(): rgb = Is.groebner() + sage: rgb + 84*c^4-40*c^3+c^2+c, + 7*b+210*c^3-79*c^2+3*c, + 7*a-420*c^3+158*c^2+8*c-7 + + Note that both bases are Groebner bases because they have + pairwise prime leading monomials but that the monic version of + the last element in ``rgb`` is smaller than the last element + of ``gb`` with respect to the lexicographical term ordering. :: + + sage: (7*a-420*c^3+158*c^2+8*c-7)/7 < (a+2*b+2*c-1) + True + + .. note:: + + This context is used automatically internally whenever a + Groebner basis is computed so the user does not need to use + it manually. + """ + if singular is None: + from sage.interfaces.all import singular as singular_default + singular = singular_default + self.singular = singular + + def __enter__(self): + """ + EXAMPLE:: + + sage: from sage.interfaces.singular import SingularGBDefaultContext + sage: P. = PolynomialRing(QQ,3, order='lex') + sage: I = sage.rings.ideal.Katsura(P,3) + sage: singular.option('noredTail') + sage: singular.option('noredThrough') + sage: Is = I._singular_() + sage: with SingularGBDefaultContext(): rgb = Is.groebner() + sage: rgb + 84*c^4-40*c^3+c^2+c, + 7*b+210*c^3-79*c^2+3*c, + 7*a-420*c^3+158*c^2+8*c-7 + """ + from sage.interfaces.singular import SingularError + try: + self.bck_degBound = int(self.singular.eval('degBound')) + except SingularError: + self.bck_degBound = int(0) + try: + self.bck_multBound = int(self.singular.eval('multBound')) + except SingularError: + self.bck_multBound = int(0) + self.o = self.singular.option("get") + self.singular.option('set',self.singular._saved_options) + self.singular.option("redSB") + self.singular.option("redTail") + try: + self.singular.eval('degBound=0') + except SingularError: + pass + try: + self.singular.eval('multBound=0') + except SingularError: + pass + + def __exit__(self, typ, value, tb): + """ + EXAMPLE:: + + sage: from sage.interfaces.singular import SingularGBDefaultContext + sage: P. = PolynomialRing(QQ,3, order='lex') + sage: I = sage.rings.ideal.Katsura(P,3) + sage: singular.option('noredTail') + sage: singular.option('noredThrough') + sage: Is = I._singular_() + sage: with SingularGBDefaultContext(): rgb = Is.groebner() + sage: rgb + 84*c^4-40*c^3+c^2+c, + 7*b+210*c^3-79*c^2+3*c, + 7*a-420*c^3+158*c^2+8*c-7 + """ + from sage.interfaces.singular import SingularError + self.singular.option("set",self.o) + try: + self.singular.eval('degBound=%d'%self.bck_degBound) + except SingularError: + pass + try: + self.singular.eval('multBound=%d'%self.bck_multBound) + except SingularError: + pass + +def singular_gb_standard_options(func): + r""" + Decorator to force a reduced Singular groebner basis. + + TESTS:: + + sage: P. = PolynomialRing(GF(127)) + sage: J = sage.rings.ideal.Cyclic(P).homogenize() + sage: from sage.misc.sageinspect import sage_getsource + sage: "basis" in sage_getsource(J.interreduced_basis) #indirect doctest + True + + The following tests against a bug that was fixed in trac ticket #11298:: + + sage: from sage.misc.sageinspect import sage_getsourcelines, sage_getargspec + sage: P. = QQ[] + sage: I = P*[x,y] + sage: sage_getargspec(I.interreduced_basis) + ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None) + sage: sage_getsourcelines(I.interreduced_basis) + ([' @singular_gb_standard_options\n', + ' @libsingular_gb_standard_options\n', + ' def interreduced_basis(self):\n', ' + ... + ' return self.basis.reduced()\n'], ...) + + .. note:: + + This decorator is used automatically internally so the user + does not need to use it manually. + """ + from sage.misc.decorators import sage_wraps + @sage_wraps(func) + def wrapper(*args, **kwds): + with SingularGBDefaultContext(): + return func(*args, **kwds) + return wrapper diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index b86c886439b..8930468198b 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -16,7 +16,7 @@ #***************************************************************************** from sage.misc.pager import pager -from sage.misc.misc import tmp_filename +from sage.misc.temporary_file import tmp_filename from sage.misc.sagedoc import format import os import sys diff --git a/src/sage/libs/flint/fmpz_poly.pyx b/src/sage/libs/flint/fmpz_poly.pyx index 0233f667642..d74c01446d8 100644 --- a/src/sage/libs/flint/fmpz_poly.pyx +++ b/src/sage/libs/flint/fmpz_poly.pyx @@ -162,7 +162,7 @@ cdef class Fmpz_poly(SageObject): """ if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly): raise TypeError - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_add(res.poly, (left).poly, (right).poly) return res @@ -178,7 +178,7 @@ cdef class Fmpz_poly(SageObject): """ if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly): raise TypeError - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_sub(res.poly, (left).poly, (right).poly) return res @@ -192,7 +192,7 @@ cdef class Fmpz_poly(SageObject): sage: -Fmpz_poly([2,10,2,3,18,-5]) 6 -2 -10 -2 -3 -18 5 """ - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_neg(res.poly, self.poly) return res @@ -216,7 +216,7 @@ cdef class Fmpz_poly(SageObject): sage: f * 5r 3 5 0 -5 """ - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly): if PY_TYPE_CHECK(left, int) : fmpz_poly_scalar_mul_si(res.poly, (right).poly, left) @@ -251,7 +251,7 @@ cdef class Fmpz_poly(SageObject): cdef long nn = n if not PY_TYPE_CHECK(self, Fmpz_poly): raise TypeError - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_pow(res.poly, (self).poly, nn) return res @@ -273,7 +273,7 @@ cdef class Fmpz_poly(SageObject): if n < 0: raise ValueError, "Exponent must be at least 0" cdef long exp_c = exp, nn = n - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_pow_trunc(res.poly, (self).poly, exp_c, nn) return res @@ -294,7 +294,7 @@ cdef class Fmpz_poly(SageObject): """ if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly): raise TypeError - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_div(res.poly, (left).poly, (right).poly) return res @@ -321,8 +321,8 @@ cdef class Fmpz_poly(SageObject): sage: q*g+r 10 1 2 3 4 5 6 7 8 9 10 """ - cdef Fmpz_poly Q = PY_NEW(Fmpz_poly) - cdef Fmpz_poly R = PY_NEW(Fmpz_poly) + cdef Fmpz_poly Q = Fmpz_poly.__new__(Fmpz_poly) + cdef Fmpz_poly R = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_divrem(Q.poly, R.poly, self.poly, other.poly) return Q, R @@ -337,7 +337,7 @@ cdef class Fmpz_poly(SageObject): sage: f.left_shift(1).list() == [0,1,2] True """ - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_shift_left(res.poly, self.poly, n) @@ -354,7 +354,7 @@ cdef class Fmpz_poly(SageObject): sage: f.right_shift(1).list() == [2] True """ - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_shift_right(res.poly, self.poly, n) @@ -362,14 +362,14 @@ cdef class Fmpz_poly(SageObject): def pseudo_div(self, Fmpz_poly other): cdef ulong d - cdef Fmpz_poly Q = PY_NEW(Fmpz_poly) + cdef Fmpz_poly Q = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_pseudo_div(Q.poly, &d, self.poly, other.poly) return Q, d def pseudo_div_rem(self, Fmpz_poly other): cdef ulong d - cdef Fmpz_poly Q = PY_NEW(Fmpz_poly) - cdef Fmpz_poly R = PY_NEW(Fmpz_poly) + cdef Fmpz_poly Q = Fmpz_poly.__new__(Fmpz_poly) + cdef Fmpz_poly R = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_pseudo_divrem(Q.poly, R.poly, &d, self.poly, other.poly) return Q, R, d @@ -384,14 +384,14 @@ cdef class Fmpz_poly(SageObject): sage: f.derivative().list() == [2, 12] True """ - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_derivative(res.poly, self.poly) return res def __copy__(self): - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) fmpz_poly_set(res.poly, self.poly) return res diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index b607018884e..d8ac1aac73c 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -1869,7 +1869,7 @@ cdef class GapElement_String(GapElement): libgap_exit() return s - + __str__ = sage ############################################################################ ### GapElement_Function #################################################### diff --git a/src/sage/libs/gap/libgap.pyx b/src/sage/libs/gap/libgap.pyx index 32cdfa09753..75032d46755 100644 --- a/src/sage/libs/gap/libgap.pyx +++ b/src/sage/libs/gap/libgap.pyx @@ -249,6 +249,7 @@ from sage.structure.parent cimport Parent from sage.structure.element cimport ModuleElement, RingElement from sage.rings.all import ZZ from sage.misc.cachefunc import cached_method +from sage.misc.superseded import deprecated_function_alias from sage.libs.gap.element cimport * @@ -567,7 +568,7 @@ class Gap(Parent): """ return self(0) - def zero_element(self): + def zero(self): """ Return (integer) zero in GAP. @@ -577,11 +578,19 @@ class Gap(Parent): EXAMPLES:: + sage: libgap.zero() + 0 + + TESTS:: + sage: libgap.zero_element() + doctest:...: DeprecationWarning: zero_element is deprecated. Please use zero instead. + See http://trac.sagemath.org/17694 for details. 0 """ return self(0) + zero_element = deprecated_function_alias(17694, zero) def __init__(self): r""" diff --git a/src/sage/libs/gap/util.pyx b/src/sage/libs/gap/util.pyx index aca815b3e73..e3f2c9e9055 100644 --- a/src/sage/libs/gap/util.pyx +++ b/src/sage/libs/gap/util.pyx @@ -12,12 +12,10 @@ Utility functions for libGAP ############################################################################### from sage.env import SAGE_LOCAL -from sage.misc.misc import is_64_bit from libc.stdint cimport uintptr_t from element cimport * - ############################################################################ ### Hooking into the GAP memory management ################################# ############################################################################ diff --git a/src/sage/libs/lrcalc/lrcalc.pyx b/src/sage/libs/lrcalc/lrcalc.pyx index a7fc39849e9..1d8f3f31ab3 100644 --- a/src/sage/libs/lrcalc/lrcalc.pyx +++ b/src/sage/libs/lrcalc/lrcalc.pyx @@ -376,7 +376,9 @@ def lrcoef_unsafe(outer, inner1, inner2): 0 """ cdef long long result - cdef vector *o, *i1, *i2 + cdef vector *o + cdef vector *i1 + cdef vector *i2 o = iterable_to_vector(outer) i1 = iterable_to_vector(inner1) i2 = iterable_to_vector(inner2) diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index 872a8ac7236..39122a3a9fd 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -216,12 +216,12 @@ cdef binop(int op, x, y, MPopts opts): if op == OP_ADD: if typx == 1 and typy == 1: # Real result - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_add(&rr.value, &xre, &yre, opts) return rr else: # Complex result - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_add(&rc.re, &xre, &yre, opts) if typx == 1: MPF_set(&rc.im, &yim) @@ -236,12 +236,12 @@ cdef binop(int op, x, y, MPopts opts): elif op == OP_SUB: if typx == 1 and typy == 1: # Real result - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_sub(&rr.value, &xre, &yre, opts) return rr else: # Complex result - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_sub(&rc.re, &xre, &yre, opts) if typx == 1: MPF_neg(&rc.im, &yim) @@ -256,12 +256,12 @@ cdef binop(int op, x, y, MPopts opts): elif op == OP_MUL: if typx == 1 and typy == 1: # Real result - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_mul(&rr.value, &xre, &yre, opts) return rr else: # Complex result - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) if typx == 1: MPF_mul(&rc.re, &yre, &xre, opts) MPF_mul(&rc.im, &yim, &xre, opts) @@ -283,11 +283,11 @@ cdef binop(int op, x, y, MPopts opts): elif op == OP_DIV: if typx == 1 and typy == 1: # Real result - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_div(&rr.value, &xre, &yre, opts) return rr else: - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) if typy == 1: MPF_div(&rc.re, &xre, &yre, opts) MPF_div(&rc.im, &xim, &yre, opts) @@ -314,12 +314,12 @@ cdef binop(int op, x, y, MPopts opts): elif op == OP_POW: if typx == 1 and typy == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) if not MPF_pow(&rr.value, &xre, &yre, opts): return rr if typx == 1: xim = MPF_C_0 if typy == 1: yim = MPF_C_0 - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_complex_pow(&rc.re, &rc.im, &xre, &xim, &yre, &yim, opts) return rc @@ -329,7 +329,7 @@ cdef binop(int op, x, y, MPopts opts): xret = MPF_to_tuple(&xre) yret = MPF_to_tuple(&yre) v = libmp.mpf_mod(xret, yret, opts.prec, rndmode_to_python(opts.rounding)) - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_set_tuple(&rr.value, v) return rr @@ -499,7 +499,7 @@ cdef class Context: 0.5 """ cdef mpf x - x = PY_NEW(mpf) + x = mpf.__new__(mpf) MPF_set_tuple(&x.value, v) return x @@ -512,7 +512,7 @@ cdef class Context: (0.5-0.25j) """ cdef mpc x - x = PY_NEW(mpc) + x = mpc.__new__(mpc) MPF_set_tuple(&x.re, v[0]) MPF_set_tuple(&x.im, v[1]) return x @@ -547,11 +547,11 @@ cdef class Context: return x typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, strings) if typx == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_set(&rr.value, &tmp_opx_re) return rr if typx == 2: - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set(&rc.re, &tmp_opx_re) MPF_set(&rc.im, &tmp_opx_im) return rc @@ -817,7 +817,7 @@ cdef class Context: MPF_clear(&tre) MPF_clear(&tim) if styp == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_set(&rr.value, &sre) MPF_clear(&sre) MPF_clear(&sim) @@ -826,7 +826,7 @@ cdef class Context: return ctx._stupid_add(rr, unknown) return rr elif styp == 2: - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set(&rc.re, &sre) MPF_set(&rc.im, &sim) MPF_clear(&sre) @@ -932,7 +932,7 @@ cdef class Context: MPF_clear(&uim) MPF_clear(&tmp) if styp == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_set(&rr.value, &sre) MPF_clear(&sre) MPF_clear(&sim) @@ -941,7 +941,7 @@ cdef class Context: return ctx._stupid_add(rr, unknown) return rr elif styp == 2: - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set(&rc.re, &sre) MPF_set(&rc.im, &sim) MPF_clear(&sre) @@ -1207,14 +1207,14 @@ cdef class Context: opts = ctx._fun_get_opts(kwargs) typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1) if typx == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) if MPF_sqrt(&rr.value, &tmp_opx_re, opts): - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &MPF_C_0, opts) return rc return rr elif typx == 2: - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) return rc else: @@ -1243,11 +1243,11 @@ cdef class Context: opts = ctx._fun_get_opts(kwargs) typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1) if typx == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_exp(&rr.value, &tmp_opx_re, opts) return rr elif typx == 2: - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_complex_exp(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) return rc else: @@ -1275,7 +1275,7 @@ cdef class Context: opts = ctx._fun_get_opts(kwargs) typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) if typx == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_cos(&rr.value, &tmp_opx_re, opts) return rr elif typx == 2: @@ -1283,7 +1283,7 @@ cdef class Context: imv = MPF_to_tuple(&tmp_opx_im) cxu = libmp.mpc_cos((rev, imv), opts.prec, rndmode_to_python(opts.rounding)) - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set_tuple(&rc.re, cxu[0]) MPF_set_tuple(&rc.im, cxu[1]) return rc @@ -1312,7 +1312,7 @@ cdef class Context: opts = ctx._fun_get_opts(kwargs) typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1) if typx == 1: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_sin(&rr.value, &tmp_opx_re, opts) return rr elif typx == 2: @@ -1320,7 +1320,7 @@ cdef class Context: imv = MPF_to_tuple(&tmp_opx_im) cxu = libmp.mpc_sin((rev, imv), opts.prec, rndmode_to_python(opts.rounding)) - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set_tuple(&rc.re, cxu[0]) MPF_set_tuple(&rc.im, cxu[1]) return rc @@ -1358,24 +1358,24 @@ cdef class Context: if 'rounding' in kwargs: opts.rounding = rndmode_from_python(kwargs['rounding']) if typx == 1: if MPF_sgn(&tmp_opx_re) < 0: - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_log(&rc.re, &tmp_opx_re, opts) MPF_set_pi(&rc.im, opts) return rc else: - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_log(&rr.value, &tmp_opx_re, opts) return rr elif typx == 2: rev = MPF_to_tuple(&tmp_opx_re) imv = MPF_to_tuple(&tmp_opx_im) cxu = libmp.mpc_log((rev, imv), opts.prec, rndmode_to_python(opts.rounding)) - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set_tuple(&rc.re, cxu[0]) MPF_set_tuple(&rc.im, cxu[1]) return rc - #rc = PY_NEW(mpc) + #rc = mpc.__new__(mpc) #MPF_complex_log(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts) #return rc else: @@ -1446,14 +1446,14 @@ cdef class wrapped_libmp_function: rev = MPF_to_tuple(&tmp_opx_re) try: reu = self.mpf_f(rev, prec, rounding) - rr = PY_NEW(mpf) + rr = mpf.__new__(mpf) MPF_set_tuple(&rr.value, reu) return rr except libmp.ComplexResult: if global_context.trap_complex: raise cxu = self.mpc_f((rev, libmp.fzero), prec, rounding) - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set_tuple(&rc.re, cxu[0]) MPF_set_tuple(&rc.im, cxu[1]) return rc @@ -1461,7 +1461,7 @@ cdef class wrapped_libmp_function: rev = MPF_to_tuple(&tmp_opx_re) imv = MPF_to_tuple(&tmp_opx_im) cxu = self.mpc_f((rev, imv), prec, rounding) - rc = PY_NEW(mpc) + rc = mpc.__new__(mpc) MPF_set_tuple(&rc.re, cxu[0]) MPF_set_tuple(&rc.im, cxu[1]) return rc @@ -2116,7 +2116,7 @@ cdef class mpf(mpf_base): sage: -mpf(2) mpf('-2.0') """ - cdef mpf r = PY_NEW(mpf) + cdef mpf r = mpf.__new__(mpf) MPF_neg(&r.value, &s.value) MPF_normalize(&r.value, global_opts) return r @@ -2136,7 +2136,7 @@ cdef class mpf(mpf_base): sage: print +x 0.333333333333333 """ - cdef mpf r = PY_NEW(mpf) + cdef mpf r = mpf.__new__(mpf) MPF_set(&r.value, &s.value) MPF_normalize(&r.value, global_opts) return r @@ -2150,7 +2150,7 @@ cdef class mpf(mpf_base): sage: abs(mpf(-2)) mpf('2.0') """ - cdef mpf r = PY_NEW(mpf) + cdef mpf r = mpf.__new__(mpf) MPF_abs(&r.value, &s.value) MPF_normalize(&r.value, global_opts) return r @@ -2164,7 +2164,7 @@ cdef class mpf(mpf_base): sage: mpf(2).sqrt() mpf('1.4142135623730951') """ - cdef mpf r = PY_NEW(mpf) + cdef mpf r = mpf.__new__(mpf) MPF_sqrt(&r.value, &s.value, global_opts) return r @@ -2510,7 +2510,7 @@ cdef class mpc(mpnumber): sage: mp.mpc(1,2).real mpf('1.0') """ - cdef mpf r = PY_NEW(mpf) + cdef mpf r = mpf.__new__(mpf) MPF_set(&r.value, &self.re) return r @@ -2523,7 +2523,7 @@ cdef class mpc(mpnumber): sage: mp.mpc(1,2).imag mpf('2.0') """ - cdef mpf r = PY_NEW(mpf) + cdef mpf r = mpf.__new__(mpf) MPF_set(&r.value, &self.im) return r @@ -2545,7 +2545,7 @@ cdef class mpc(mpnumber): sage: -mpc(1,2) mpc(real='-1.0', imag='-2.0') """ - cdef mpc r = PY_NEW(mpc) + cdef mpc r = mpc.__new__(mpc) MPF_neg(&r.re, &s.re) MPF_neg(&r.im, &s.im) MPF_normalize(&r.re, global_opts) @@ -2560,7 +2560,7 @@ cdef class mpc(mpnumber): sage: mpc(1,2).conjugate() mpc(real='1.0', imag='-2.0') """ - cdef mpc r = PY_NEW(mpc) + cdef mpc r = mpc.__new__(mpc) MPF_set(&r.re, &s.re) MPF_neg(&r.im, &s.im) MPF_normalize(&r.re, global_opts) @@ -2582,7 +2582,7 @@ cdef class mpc(mpnumber): sage: (+x).real.man 6004799503160661 """ - cdef mpc r = PY_NEW(mpc) + cdef mpc r = mpc.__new__(mpc) MPF_set(&r.re, &s.re) MPF_set(&r.im, &s.im) MPF_normalize(&r.re, global_opts) @@ -2597,7 +2597,7 @@ cdef class mpc(mpnumber): sage: abs(mpc(3,4)) mpf('5.0') """ - cdef mpf r = PY_NEW(mpf) + cdef mpf r = mpf.__new__(mpf) MPF_hypot(&r.value, &s.re, &s.im, global_opts) return r @@ -2634,13 +2634,13 @@ def hypsum_internal(int p, int q, param_types, str ztype, coeffs, z, """ cdef mpf f cdef mpc c - c = PY_NEW(mpc) + c = mpc.__new__(mpc) have_complex, magn = MPF_hypsum(&c.re, &c.im, p, q, param_types, \ ztype, coeffs, z, prec, wp, epsshift, magnitude_check, kwargs) if have_complex: v = c else: - f = PY_NEW(mpf) + f = mpf.__new__(mpf) MPF_set(&f.value, &c.re) v = f return v, have_complex, magn diff --git a/src/sage/libs/ntl/ntl_GF2.pyx b/src/sage/libs/ntl/ntl_GF2.pyx index b71c5d24322..f0c9e94e22e 100644 --- a/src/sage/libs/ntl/ntl_GF2.pyx +++ b/src/sage/libs/ntl/ntl_GF2.pyx @@ -121,7 +121,7 @@ cdef class ntl_GF2: sage: z*z 0 """ - cdef ntl_GF2 r = PY_NEW(ntl_GF2) + cdef ntl_GF2 r = ntl_GF2.__new__(ntl_GF2) if not PY_TYPE_CHECK(self, ntl_GF2): self = ntl_GF2(self) if not PY_TYPE_CHECK(other, ntl_GF2): @@ -147,7 +147,7 @@ cdef class ntl_GF2: other = ntl_GF2(other) if GF2_IsZero((other).x): raise ZeroDivisionError - r = PY_NEW(ntl_GF2) + r = ntl_GF2.__new__(ntl_GF2) GF2_div(r.x, (self).x, (other).x) return r @@ -164,7 +164,7 @@ cdef class ntl_GF2: sage: z-z 0 """ - cdef ntl_GF2 r = PY_NEW(ntl_GF2) + cdef ntl_GF2 r = ntl_GF2.__new__(ntl_GF2) if not PY_TYPE_CHECK(self, ntl_GF2): self = ntl_GF2(self) if not PY_TYPE_CHECK(other, ntl_GF2): @@ -185,7 +185,7 @@ cdef class ntl_GF2: sage: z+z 0 """ - cdef ntl_GF2 r = PY_NEW(ntl_GF2) + cdef ntl_GF2 r = ntl_GF2.__new__(ntl_GF2) if not PY_TYPE_CHECK(self, ntl_GF2): self = ntl_GF2(self) if not PY_TYPE_CHECK(other, ntl_GF2): @@ -202,7 +202,7 @@ cdef class ntl_GF2: sage: -o 1 """ - cdef ntl_GF2 r = PY_NEW(ntl_GF2) + cdef ntl_GF2 r = ntl_GF2.__new__(ntl_GF2) GF2_negate(r.x, self.x) return r diff --git a/src/sage/libs/ntl/ntl_GF2E.pyx b/src/sage/libs/ntl/ntl_GF2E.pyx index 817355a363c..ef81caeacda 100644 --- a/src/sage/libs/ntl/ntl_GF2E.pyx +++ b/src/sage/libs/ntl/ntl_GF2E.pyx @@ -56,7 +56,7 @@ def ntl_GF2E_random(ntl_GF2EContext_class ctx): cdef ntl_GF2E r ctx.restore_c() - r = PY_NEW(ntl_GF2E) + r = ntl_GF2E.__new__(ntl_GF2E) r.c = ctx r.x = GF2E_random() return r @@ -128,7 +128,7 @@ cdef class ntl_GF2E: ## the error checking in __init__ will prevent## ## you from constructing an ntl_GF2E ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_GF2E) without ## + ## could do r = ntl_GF2E.__new__(ntl_GF2E) without ## first restoring a GF2EContext, which could ## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -152,7 +152,7 @@ cdef class ntl_GF2E: cdef ntl_GF2E _new(self): cdef ntl_GF2E r self.c.restore_c() - r = PY_NEW(ntl_GF2E) + r = ntl_GF2E.__new__(ntl_GF2E) r.c = self.c return r @@ -369,7 +369,7 @@ cdef class ntl_GF2E: sage: y.trace() 1 """ - cdef ntl_GF2 x = PY_NEW(ntl_GF2) + cdef ntl_GF2 x = ntl_GF2.__new__(ntl_GF2) x.x = GF2E_trace(self.x) return x @@ -385,7 +385,7 @@ cdef class ntl_GF2E: sage: type(a.rep()) """ - cdef ntl_GF2X x = PY_NEW(ntl_GF2X) + cdef ntl_GF2X x = ntl_GF2X.__new__(ntl_GF2X) x.x = GF2E_rep(self.x) return x @@ -412,7 +412,7 @@ cdef class ntl_GF2E: l = [] for i from 0 <= i <= GF2X_deg(x): - b = PY_NEW(ntl_GF2) + b = ntl_GF2.__new__(ntl_GF2) b.x = GF2X_coeff(x,i) l.append(b) return l diff --git a/src/sage/libs/ntl/ntl_GF2EX.pyx b/src/sage/libs/ntl/ntl_GF2EX.pyx index 4a1d837a3d0..a12ff04c30a 100644 --- a/src/sage/libs/ntl/ntl_GF2EX.pyx +++ b/src/sage/libs/ntl/ntl_GF2EX.pyx @@ -60,7 +60,7 @@ cdef class ntl_GF2EX: ## the error checking in __init__ will prevent## ## you from constructing an ntl_GF2E ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_GF2E) without ## + ## could do r = ntl_GF2E.__new__(ntl_GF2E) without ## first restoring a GF2EContext, which could ## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -81,14 +81,14 @@ cdef class ntl_GF2EX: cdef ntl_GF2E _new_element(self): cdef ntl_GF2E r self.c.restore_c() - r = PY_NEW(ntl_GF2E) + r = ntl_GF2E.__new__(ntl_GF2E) r.c = self.c return r cdef ntl_GF2EX _new(self): cdef ntl_GF2EX r self.c.restore_c() - r = PY_NEW(ntl_GF2EX) + r = ntl_GF2EX.__new__(ntl_GF2EX) r.c = self.c return r diff --git a/src/sage/libs/ntl/ntl_GF2X.pyx b/src/sage/libs/ntl/ntl_GF2X.pyx index 68a49323ef4..9f9de28ea8d 100644 --- a/src/sage/libs/ntl/ntl_GF2X.pyx +++ b/src/sage/libs/ntl/ntl_GF2X.pyx @@ -190,7 +190,7 @@ cdef class ntl_GF2X: sage: f*g ## indirect doctest [0 1 0 1 1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(other, ntl_GF2X): other = ntl_GF2X(other) GF2X_mul(r.x, self.x, (other).x) @@ -207,7 +207,7 @@ cdef class ntl_GF2X: ... ArithmeticError: self (=[0 0 1]) is not divisible by b (=[1 1]) """ - cdef ntl_GF2X q = PY_NEW(ntl_GF2X) + cdef ntl_GF2X q = ntl_GF2X.__new__(ntl_GF2X) cdef int divisible if not PY_TYPE_CHECK(b, ntl_GF2X): @@ -227,8 +227,8 @@ cdef class ntl_GF2X: sage: a.DivRem( ntl.GF2X(3) ) ([1 1], [1]) """ - cdef ntl_GF2X q = PY_NEW(ntl_GF2X) - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X q = ntl_GF2X.__new__(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(b, ntl_GF2X): b = ntl_GF2X(b) @@ -245,7 +245,7 @@ cdef class ntl_GF2X: sage: a // ntl.GF2X(3) [1 1] """ - cdef ntl_GF2X q = PY_NEW(ntl_GF2X) + cdef ntl_GF2X q = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(b, ntl_GF2X): b = ntl_GF2X(b) @@ -262,7 +262,7 @@ cdef class ntl_GF2X: sage: a % ntl.GF2X(3) [1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(b, ntl_GF2X): b = ntl_GF2X(b) @@ -279,7 +279,7 @@ cdef class ntl_GF2X: sage: g - f [1 1 1 1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(other, ntl_GF2X): other = ntl_GF2X(other) GF2X_sub(r.x, self.x, (other).x) @@ -292,7 +292,7 @@ cdef class ntl_GF2X: sage: f + g ## indirect doctest [1 1 1 1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(other, ntl_GF2X): other = ntl_GF2X(other) GF2X_add(r.x, self.x, (other).x) @@ -307,7 +307,7 @@ cdef class ntl_GF2X: sage: f == -f True """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) GF2X_negate(r.x, self.x) return r @@ -318,7 +318,7 @@ cdef class ntl_GF2X: sage: f**3 ## indirect doctest [1 0 1 1 1 0 0 1 1 1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) GF2X_power(r.x, self.x, e) return r @@ -362,7 +362,7 @@ cdef class ntl_GF2X: sage: a << 2 [0 0 0 0 1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) GF2X_LeftShift(r.x, self.x, i) return r @@ -380,7 +380,7 @@ cdef class ntl_GF2X: sage: a >> 1 [0 1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) GF2X_RightShift(r.x, self.x, offset) return r @@ -397,7 +397,7 @@ cdef class ntl_GF2X: sage: a.GCD(b) [0 1] """ - cdef ntl_GF2X gcd = PY_NEW(ntl_GF2X) + cdef ntl_GF2X gcd = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(other, ntl_GF2X): other = ntl_GF2X(other) @@ -422,9 +422,9 @@ cdef class ntl_GF2X: True """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) - cdef ntl_GF2X s = PY_NEW(ntl_GF2X) - cdef ntl_GF2X t = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) + cdef ntl_GF2X s = ntl_GF2X.__new__(ntl_GF2X) + cdef ntl_GF2X t = ntl_GF2X.__new__(ntl_GF2X) if not PY_TYPE_CHECK(other, ntl_GF2X): other = ntl_GF2X(other) @@ -550,7 +550,7 @@ cdef class ntl_GF2X: sage: e.coeff(1) 1 """ - cdef ntl_GF2 c = PY_NEW(ntl_GF2) + cdef ntl_GF2 c = ntl_GF2.__new__(ntl_GF2) c.x = GF2X_coeff(self.x, i) return c @@ -562,7 +562,7 @@ cdef class ntl_GF2X: sage: e[1] 1 """ - cdef ntl_GF2 c = PY_NEW(ntl_GF2) + cdef ntl_GF2 c = ntl_GF2.__new__(ntl_GF2) c.x = GF2X_coeff(self.x, i) return c @@ -579,7 +579,7 @@ cdef class ntl_GF2X: sage: e.LeadCoeff() 0 """ - cdef ntl_GF2 c = PY_NEW(ntl_GF2) + cdef ntl_GF2 c = ntl_GF2.__new__(ntl_GF2) c.x = GF2X_LeadCoeff(self.x) return c @@ -595,7 +595,7 @@ cdef class ntl_GF2X: sage: e.ConstTerm() 0 """ - cdef ntl_GF2 c = PY_NEW(ntl_GF2) + cdef ntl_GF2 c = ntl_GF2.__new__(ntl_GF2) c.x = GF2X_ConstTerm (self.x) return c @@ -632,7 +632,7 @@ cdef class ntl_GF2X: sage: e.diff() [0 0 1] """ - cdef ntl_GF2X d = PY_NEW(ntl_GF2X) + cdef ntl_GF2X d = ntl_GF2X.__new__(ntl_GF2X) d.x = GF2X_diff(self.x) return d @@ -649,7 +649,7 @@ cdef class ntl_GF2X: sage: e.reverse() [1 1 0 1] """ - cdef ntl_GF2X r = PY_NEW(ntl_GF2X) + cdef ntl_GF2X r = ntl_GF2X.__new__(ntl_GF2X) if hi < -1: hi = GF2X_deg(self.x) r.x = GF2X_reverse(self.x, hi) diff --git a/src/sage/libs/ntl/ntl_ZZ.pyx b/src/sage/libs/ntl/ntl_ZZ.pyx index 4af184c3d2c..433175858c8 100644 --- a/src/sage/libs/ntl/ntl_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_ZZ.pyx @@ -168,7 +168,7 @@ cdef class ntl_ZZ: sage: n 5966 """ - cdef ntl_ZZ r = PY_NEW(ntl_ZZ) + cdef ntl_ZZ r = ntl_ZZ.__new__(ntl_ZZ) if not PY_TYPE_CHECK(self, ntl_ZZ): self = ntl_ZZ(self) if not PY_TYPE_CHECK(other, ntl_ZZ): @@ -186,7 +186,7 @@ cdef class ntl_ZZ: sage: ntl.ZZ(2983)-2 2981 """ - cdef ntl_ZZ r = PY_NEW(ntl_ZZ) + cdef ntl_ZZ r = ntl_ZZ.__new__(ntl_ZZ) if not PY_TYPE_CHECK(self, ntl_ZZ): self = ntl_ZZ(self) if not PY_TYPE_CHECK(other, ntl_ZZ): @@ -202,7 +202,7 @@ cdef class ntl_ZZ: sage: ntl.ZZ(23)+2 25 """ - cdef ntl_ZZ r = PY_NEW(ntl_ZZ) + cdef ntl_ZZ r = ntl_ZZ.__new__(ntl_ZZ) if not PY_TYPE_CHECK(self, ntl_ZZ): self = ntl_ZZ(self) if not PY_TYPE_CHECK(other, ntl_ZZ): @@ -218,7 +218,7 @@ cdef class ntl_ZZ: sage: x.__neg__() -38 """ - cdef ntl_ZZ r = PY_NEW(ntl_ZZ) + cdef ntl_ZZ r = ntl_ZZ.__new__(ntl_ZZ) ZZ_negate(r.x, self.x) return r @@ -341,8 +341,8 @@ cdef class ntl_ZZ: sage: b.valuation(p) +Infinity """ - cdef ntl_ZZ ans = PY_NEW(ntl_ZZ) - cdef ntl_ZZ unit = PY_NEW(ntl_ZZ) + cdef ntl_ZZ ans = ntl_ZZ.__new__(ntl_ZZ) + cdef ntl_ZZ unit = ntl_ZZ.__new__(ntl_ZZ) cdef long valuation if ZZ_IsZero(self.x): from sage.rings.infinity import infinity @@ -367,8 +367,8 @@ cdef class ntl_ZZ: sage: a.val_unit(ntl.ZZ(2)) (0, 6328125) """ - cdef ntl_ZZ val = PY_NEW(ntl_ZZ) - cdef ntl_ZZ unit = PY_NEW(ntl_ZZ) + cdef ntl_ZZ val = ntl_ZZ.__new__(ntl_ZZ) + cdef ntl_ZZ unit = ntl_ZZ.__new__(ntl_ZZ) cdef long valuation sig_on() valuation = ZZ_remove(unit.x, self.x, prime.x) @@ -461,7 +461,7 @@ def randomBnd(q): q = ntl_ZZ(str(q)) w = q cdef ntl_ZZ ans - ans = PY_NEW(ntl_ZZ) + ans = ntl_ZZ.__new__(ntl_ZZ) sig_on() ZZ_RandomBnd(ans.x, w.x) sig_off() @@ -481,7 +481,7 @@ def randomBits(long n): current_randstate().set_seed_ntl(False) cdef ntl_ZZ ans - ans = PY_NEW(ntl_ZZ) + ans = ntl_ZZ.__new__(ntl_ZZ) sig_on() ZZ_RandomBits(ans.x, n) sig_off() diff --git a/src/sage/libs/ntl/ntl_ZZX.pyx b/src/sage/libs/ntl/ntl_ZZX.pyx index 57d8098149a..47b6d9551cf 100644 --- a/src/sage/libs/ntl/ntl_ZZX.pyx +++ b/src/sage/libs/ntl/ntl_ZZX.pyx @@ -283,7 +283,7 @@ cdef class ntl_ZZX: sage: ntl.ZZX(range(5)) + ntl.ZZX(range(6)) [0 2 4 6 8 5] """ - cdef ntl_ZZX r = PY_NEW(ntl_ZZX) + cdef ntl_ZZX r = ntl_ZZX.__new__(ntl_ZZX) if not PY_TYPE_CHECK(self, ntl_ZZX): self = ntl_ZZX(self) if not PY_TYPE_CHECK(other, ntl_ZZX): @@ -297,7 +297,7 @@ cdef class ntl_ZZX: sage: ntl.ZZX(range(5)) - ntl.ZZX(range(6)) [0 0 0 0 0 -5] """ - cdef ntl_ZZX r = PY_NEW(ntl_ZZX) + cdef ntl_ZZX r = ntl_ZZX.__new__(ntl_ZZX) if not PY_TYPE_CHECK(self, ntl_ZZX): self = ntl_ZZX(self) if not PY_TYPE_CHECK(other, ntl_ZZX): @@ -311,7 +311,7 @@ cdef class ntl_ZZX: sage: ntl.ZZX(range(5)) * ntl.ZZX(range(6)) [0 0 1 4 10 20 30 34 31 20] """ - cdef ntl_ZZX r = PY_NEW(ntl_ZZX) + cdef ntl_ZZX r = ntl_ZZX.__new__(ntl_ZZX) if not PY_TYPE_CHECK(self, ntl_ZZX): self = ntl_ZZX(self) if not PY_TYPE_CHECK(other, ntl_ZZX): @@ -367,7 +367,7 @@ cdef class ntl_ZZX: sage: f % g [20 25] """ - cdef ntl_ZZX r = PY_NEW(ntl_ZZX) + cdef ntl_ZZX r = ntl_ZZX.__new__(ntl_ZZX) if not PY_TYPE_CHECK(self, ntl_ZZX): self = ntl_ZZX(self) if not PY_TYPE_CHECK(other, ntl_ZZX): @@ -391,7 +391,8 @@ cdef class ntl_ZZX: sage: q*g + r == f True """ - cdef ZZX_c *r, *q + cdef ZZX_c *r + cdef ZZX_c *q sig_on() try: ZZX_quo_rem(&self.x, &other.x, &r, &q) @@ -563,7 +564,7 @@ cdef class ntl_ZZX: sage: f.content() 0 """ - cdef ntl_ZZ r = PY_NEW(ntl_ZZ) + cdef ntl_ZZ r = ntl_ZZ.__new__(ntl_ZZ) ZZX_content(r.x, self.x) return r @@ -605,7 +606,8 @@ cdef class ntl_ZZX: sage: g.pseudo_quo_rem(f) ([-1 3], [2]) """ - cdef ZZX_c *r, *q + cdef ZZX_c *r + cdef ZZX_c *q sig_on() try: ZZX_pseudo_quo_rem(&self.x, &other.x, &r, &q) @@ -675,7 +677,8 @@ cdef class ntl_ZZX: """ proof = proof_flag(proof) - cdef ZZX_c *s, *t + cdef ZZX_c *s + cdef ZZX_c *t cdef ZZ_c *r sig_on() try: @@ -717,7 +720,7 @@ cdef class ntl_ZZX: sage: f.leading_coefficient() 0 """ - cdef ntl_ZZ r = PY_NEW(ntl_ZZ) + cdef ntl_ZZ r = ntl_ZZ.__new__(ntl_ZZ) r.x = ZZX_LeadCoeff(self.x) return r @@ -733,7 +736,7 @@ cdef class ntl_ZZX: sage: f.constant_term() 0 """ - cdef ntl_ZZ r = PY_NEW(ntl_ZZ) + cdef ntl_ZZ r = ntl_ZZ.__new__(ntl_ZZ) r.x = ZZX_ConstTerm(self.x) return r diff --git a/src/sage/libs/ntl/ntl_ZZ_p.pyx b/src/sage/libs/ntl/ntl_ZZ_p.pyx index 82ab0ff1fd1..de0b203a735 100644 --- a/src/sage/libs/ntl/ntl_ZZ_p.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_p.pyx @@ -127,7 +127,7 @@ cdef class ntl_ZZ_p: ## the error checking in __init__ will prevent## ## you from constructing an ntl_ZZ_p ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_ZZ_p) without ## + ## could do r = ntl_ZZ_p.__new__(ntl_ZZ_p) without ## first restoring a ZZ_pContext, which could ## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -152,7 +152,7 @@ cdef class ntl_ZZ_p: cdef ntl_ZZ_p _new(self): cdef ntl_ZZ_p r self.c.restore_c() - r = PY_NEW(ntl_ZZ_p) + r = ntl_ZZ_p.__new__(ntl_ZZ_p) r.c = self.c return r diff --git a/src/sage/libs/ntl/ntl_ZZ_pE.pyx b/src/sage/libs/ntl/ntl_ZZ_pE.pyx index 637c68c5f72..3eecd6f16da 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pE.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pE.pyx @@ -150,7 +150,7 @@ cdef class ntl_ZZ_pE: ## the error checking in __init__ will prevent## ## you from constructing an ntl_ZZ_pE ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_ZZ_pE) without ## + ## could do r = ntl_ZZ_pE.__new__(ntl_ZZ_pE) without ## first restoring a ZZ_pEContext, which could## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -175,7 +175,7 @@ cdef class ntl_ZZ_pE: cdef ntl_ZZ_pE _new(self): cdef ntl_ZZ_pE r self.c.restore_c() - r = PY_NEW(ntl_ZZ_pE) + r = ntl_ZZ_pE.__new__(ntl_ZZ_pE) r.c = self.c return r @@ -298,7 +298,7 @@ cdef class ntl_ZZ_pE: Returns value as ntl_ZZ_pX. """ self.c.restore_c() - cdef ntl_ZZ_pX y = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX y = ntl_ZZ_pX.__new__(ntl_ZZ_pX) y.c = self.c.pc sig_on() y.x = ZZ_pE_to_ZZ_pX(self.x) diff --git a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx index 44d66cacf0a..15b33c65464 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx @@ -102,7 +102,7 @@ cdef class ntl_ZZ_pEX: ## the error checking in __init__ will prevent## ## you from constructing an ntl_ZZ_pEX ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_ZZ_pEX) without ## + ## could do r = ntl_ZZ_pEX.__new__(ntl_ZZ_pEX) without ## first restoring a ZZ_pEContext, which could## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -138,7 +138,7 @@ cdef class ntl_ZZ_pEX: cdef ntl_ZZ_pEX _new(self): cdef ntl_ZZ_pEX r self.c.restore_c() - r = PY_NEW(ntl_ZZ_pEX) + r = ntl_ZZ_pEX.__new__(ntl_ZZ_pEX) r.c = self.c return r @@ -249,7 +249,7 @@ cdef class ntl_ZZ_pEX: cdef ntl_ZZ_pE r sig_on() self.c.restore_c() - r = PY_NEW(ntl_ZZ_pE) + r = ntl_ZZ_pE.__new__(ntl_ZZ_pE) r.c = self.c r.x = ZZ_pEX_coeff( self.x, i) sig_off() @@ -596,7 +596,7 @@ cdef class ntl_ZZ_pEX: """ cdef ntl_ZZ_pEContext_class cE = ntl_ZZ_pEContext(self.c.f.convert_to_modulus(c)) cE.restore_c() - cdef ntl_ZZ_pEX ans = PY_NEW(ntl_ZZ_pEX) + cdef ntl_ZZ_pEX ans = ntl_ZZ_pEX.__new__(ntl_ZZ_pEX) sig_on() ZZ_pEX_conv_modulus(ans.x, self.x, c.x) sig_off() diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index a25073d82e2..7d70f587a7a 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -37,7 +37,7 @@ cdef inline make_ZZ_p(ZZ_p_c* x, ntl_ZZ_pContext_class ctx): cdef make_ZZ_pX(ZZ_pX_c* x, ntl_ZZ_pContext_class ctx): cdef ntl_ZZ_pX y - y = PY_NEW(ntl_ZZ_pX) + y = ntl_ZZ_pX.__new__(ntl_ZZ_pX) y.c = ctx y.x = x[0] ZZ_pX_delete(x) @@ -110,7 +110,7 @@ cdef class ntl_ZZ_pX: ## the error checking in __init__ will prevent## ## you from constructing an ntl_ZZ_p ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_ZZ_p) without ## + ## could do r = ntl_ZZ_p.__new__(ntl_ZZ_p) without ## first restoring a ZZ_pContext, which could ## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -135,7 +135,7 @@ cdef class ntl_ZZ_pX: cdef ntl_ZZ_pX _new(self): cdef ntl_ZZ_pX r self.c.restore_c() - r = PY_NEW(ntl_ZZ_pX) + r = ntl_ZZ_pX.__new__(ntl_ZZ_pX) #ZZ_pX_construct(&r.x) r.c = self.c return r @@ -255,7 +255,7 @@ cdef class ntl_ZZ_pX: 3 """ cdef ntl_ZZ_p r - r = PY_NEW(ntl_ZZ_p) + r = ntl_ZZ_p.__new__(ntl_ZZ_p) r.c = self.c self.c.restore_c() if i < 0: @@ -661,11 +661,11 @@ cdef class ntl_ZZ_pX: """ Multiplies all coefficients by n and the context by n. """ - cdef ntl_ZZ new_c_p = PY_NEW(ntl_ZZ) + cdef ntl_ZZ new_c_p = ntl_ZZ.__new__(ntl_ZZ) ZZ_mul(new_c_p.x, (self.c.p).x, n.x) cdef ntl_ZZ_pContext_class new_c = ntl_ZZ_pContext(new_c_p) new_c.restore_c() - cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX) ans.c = new_c ZZ_pX_left_pshift(ans.x, self.x, n.x, new_c.x) return ans @@ -674,11 +674,11 @@ cdef class ntl_ZZ_pX: """ Divides all coefficients by n and the context by n. Only really makes sense when n divides self.c.p """ - cdef ntl_ZZ new_c_p = PY_NEW(ntl_ZZ) + cdef ntl_ZZ new_c_p = ntl_ZZ.__new__(ntl_ZZ) ZZ_div(new_c_p.x, (self.c.p).x, n.x) cdef ntl_ZZ_pContext_class new_c = ntl_ZZ_pContext(new_c_p) new_c.restore_c() - cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX) ans.c = new_c ZZ_pX_right_pshift(ans.x, self.x, n.x, new_c.x) return ans @@ -874,7 +874,7 @@ cdef class ntl_ZZ_pX: [1 9 8 24 6] """ c.restore_c() - cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX) ZZ_pX_construct(&ans.x) ZZ_pX_conv_modulus(ans.x, self.x, c.x) ans.c = c @@ -984,7 +984,7 @@ cdef class ntl_ZZ_pX: sig_off() F = [] for i from 0 <= i < n: - r = PY_NEW(ntl_ZZ_p) + r = ntl_ZZ_p.__new__(ntl_ZZ_p) r.c = self.c r.x = v[i][0] F.append(r) @@ -1158,7 +1158,7 @@ cdef class ntl_ZZ_pX: raise ValueError, "not eisenstein or unramified" else: ctx = ntl_ZZ_pContext(p) - mod_prime = PY_NEW(ntl_ZZ_pX) + mod_prime = ntl_ZZ_pX.__new__(ntl_ZZ_pX) ZZ_pX_conv_modulus(mod_prime.x, modulus.x, ctx.x) mod_prime.c = ctx F = mod_prime.factor() @@ -1206,7 +1206,7 @@ cdef class ntl_ZZ_pX: 3 """ self.c.restore_c() - cdef ntl_ZZ_p r = PY_NEW(ntl_ZZ_p) + cdef ntl_ZZ_p r = ntl_ZZ_p.__new__(ntl_ZZ_p) r.c = self.c sig_on() ZZ_pX_TraceMod(r.x, self.x, modulus.x) @@ -1257,7 +1257,7 @@ cdef class ntl_ZZ_pX: 0 """ self.c.restore_c() - cdef ntl_ZZ_p r = PY_NEW(ntl_ZZ_p) + cdef ntl_ZZ_p r = ntl_ZZ_p.__new__(ntl_ZZ_p) r.c = self.c sig_on() ZZ_pX_resultant(r.x, self.x, other.x) @@ -1284,7 +1284,7 @@ cdef class ntl_ZZ_pX: [11 1 8 14 1] """ self.c.restore_c() - cdef ntl_ZZ_p r = PY_NEW(ntl_ZZ_p) + cdef ntl_ZZ_p r = ntl_ZZ_p.__new__(ntl_ZZ_p) r.c = self.c sig_on() ZZ_pX_NormMod(r.x, self.x, modulus.x) diff --git a/src/sage/libs/ntl/ntl_lzz_p.pyx b/src/sage/libs/ntl/ntl_lzz_p.pyx index 555012a9278..d7cf1f99891 100644 --- a/src/sage/libs/ntl/ntl_lzz_p.pyx +++ b/src/sage/libs/ntl/ntl_lzz_p.pyx @@ -125,7 +125,7 @@ cdef class ntl_zz_p: ## the error checking in __init__ will prevent## ## you from constructing a zz_p ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_zz_p) without ## + ## could do r = ntl_zz_p.__new__(ntl_zz_p) without ## first restoring a zz_pContext, which could ## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -165,7 +165,7 @@ cdef class ntl_zz_p: """ cdef ntl_zz_p y self.c.restore_c() - y = PY_NEW(ntl_zz_p) + y = ntl_zz_p.__new__(ntl_zz_p) y.c = self.c return y @@ -285,7 +285,7 @@ cdef class ntl_zz_p: if n == 0: return self elif n < 0: - y = PY_NEW(ntl_zz_p) + y = ntl_zz_p.__new__(ntl_zz_p) y.c = self.c zz_p_inv(y.x, self.x) return power(y, -n, ntl_zz_p(1,self.c)) diff --git a/src/sage/libs/ntl/ntl_lzz_pX.pyx b/src/sage/libs/ntl/ntl_lzz_pX.pyx index 1f713faab46..682054a2140 100644 --- a/src/sage/libs/ntl/ntl_lzz_pX.pyx +++ b/src/sage/libs/ntl/ntl_lzz_pX.pyx @@ -141,7 +141,7 @@ cdef class ntl_zz_pX: ## the error checking in __init__ will prevent## ## you from constructing a zz_pX ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_zz_pX) without ## + ## could do r = ntl_zz_pX.__new__(ntl_zz_pX) without ## first restoring a zz_pContext, which could ## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -207,7 +207,7 @@ cdef class ntl_zz_pX: 0 """ cdef ntl_zz_p y - y = PY_NEW(ntl_zz_p) + y = ntl_zz_p.__new__(ntl_zz_p) y.c = self.c self.c.restore_c() if not PY_TYPE_CHECK( i, long ): @@ -251,7 +251,7 @@ cdef class ntl_zz_pX: [1] """ cdef ntl_zz_pX y - y = PY_NEW(ntl_zz_pX) + y = ntl_zz_pX.__new__(ntl_zz_pX) y.c = self.c return y diff --git a/src/sage/libs/ntl/ntl_mat_GF2.pyx b/src/sage/libs/ntl/ntl_mat_GF2.pyx index b5690f4a5b0..17c86edc744 100644 --- a/src/sage/libs/ntl/ntl_mat_GF2.pyx +++ b/src/sage/libs/ntl/ntl_mat_GF2.pyx @@ -117,12 +117,12 @@ cdef class ntl_mat_GF2: cdef ntl_GF2 _new_element(self): cdef ntl_GF2 r - r = PY_NEW(ntl_GF2) + r = ntl_GF2.__new__(ntl_GF2) return r cdef ntl_mat_GF2 _new(self): cdef ntl_mat_GF2 r - r = PY_NEW(ntl_mat_GF2) + r = ntl_mat_GF2.__new__(ntl_mat_GF2) r.x.SetDims(self.x.NumRows(),self.x.NumCols()) return r diff --git a/src/sage/libs/ntl/ntl_mat_GF2E.pyx b/src/sage/libs/ntl/ntl_mat_GF2E.pyx index ae60edce5f4..aac1f995bf8 100644 --- a/src/sage/libs/ntl/ntl_mat_GF2E.pyx +++ b/src/sage/libs/ntl/ntl_mat_GF2E.pyx @@ -111,7 +111,7 @@ cdef class ntl_mat_GF2E: ## the error checking in __init__ will prevent## ## you from constructing an ntl_GF2E ## ## inappropriately. However, from Cython, you## - ## could do r = PY_NEW(ntl_GF2E) without ## + ## could do r = ntl_GF2E.__new__(ntl_GF2E) without ## first restoring a GF2EContext, which could ## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## @@ -132,14 +132,14 @@ cdef class ntl_mat_GF2E: cdef ntl_GF2E _new_element(self): cdef ntl_GF2E r self.c.restore_c() - r = PY_NEW(ntl_GF2E) + r = ntl_GF2E.__new__(ntl_GF2E) r.c = self.c return r cdef ntl_mat_GF2E _new(self): cdef ntl_mat_GF2E r self.c.restore_c() - r = PY_NEW(ntl_mat_GF2E) + r = ntl_mat_GF2E.__new__(ntl_mat_GF2E) r.x.SetDims(self.x.NumRows(),self.x.NumCols()) r.c = self.c return r diff --git a/src/sage/libs/ntl/ntl_mat_ZZ.pyx b/src/sage/libs/ntl/ntl_mat_ZZ.pyx index 4058d16d0d6..2988a41c4c4 100644 --- a/src/sage/libs/ntl/ntl_mat_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_mat_ZZ.pyx @@ -151,7 +151,7 @@ cdef class ntl_mat_ZZ: [1 22] ] """ - cdef ntl_mat_ZZ r = PY_NEW(ntl_mat_ZZ) + cdef ntl_mat_ZZ r = ntl_mat_ZZ.__new__(ntl_mat_ZZ) if not PY_TYPE_CHECK(self, ntl_mat_ZZ): self = ntl_mat_ZZ(self) if not PY_TYPE_CHECK(other, ntl_mat_ZZ): @@ -173,7 +173,7 @@ cdef class ntl_mat_ZZ: [9 9] ] """ - cdef ntl_mat_ZZ r = PY_NEW(ntl_mat_ZZ) + cdef ntl_mat_ZZ r = ntl_mat_ZZ.__new__(ntl_mat_ZZ) if not PY_TYPE_CHECK(self, ntl_mat_ZZ): self = ntl_mat_ZZ(self) if not PY_TYPE_CHECK(other, ntl_mat_ZZ): @@ -195,7 +195,7 @@ cdef class ntl_mat_ZZ: [11 13] ] """ - cdef ntl_mat_ZZ r = PY_NEW(ntl_mat_ZZ) + cdef ntl_mat_ZZ r = ntl_mat_ZZ.__new__(ntl_mat_ZZ) if not PY_TYPE_CHECK(self, ntl_mat_ZZ): self = ntl_mat_ZZ(self) if not PY_TYPE_CHECK(other, ntl_mat_ZZ): @@ -246,7 +246,7 @@ cdef class ntl_mat_ZZ: raise TypeError, "cannot take powers of non-square matrices." if e < 0: raise ValueError, "cannot take negative powers of matrices." - cdef ntl_mat_ZZ r = PY_NEW(ntl_mat_ZZ) + cdef ntl_mat_ZZ r = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() mat_ZZ_power(r.x, (self).x, e) sig_off() @@ -1215,7 +1215,7 @@ cdef class ntl_mat_ZZ: cdef ZZ_c *det2 cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_LLL_U(&det2, &self.x, &U.x, int(a), int(b), int(verbose))) return rank, make_ZZ_sig_off(det2), U @@ -1299,7 +1299,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_LLL_FP_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() @@ -1322,7 +1322,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_LLL_QP_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() @@ -1346,7 +1346,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_LLL_XD_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() @@ -1370,7 +1370,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_LLL_RR_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() @@ -1400,7 +1400,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_G_LLL_FP_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() @@ -1418,7 +1418,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_G_LLL_QP_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() @@ -1437,7 +1437,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_G_LLL_XD_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() @@ -1456,7 +1456,7 @@ cdef class ntl_mat_ZZ: """ cdef ntl_mat_ZZ U if return_U: - U = PY_NEW(ntl_mat_ZZ) + U = ntl_mat_ZZ.__new__(ntl_mat_ZZ) sig_on() rank = int(mat_ZZ_G_LLL_RR_U(self.x, U.x, float(delta), 0, 0, int(verbose))) sig_off() diff --git a/src/sage/libs/pari/all.py b/src/sage/libs/pari/all.py index 450bdfb7d79..7adf0d1b32b 100644 --- a/src/sage/libs/pari/all.py +++ b/src/sage/libs/pari/all.py @@ -1,2 +1,3 @@ -from gen import gen as pari_gen, PariError +from gen import gen as pari_gen from pari_instance import pari +from handle_error import PariError diff --git a/src/sage/libs/pari/decl.pxi b/src/sage/libs/pari/decl.pxi index 05259dfc8a4..2d6879d50f3 100644 --- a/src/sage/libs/pari/decl.pxi +++ b/src/sage/libs/pari/decl.pxi @@ -164,7 +164,8 @@ cdef extern from 'parisage.h': extern int INIT_JMPm, INIT_SIGm, INIT_DFTm extern int new_galois_format, precdl # The "except 0" here is to ensure compatibility with - # _pari_handle_exception() in handle_error.pyx + # _pari_err_handle() in handle_error.pyx + extern int (*cb_pari_err_handle)(GEN) except 0 extern int (*cb_pari_handle_exception)(long) except 0 extern void (*cb_pari_err_recover)(long) @@ -3756,3 +3757,6 @@ cdef extern from 'pari/paripriv.h': unsigned long flags extern gp_data* GP_DATA + +cdef extern from 'pari/anal.h': + char* closure_func_err() diff --git a/src/sage/libs/pari/gen.pyx b/src/sage/libs/pari/gen.pyx index 6cbfd2ab8c4..f3301ef9fbc 100644 --- a/src/sage/libs/pari/gen.pyx +++ b/src/sage/libs/pari/gen.pyx @@ -50,8 +50,6 @@ import sage.structure.element from sage.structure.element cimport ModuleElement, RingElement, Element from sage.misc.randstate cimport randstate, current_randstate -from sage.misc.misc_c import is_64_bit - include 'pari_err.pxi' include 'sage/ext/stdsage.pxi' include 'sage/ext/python.pxi' @@ -10006,85 +10004,6 @@ cdef GEN _Vec_append(GEN v, GEN a, long n): return v -# We derive PariError from RuntimeError, for backward compatibility with -# code that catches the latter. -class PariError(RuntimeError): - """ - Error raised by PARI - """ - def errnum(self): - r""" - Return the PARI error number corresponding to this exception. - - EXAMPLES:: - - sage: try: - ....: pari('1/0') - ....: except PariError as err: - ....: print err.errnum() - 30 - """ - return self.args[0] - - def errtext(self): - """ - Return the message output by PARI when this error occurred. - - EXAMPLE:: - - sage: try: - ....: pari('pi()') - ....: except PariError as e: - ....: print e.errtext() - ....: - *** at top-level: pi() - *** ^---- - *** not a function in function call - - """ - return self.args[1] - - def __repr__(self): - r""" - TESTS:: - - sage: PariError(11) - PariError(11) - """ - return "PariError(%d)"%self.errnum() - - def __str__(self): - r""" - Return a suitable message for displaying this exception. - - This is the last line of ``self.errtext()``, with the leading - ``" *** "`` and trailing periods and colons (if any) removed. - An exception is syntax errors, where the "syntax error" line is - shown. - - EXAMPLES:: - - sage: try: - ....: pari('1/0') - ....: except PariError as err: - ....: print err - _/_: impossible inverse in gdiv: 0 - - A syntax error:: - - sage: pari('!@#$%^&*()') - Traceback (most recent call last): - ... - PariError: syntax error, unexpected $undefined: !@#$%^&*() - """ - lines = self.errtext().split('\n') - if self.errnum() == e_SYNTAX: - for line in lines: - if "syntax error" in line: - return line.lstrip(" *").rstrip(" .:") - return lines[-1].lstrip(" *").rstrip(" .:") - - cdef _factor_int_when_pari_factor_failed(x, failed_factorization): """ This is called by factor when PARI's factor tried to factor, got diff --git a/src/sage/libs/pari/handle_error.pxd b/src/sage/libs/pari/handle_error.pxd index 80f80b06732..5cdd9604ff5 100644 --- a/src/sage/libs/pari/handle_error.pxd +++ b/src/sage/libs/pari/handle_error.pxd @@ -1,6 +1,5 @@ -cdef str pari_error_string +include 'sage/libs/pari/decl.pxi' cdef void _pari_init_error_handling() -cdef void _pari_check_warning "_pari_check_warning"() -cdef int _pari_handle_exception(long err) except 0 -cdef void _pari_err_recover(long err) +cdef int _pari_err_handle(GEN E) except 0 +cdef void _pari_err_recover(long errnum) diff --git a/src/sage/libs/pari/handle_error.pyx b/src/sage/libs/pari/handle_error.pyx index 101028bb100..42eb556afc1 100644 --- a/src/sage/libs/pari/handle_error.pyx +++ b/src/sage/libs/pari/handle_error.pyx @@ -3,57 +3,141 @@ Functions for handling PARI errors AUTHORS: -- Peter Bruin (September 2013): initial version (#9640) +- Peter Bruin (September 2013): initial version (:trac:`9640`) + +- Jeroen Demeyer (January 2015): use ``cb_pari_err_handle`` (:trac:`14894`) """ -include "sage/ext/stdsage.pxi" + +#***************************************************************************** +# Copyright (C) 2013 Peter Bruin +# Copyright (C) 2015 Jeroen Demeyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + include "sage/ext/interrupt.pxi" include "decl.pxi" from cpython cimport PyErr_Occurred +from pari_instance cimport pari_instance -# Global variable to record error string -cdef str pari_error_string +# We derive PariError from RuntimeError, for backward compatibility with +# code that catches the latter. +class PariError(RuntimeError): + """ + Error raised by PARI + """ + def errnum(self): + r""" + Return the PARI error number corresponding to this exception. + + EXAMPLES:: + + sage: try: + ....: pari('1/0') + ....: except PariError as err: + ....: print err.errnum() + 30 + """ + return self.args[0] + + def errtext(self): + """ + Return the message output by PARI when this error occurred. + + EXAMPLE:: + + sage: try: + ....: pari('pi()') + ....: except PariError as e: + ....: print e.errtext() + not a function in function call + + """ + return self.args[1] + + def errdata(self): + """ + Return the error data (a ``t_ERROR`` gen) corresponding to this + error. + + EXAMPLES:: + + sage: try: + ....: pari(Mod(2,6))^-1 + ....: except PariError as e: + ....: E = e.errdata() + sage: E + error("impossible inverse in Fp_inv: Mod(2, 6).") + sage: E.component(2) + Mod(2, 6) + """ + return self.args[2] + + def __repr__(self): + r""" + TESTS:: + + sage: PariError(11) + PariError(11) + """ + return "PariError(%d)"%self.errnum() + + def __str__(self): + r""" + Return a suitable message for displaying this exception. + + This is simply the error text with certain trailing characters + stripped. + + EXAMPLES:: + + sage: try: + ....: pari('1/0') + ....: except PariError as err: + ....: print err + _/_: impossible inverse in gdiv: 0 + + A syntax error:: + + sage: pari('!@#$%^&*()') + Traceback (most recent call last): + ... + PariError: syntax error, unexpected $undefined + """ + return self.errtext().rstrip(" .:") + cdef void _pari_init_error_handling(): """ Set up our code for handling PARI errors. - TEST:: + TESTS:: sage: try: ....: p = pari.polcyclo(-1) ....: except PariError as e: ....: print e.errtext() - ....: - *** domain error in polcyclo: index <= 0 + domain error in polcyclo: index <= 0 - """ - global pari_error_string - global cb_pari_err_recover - global cb_pari_handle_exception - pari_error_string = "" - cb_pari_err_recover = _pari_err_recover - cb_pari_handle_exception = _pari_handle_exception - -cdef void _pari_check_warning(): - """ - Print pending PARI library warning messages to stderr. - - TEST:: + Warnings still work just like in GP:: sage: pari('warning("test")') *** user warning: test - """ - global pari_error_string - if pari_error_string != "": - import sys - sys.stderr.write(pari_error_string) - pari_error_string = "" + global cb_pari_err_handle + global cb_pari_err_recover + cb_pari_err_handle = _pari_err_handle + cb_pari_err_recover = _pari_err_recover + -cdef int _pari_handle_exception(long err) except 0: +cdef int _pari_err_handle(GEN E) except 0: """ Convert a PARI error into a Sage exception, unless the error was a stack overflow, in which case we enlarge the stack. @@ -65,31 +149,38 @@ cdef int _pari_handle_exception(long err) except 0: sage: pari('error("test")') Traceback (most recent call last): ... - RuntimeError: PARI user exception - *** at top-level: error("test") - *** ^------------- - *** user error: test - + PariError: error: user error: test sage: pari(1)/pari(0) Traceback (most recent call last): ... PariError: impossible inverse in gdiv: 0 """ - if err == e_STACK: + cdef long errnum = E[1] + if errnum == e_STACK: # PARI is out of memory. We double the size of the PARI stack # and retry the computation. - from sage.libs.pari.all import pari - pari.allocatemem(silent=True) + pari_instance.allocatemem(silent=True) return 0 - if err == e_USER: - raise RuntimeError("PARI user exception\n%s" % pari_error_string) - else: - from sage.libs.pari.all import PariError - raise PariError(err, pari_error_string) + sig_block() + cdef char* errstr + cdef char* s + try: + errstr = pari_err2str(E) + pari_error_string = errstr.decode('ascii') + + s = closure_func_err() + if s is not NULL: + pari_error_string = s.decode('ascii') + ": " + pari_error_string + + raise PariError(errnum, pari_error_string, pari_instance.new_gen_noclear(E)) + finally: + pari_free(errstr) + sig_unblock() + -cdef void _pari_err_recover(long err): +cdef void _pari_err_recover(long errnum): """ Reset the error string and jump back to ``sig_on()``, either to retry the code (in case of no error) or to make the already-raised @@ -107,8 +198,6 @@ cdef void _pari_err_recover(long err): True """ - global pari_error_string - pari_error_string = "" if not PyErr_Occurred(): # No exception was raised => retry the computation starting # from sig_on(). This can happen if we successfully enlarged the diff --git a/src/sage/libs/pari/pari_err.h b/src/sage/libs/pari/pari_err.h deleted file mode 100644 index e90ee3ee0f4..00000000000 --- a/src/sage/libs/pari/pari_err.h +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include "interrupt.h" - - -/***************************************** - Interrupts and PARI exception handling - *****************************************/ - -#define pari_catch_sig_on() _sig_on_(NULL) -#define pari_catch_sig_str(s) _sig_on_(s) -#define pari_catch_sig_off() (_sig_off_(__FILE__, __LINE__), _pari_check_warning()) diff --git a/src/sage/libs/pari/pari_err.pxi b/src/sage/libs/pari/pari_err.pxi index 65fdc86bf51..38f3beef39e 100644 --- a/src/sage/libs/pari/pari_err.pxi +++ b/src/sage/libs/pari/pari_err.pxi @@ -1,10 +1,4 @@ -# Let Cython know that pari_err.h includes interrupt.h cdef extern from 'interrupt.h': - pass - -from sage.libs.pari.handle_error cimport _pari_check_warning - -cdef extern from 'sage/libs/pari/pari_err.h': - int pari_catch_sig_on() except 0 - int pari_catch_sig_str(char *) except 0 - void pari_catch_sig_off() + int pari_catch_sig_on "sig_on"() except 0 + int pari_catch_sig_str "sig_str"(char *) except 0 + void pari_catch_sig_off "sig_off"() diff --git a/src/sage/libs/pari/pari_instance.pxd b/src/sage/libs/pari/pari_instance.pxd index 759fec51436..fdd20767ec4 100644 --- a/src/sage/libs/pari/pari_instance.pxd +++ b/src/sage/libs/pari/pari_instance.pxd @@ -33,3 +33,5 @@ cdef class PariInstance(sage.structure.parent_base.ParentWithBase): cdef gen integer_matrix(self, fmpz_mat_t B, Py_ssize_t nr, Py_ssize_t nc, bint permute_for_hnf) cdef GEN _new_GEN_from_mpq_t_matrix(self, mpq_t** B, Py_ssize_t nr, Py_ssize_t nc) cdef gen rational_matrix(self, mpq_t** B, Py_ssize_t nr, Py_ssize_t nc) + +cdef PariInstance pari_instance diff --git a/src/sage/libs/pari/pari_instance.pyx b/src/sage/libs/pari/pari_instance.pyx index 918ad754134..6552963ce03 100644 --- a/src/sage/libs/pari/pari_instance.pyx +++ b/src/sage/libs/pari/pari_instance.pyx @@ -170,9 +170,7 @@ from sage.libs.flint.fmpz cimport fmpz_get_mpz from sage.libs.flint.fmpz_mat cimport * from sage.libs.pari.gen cimport gen, objtogen -from sage.libs.pari.handle_error cimport pari_error_string, \ - _pari_init_error_handling, _pari_check_warning, \ - _pari_handle_exception, _pari_err_recover +from sage.libs.pari.handle_error cimport _pari_init_error_handling # so Galois groups are represented in a sane way # See the polgalois section of the PARI users manual. @@ -370,24 +368,6 @@ cdef void sage_puts(char* s): cdef void sage_flush(): sys.stdout.flush() -cdef PariOUT sage_pariErr - -cdef void sage_pariErr_putchar(char c): - cdef char s[2] - s[0] = c - s[1] = 0 - global pari_error_string - pari_error_string += str(s) - pari_set_last_newline(1) - -cdef void sage_pariErr_puts(char *s): - global pari_error_string - pari_error_string += str(s) - pari_set_last_newline(1) - -cdef void sage_pariErr_flush(): - pass - @cython.final cdef class PariInstance(sage.structure.parent_base.ParentWithBase): @@ -439,6 +419,10 @@ cdef class PariInstance(sage.structure.parent_base.ParentWithBase): # error handlers. pari_init_opts(10000, maxprime, INIT_DFTm) + # Disable PARI's stack overflow checking which is incompatible + # with multi-threading. + pari_stackcheck_init(NULL) + _pari_init_error_handling() # pari_init_opts() overrides MPIR's memory allocation functions, @@ -457,11 +441,6 @@ cdef class PariInstance(sage.structure.parent_base.ParentWithBase): pariOut.puts = sage_puts pariOut.flush = sage_flush - pariErr = &sage_pariErr - pariErr.putch = sage_pariErr_putchar - pariErr.puts = sage_pariErr_puts - pariErr.flush = sage_pariErr_flush - # Display only 15 digits self._real_precision = 15 sd_format("g.15", d_SILENT) @@ -643,7 +622,7 @@ cdef class PariInstance(sage.structure.parent_base.ParentWithBase): call pari_catch_sig_off(). """ cdef pari_sp address - cdef gen y = PY_NEW(gen) + cdef gen y = gen.__new__(gen) y.g = self.deepcopy_to_python_heap(x, &address) y.b = address y._parent = self @@ -858,7 +837,7 @@ cdef class PariInstance(sage.structure.parent_base.ParentWithBase): sage: pari("[[1,2],3]")[0][1] ## indirect doctest 2 """ - cdef gen p = PY_NEW(gen) + cdef gen p = gen.__new__(gen) p.g = g p.b = 0 p._parent = self diff --git a/src/sage/libs/singular/__init__.py b/src/sage/libs/singular/__init__.py index 12c8bf2e94a..8b137891791 100644 --- a/src/sage/libs/singular/__init__.py +++ b/src/sage/libs/singular/__init__.py @@ -1,6 +1 @@ -from sage.libs.singular.function import singular_function, lib - -from sage.libs.singular.function_factory import SingularFunctionFactory - -ff = SingularFunctionFactory() diff --git a/src/sage/libs/singular/function.pyx b/src/sage/libs/singular/function.pyx index fbbbe1abf67..d6ac6f99380 100644 --- a/src/sage/libs/singular/function.pyx +++ b/src/sage/libs/singular/function.pyx @@ -50,7 +50,8 @@ available, use the :func:`lib` function as shown below:: There is also a short-hand notation for the above:: - sage: primdecSY = sage.libs.singular.ff.primdec__lib.primdecSY + sage: import sage.libs.singular.function_factory + sage: primdecSY = sage.libs.singular.function_factory.ff.primdec__lib.primdecSY The above line will load "primdec.lib" first and then load the function ``primdecSY``. @@ -1230,7 +1231,7 @@ cdef class SingularFunction(SageObject): sage: P. = PolynomialRing(QQ) sage: I = Ideal([x^3*y^2 + 3*x^2*y^2*z + y^3*z^2 + z^5]) sage: I = Ideal(I.groebner_basis()) - sage: hilb = sage.libs.singular.ff.hilb + sage: hilb = sage.libs.singular.function_factory.ff.hilb sage: hilb(I) # Singular will print // ** _ is no standard basis // ** _ is no standard basis // 1 t^0 @@ -1266,7 +1267,7 @@ cdef class SingularFunction(SageObject): sage: P. = PolynomialRing(QQ,5,order='lex') sage: I = sage.rings.ideal.Cyclic(P) - sage: triangL = sage.libs.singular.ff.triang__lib.triangL + sage: triangL = sage.libs.singular.function_factory.ff.triang__lib.triangL sage: _ = triangL(I) Traceback (most recent call last): ... @@ -1317,13 +1318,13 @@ INPUT: EXAMPLE:: - sage: groebner = sage.libs.singular.ff.groebner + sage: groebner = sage.libs.singular.function_factory.ff.groebner sage: P. = PolynomialRing(QQ) sage: I = P.ideal(x^2-y, y+x) sage: groebner(I) [x + y, y^2 - y] - sage: triangL = sage.libs.singular.ff.triang__lib.triangL + sage: triangL = sage.libs.singular.function_factory.ff.triang__lib.triangL sage: P. = PolynomialRing(QQ, order='lex') sage: f1 = 1/2*((x1^2 + 2*x1 - 4)*x2^2 + 2*(x1^2 + x1)*x2 + x1^2) sage: f2 = 1/2*((x1^2 + 2*x1 + 1)*x2^2 + 2*(x1^2 + x1)*x2 - 4*x1^2) @@ -1823,7 +1824,7 @@ def list_of_functions(packages=False): #cdef ring*? cdef inline RingWrap new_RingWrap(ring* r): - cdef RingWrap ring_wrap_result = PY_NEW(RingWrap) + cdef RingWrap ring_wrap_result = RingWrap.__new__(RingWrap) ring_wrap_result._ring = r ring_wrap_result._ring.ref += 1 diff --git a/src/sage/libs/singular/function_factory.py b/src/sage/libs/singular/function_factory.py index 85ee043b0ac..6d3169a8ff3 100644 --- a/src/sage/libs/singular/function_factory.py +++ b/src/sage/libs/singular/function_factory.py @@ -23,11 +23,13 @@ def __getattr__(self, name): """ EXAMPLE:: - sage: groebner = sage.libs.singular.ff.groebner + sage: import sage.libs.singular.function_factory + sage: groebner = sage.libs.singular.function_factory.ff.groebner sage: groebner groebner (singular function) - sage: primdecSY = sage.libs.singular.ff.primdec__lib.primdecSY + sage: import sage.libs.singular.function_factory + sage: primdecSY = sage.libs.singular.function_factory.ff.primdec__lib.primdecSY sage: primdecSY primdecSY (singular function) """ @@ -48,7 +50,11 @@ def trait_names(self): """ EXAMPLE:: - sage: "groebner" in sage.libs.singular.ff.trait_names() - True + sage: import sage.libs.singular.function_factory + sage: "groebner" in sage.libs.singular.function_factory.ff.trait_names() + True + """ return list_of_functions() + +ff = SingularFunctionFactory() diff --git a/src/sage/libs/singular/groebner_strategy.pyx b/src/sage/libs/singular/groebner_strategy.pyx index d8f3a72c697..231cce0ed21 100644 --- a/src/sage/libs/singular/groebner_strategy.pyx +++ b/src/sage/libs/singular/groebner_strategy.pyx @@ -311,7 +311,7 @@ cdef class NCGroebnerStrategy(SageObject): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: NCGroebnerStrategy(I) Groebner Strategy for ideal generated by 3 elements over Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {z*x: x*z + 2*x, z*y: y*z - 2*y, y*x: x*y - z} @@ -378,7 +378,7 @@ cdef class NCGroebnerStrategy(SageObject): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: strat = NCGroebnerStrategy(I) sage: del strat # indirect doctest """ @@ -410,7 +410,7 @@ cdef class NCGroebnerStrategy(SageObject): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: strat = NCGroebnerStrategy(I) sage: strat # indirect doctest Groebner Strategy for ideal generated by 3 elements over Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {z*x: x*z + 2*x, z*y: y*z - 2*y, y*x: x*y - z} @@ -426,7 +426,7 @@ cdef class NCGroebnerStrategy(SageObject): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: strat = NCGroebnerStrategy(I) sage: strat.ideal() == I True @@ -443,7 +443,7 @@ cdef class NCGroebnerStrategy(SageObject): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: strat = NCGroebnerStrategy(I) sage: strat.ring() is H True @@ -457,11 +457,11 @@ cdef class NCGroebnerStrategy(SageObject): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: strat = NCGroebnerStrategy(I) sage: strat == NCGroebnerStrategy(I) True - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()], side='twosided') + sage: I = H.ideal([y^2, x^2, z^2-H.one()], side='twosided') sage: strat == NCGroebnerStrategy(I) False """ @@ -479,7 +479,7 @@ cdef class NCGroebnerStrategy(SageObject): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: strat = NCGroebnerStrategy(I) sage: loads(dumps(strat)) == strat True @@ -524,7 +524,7 @@ def unpickle_NCGroebnerStrategy0(I): sage: from sage.libs.singular.groebner_strategy import NCGroebnerStrategy sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()]) + sage: I = H.ideal([y^2, x^2, z^2-H.one()]) sage: strat = NCGroebnerStrategy(I) sage: loads(dumps(strat)) == strat # indirect doctest True diff --git a/src/sage/libs/singular/option.pyx b/src/sage/libs/singular/option.pyx index e745772321f..a3e7b47cc92 100644 --- a/src/sage/libs/singular/option.pyx +++ b/src/sage/libs/singular/option.pyx @@ -12,7 +12,8 @@ We compute a Groebner basis for Cyclic-5 in two different contexts:: sage: P. = PolynomialRing(GF(127)) sage: I = sage.rings.ideal.Cyclic(P) - sage: std = sage.libs.singular.ff.std + sage: import sage.libs.singular.function_factory + sage: std = sage.libs.singular.function_factory.ff.std By default, tail reductions are performed:: diff --git a/src/sage/libs/singular/polynomial.pyx b/src/sage/libs/singular/polynomial.pyx index 4851919a944..d1efeb64ee0 100644 --- a/src/sage/libs/singular/polynomial.pyx +++ b/src/sage/libs/singular/polynomial.pyx @@ -146,6 +146,8 @@ cdef int singular_polynomial_call(poly **ret, poly *p, ring *r, list args, poly sage: (3*x*z)(x,x,x) 3*x^2 + TESTS: + Test that there is no memory leak in evaluating polynomials. Note that (lib)Singular has pre-allocated buckets, so we have to run a lot of iterations to fill those up first:: @@ -162,9 +164,30 @@ cdef int singular_polynomial_call(poly **ret, poly *p, ring *r, list args, poly ....: _ = p(a, a) ....: after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss ....: return (after - before) * 1024 # ru_maxrss is in kilobytes - sage: _ = leak(50000) # warmup and fill up pre-allocated buckets - sage: leak(10000) - 0 + + Loop (at most 30 times) until we have 6 consecutive zeros when + calling ``leak(10000)``. Depending on the operating system, it is + possible to have several non-zero leak values in the beginning, but + after a while we should get only zeros. The fact that we require 6 + zeros also means that Singular's pre-allocated buckets should not + be sufficient if there really would be a memory leak. :: + + sage: zeros = 0 + sage: for i in range(30): # long time + ....: n = leak(10000) + ....: print("Leaked {} bytes".format(n)) + ....: if n == 0: + ....: zeros += 1 + ....: if zeros >= 6: + ....: break + ....: else: + ....: zeros = 0 + Leaked... + Leaked 0 bytes + Leaked 0 bytes + Leaked 0 bytes + Leaked 0 bytes + Leaked 0 bytes """ cdef long l = len(args) cdef ideal *to_id = idInit(l,1) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index b75bb5ab324..a7ab5cc5fdb 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -38,9 +38,6 @@ from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libs from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.misc.misc_c import is_64_bit - - # mapping str --> SINGULAR representation order_dict = { "dp": ringorder_dp, @@ -194,14 +191,12 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: ch = base_ring.characteristic() if ch.is_power_of(2): exponent = ch.nbits() -1 - if is_64_bit: - # it seems Singular uses ints somewhere - # internally, cf. #6051 (Sage) and #138 (Singular) - if exponent <= 30: ringtype = 1 - else: ringtype = 3 + # it seems Singular uses ints somewhere + # internally, cf. #6051 (Sage) and #138 (Singular) + if exponent <= 30: + ringtype = 1 else: - if exponent <= 30: ringtype = 1 - else: ringtype = 3 + ringtype = 3 characteristic = exponent ringflaga = <__mpz_struct*>omAlloc(sizeof(__mpz_struct)) mpz_init_set_ui(ringflaga, 2) diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index bae2accef5f..63b9c24e662 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -24,8 +24,6 @@ cdef extern from "limits.h": import os -from sage.misc.misc_c import is_64_bit - from sage.libs.singular.decl cimport intvec from sage.libs.singular.decl cimport SR_HDL, SR_INT, SR_TO_INT from sage.libs.singular.decl cimport singular_options, singular_verbose_options @@ -231,13 +229,13 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): cdef object ret if naIsZero(n): - return base.zero_element() + return base.zero() elif naIsOne(n): - return base.one_element() + return base.one() z = (n).z a = base.gen() - ret = base.zero_element() + ret = base.zero() while z: c = napGetCoeff(z) @@ -354,7 +352,12 @@ cdef number *sa2si_GFqGivaro(int quo, ring *_ring): """ """ if _ring != currRing: rChangeCurrRing(_ring) - cdef number *n1, *n2, *a, *coeff, *apow1, *apow2 + cdef number *n1 + cdef number *n2 + cdef number *a + cdef number *coeff + cdef number *apow1 + cdef number *apow2 cdef int b = - _ring.ch a = naPar(1) @@ -388,7 +391,12 @@ cdef number *sa2si_GFqNTLGF2E(FFgf2eE elem, ring *_ring): """ if _ring != currRing: rChangeCurrRing(_ring) cdef int i - cdef number *n1, *n2, *a, *coeff, *apow1, *apow2 + cdef number *n1 + cdef number *n2 + cdef number *a + cdef number *coeff + cdef number *apow1 + cdef number *apow2 cdef GF2X_c rep = GF2E_rep(elem.x) if GF2X_deg(rep) >= 1: @@ -423,7 +431,12 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): """ """ cdef int i - cdef number *n1, *n2, *a, *coeff, *apow1, *apow2 + cdef number *n1 + cdef number *n2 + cdef number *a + cdef number *coeff + cdef number *apow1 + cdef number *apow2 elem = elem.polynomial() if _ring != currRing: rChangeCurrRing(_ring) @@ -459,7 +472,13 @@ cdef number *sa2si_NF(object elem, ring *_ring): """ """ cdef int i - cdef number *n1, *n2, *a, *nlCoeff, *naCoeff, *apow1, *apow2 + cdef number *n1 + cdef number *n2 + cdef number *a + cdef number *nlCoeff + cdef number *naCoeff + cdef number *apow1 + cdef number *apow2 elem = list(elem) if _ring != currRing: rChangeCurrRing(_ring) diff --git a/src/sage/libs/singular/standard_options.py b/src/sage/libs/singular/standard_options.py new file mode 100644 index 00000000000..89dc3b2e9be --- /dev/null +++ b/src/sage/libs/singular/standard_options.py @@ -0,0 +1,141 @@ +""" +Highlevel functions for managing options of the libSingular interface. + +AUTHOR: + +- Martin Albrecht +""" + +class LibSingularGBDefaultContext: + def __init__(self): + """ + EXAMPLE:: + + sage: from sage.libs.singular.standard_options import LibSingularGBDefaultContext + sage: from sage.libs.singular.option import opt + sage: P. = PolynomialRing(QQ, 3, order='lex') + sage: I = sage.rings.ideal.Katsura(P, 3) + sage: I.gens() + [a + 2*b + 2*c - 1, a^2 - a + 2*b^2 + 2*c^2, 2*a*b + 2*b*c - b] + sage: opt['red_tail'] = False + sage: opt['red_sb'] = False + sage: import sage.libs.singular.function_factory + sage: groebner = sage.libs.singular.function_factory.ff.groebner + sage: rgb = groebner(I) + sage: rgb + [84*c^4 - 40*c^3 + c^2 + c, 7*b + 210*c^3 - 79*c^2 + 3*c, a + 2*b + 2*c - 1] + sage: with LibSingularGBDefaultContext(): rgb = groebner(I) + sage: rgb + [84*c^4 - 40*c^3 + c^2 + c, 7*b + 210*c^3 - 79*c^2 + 3*c, 7*a - 420*c^3 + 158*c^2 + 8*c - 7] + + """ + from sage.libs.singular.option import opt_ctx + self.libsingular_option_context = opt_ctx + + def __enter__(self): + """ + EXAMPLE:: + + sage: from sage.libs.singular.standard_options import LibSingularGBDefaultContext + sage: from sage.libs.singular.option import opt + sage: P. = PolynomialRing(QQ, 4, order='lex') + sage: I = sage.rings.ideal.Katsura(P, 4) + sage: I.gens() + [a + 2*b + 2*c + 2*d - 1, a^2 - a + 2*b^2 + 2*c^2 + 2*d^2, 2*a*b + 2*b*c - b + 2*c*d, 2*a*c + b^2 + 2*b*d - c] + + sage: opt['red_tail'] = False + sage: opt['red_sb'] = False + sage: import sage.libs.singular.function_factory + sage: groebner = sage.libs.singular.function_factory.ff.groebner + sage: rgb = groebner(I) + sage: rgb + [128304*d^8 - 93312*d^7 + 15552*d^6 + 3144*d^5 - 1120*d^4 + 36*d^3 + 15*d^2 - d, + 5913075*c + 371438283744*d^7 - 237550027104*d^6 + 22645939824*d^5 + 11520686172*d^4 - 2024910556*d^3 - 132524276*d^2 + 30947828*d, + 1044*b + 10976*c^3 + 67914*c^2*d - 9709*c^2 + 100296*c*d^2 - 32862*c*d + 2412*c + 64302*d^3 - 29483*d^2 + 2683*d, + a + 2*b + 2*c + 2*d - 1] + + sage: with LibSingularGBDefaultContext(): rgb = groebner(I) + sage: rgb + [128304*d^8 - 93312*d^7 + 15552*d^6 + 3144*d^5 - 1120*d^4 + 36*d^3 + 15*d^2 - d, + 5913075*c + 371438283744*d^7 - 237550027104*d^6 + 22645939824*d^5 + 11520686172*d^4 - 2024910556*d^3 - 132524276*d^2 + 30947828*d, + 1971025*b - 97197721632*d^7 + 73975630752*d^6 - 12121915032*d^5 - 2760941496*d^4 + 814792828*d^3 - 1678512*d^2 - 9158924*d, + 5913075*a - 159690237696*d^7 + 31246269696*d^6 + 27439610544*d^5 - 6475723368*d^4 - 838935856*d^3 + 275119624*d^2 + 4884038*d - 5913075] + + """ + self.libsingular_option_context.__enter__() + self.libsingular_option_context.opt.reset_default() + self.libsingular_option_context.opt['red_sb'] = True + self.libsingular_option_context.opt['red_tail'] = True + self.libsingular_option_context.opt['deg_bound'] = 0 + self.libsingular_option_context.opt['mult_bound'] = 0 + + def __exit__(self, typ, value, tb): + """ + EXAMPLE:: + + sage: from sage.libs.singular.standard_options import LibSingularGBDefaultContext + sage: from sage.libs.singular.option import opt + sage: P. = PolynomialRing(GF(7), 4, order='lex') + sage: I = sage.rings.ideal.Katsura(P, 4) + sage: I.gens() + [a + 2*b + 2*c + 2*d - 1, a^2 - a + 2*b^2 + 2*c^2 + 2*d^2, 2*a*b + 2*b*c - b + 2*c*d, 2*a*c + b^2 + 2*b*d - c] + + sage: opt['red_tail'] = False + sage: opt['red_sb'] = False + sage: import sage.libs.singular.function_factory + sage: groebner = sage.libs.singular.function_factory.ff.groebner + sage: rgb = groebner(I) + sage: rgb + [d^7 + 3*d^6 - d^5 + 3*d^4 + d^3 - d^2 + 3*d, + c - 3*d^6 + 3*d^5 - d^4 + d^3 - 2*d, + b + 3*c*d - 3*c + d^2 + 2*d, + a + 2*b + 2*c + 2*d - 1] + sage: with LibSingularGBDefaultContext(): rgb = groebner(I) + sage: rgb + [d^7 + 3*d^6 - d^5 + 3*d^4 + d^3 - d^2 + 3*d, + c - 3*d^6 + 3*d^5 - d^4 + d^3 - 2*d, + b - 3*d^6 + 2*d^4 + d^3 + 2*d^2 - 3*d, + a - 2*d^6 + d^5 - 2*d^4 + 3*d^3 + 3*d^2 - 2*d - 1] + """ + self.libsingular_option_context.__exit__(typ,value,tb) + +def libsingular_gb_standard_options(func): + """ + Decorator to force a reduced Singular groebner basis. + + TESTS:: + + sage: P. = PolynomialRing(GF(127)) + sage: J = sage.rings.ideal.Cyclic(P).homogenize() + sage: from sage.misc.sageinspect import sage_getsource + sage: "basis.reduced" in sage_getsource(J.interreduced_basis) + True + + The following tests against a bug that was fixed in trac ticket #11298:: + + sage: from sage.misc.sageinspect import sage_getsourcelines, sage_getargspec + sage: P. = QQ[] + sage: I = P*[x,y] + sage: sage_getargspec(I.interreduced_basis) + ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None) + sage: sage_getsourcelines(I.interreduced_basis) + ([' @singular_gb_standard_options\n', + ' @libsingular_gb_standard_options\n', + ' def interreduced_basis(self):\n', + ... + ' return self.basis.reduced()\n'], ...) + + .. note:: + + This decorator is used automatically internally so the user + does not need to use it manually. + """ + from sage.misc.decorators import sage_wraps + @sage_wraps(func) + def wrapper(*args, **kwds): + """ + Execute function in ``LibSingularGBDefaultContext``. + """ + with LibSingularGBDefaultContext(): + return func(*args, **kwds) + return wrapper diff --git a/src/sage/libs/symmetrica/symmetrica.pxi b/src/sage/libs/symmetrica/symmetrica.pxi index 5909f6a0936..514fdc3d145 100644 --- a/src/sage/libs/symmetrica/symmetrica.pxi +++ b/src/sage/libs/symmetrica/symmetrica.pxi @@ -172,7 +172,8 @@ cdef extern from 'symmetrica/macro.h': INT exist INT reihenart INT z - reihe *x, *y + reihe *x + reihe *y reihe *p INT (*eingabefkt)() char ope @@ -432,8 +433,8 @@ cdef void late_import(): import sage.functions.all sqrt = sage.functions.all.sqrt - import sage.misc.misc - prod = sage.misc.misc.prod + import sage.misc.all + prod = sage.misc.all.prod import sage.rings.polynomial.polynomial_ring_constructor PolynomialRing = sage.rings.polynomial.polynomial_ring_constructor.PolynomialRing diff --git a/src/sage/matrix/constructor.py b/src/sage/matrix/constructor.py index e1408c134f5..1a645b162b4 100644 --- a/src/sage/matrix/constructor.py +++ b/src/sage/matrix/constructor.py @@ -2767,7 +2767,7 @@ def block_diagonal_matrix(*sub_matrices, **kwds): if isinstance(sub_matrices, (list, tuple)) and len(sub_matrices) == 1: sub_matrices = sub_matrices[0] n = len(sub_matrices) - entries = [ZZ.zero_element()] * n**2 + entries = [ZZ.zero()] * n**2 for i in range(n): entries[n*i+i] = sub_matrices[i] return block_matrix(n, n, entries, **kwds) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index a36141b3ad7..db68f40cf22 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -26,7 +26,6 @@ include "sage/ext/cdefs.pxi" include "sage/ext/python.pxi" from cpython.list cimport * from cpython.object cimport * -from cpython.slice cimport PySlice_Check from cpython.tuple cimport * import sage.modules.free_module @@ -49,8 +48,6 @@ import sage.modules.free_module import matrix_misc -cdef extern from "Python.h": - bint PySlice_Check(PyObject* ob) cdef class Matrix(sage.structure.element.Matrix): r""" @@ -879,7 +876,7 @@ cdef class Matrix(sage.structure.element.Matrix): if ind < 0 or ind >= nrows: raise IndexError("matrix index out of range") - elif PySlice_Check(row_index): + elif isinstance(row_index, slice): row_list = range(*row_index.indices(nrows)) else: if not PyIndex_Check(row_index): @@ -911,7 +908,7 @@ cdef class Matrix(sage.structure.element.Matrix): if ind < 0 or ind >= ncols: raise IndexError("matrix index out of range") - elif PySlice_Check(col_index): + elif isinstance(col_index, slice): col_list = range(*col_index.indices(ncols)) else: if not PyIndex_Check(col_index): @@ -963,7 +960,7 @@ cdef class Matrix(sage.structure.element.Matrix): if ind < 0 or ind >= nrows: raise IndexError("matrix index out of range") r = self.matrix_from_rows(row_list) - elif PySlice_Check(row_index): + elif isinstance(row_index, slice): row_list = range(*row_index.indices(nrows)) r = self.matrix_from_rows(row_list) else: diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index b627dda2ce7..f6cea33b5db 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -233,7 +233,7 @@ cdef class Matrix_cyclo_dense(matrix_dense.Matrix_dense): # The i,j entry is the (i * self._ncols + j)'th column. c = i * self._ncols + j - if PY_TYPE_CHECK_EXACT(value, NumberFieldElement_quadratic): + if type(value) is NumberFieldElement_quadratic: # Must be coded differently, since elements of # quadratic number fields are stored differently. if self._n == 4: diff --git a/src/sage/matrix/matrix_generic_dense.pyx b/src/sage/matrix/matrix_generic_dense.pyx index 0c8e65cd51b..8bbcf549ab4 100644 --- a/src/sage/matrix/matrix_generic_dense.pyx +++ b/src/sage/matrix/matrix_generic_dense.pyx @@ -307,7 +307,8 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): v = PyList_New(left._nrows * right._ncols) zero = R(0) p = 0 - cdef PyObject *l, *r + cdef PyObject *l + cdef PyObject *r for i from 0 <= i < nr: for j from 0 <= j < nc: z = zero diff --git a/src/sage/matrix/matrix_generic_sparse.pxd b/src/sage/matrix/matrix_generic_sparse.pxd index ba00eb3b51f..4b020d61972 100644 --- a/src/sage/matrix/matrix_generic_sparse.pxd +++ b/src/sage/matrix/matrix_generic_sparse.pxd @@ -1,6 +1,6 @@ cimport matrix_sparse cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): - cdef object _entries + cdef dict _entries cdef object _zero diff --git a/src/sage/matrix/matrix_generic_sparse.pyx b/src/sage/matrix/matrix_generic_sparse.pyx index 830c62acac6..bfdc583e222 100644 --- a/src/sage/matrix/matrix_generic_sparse.pyx +++ b/src/sage/matrix/matrix_generic_sparse.pyx @@ -62,13 +62,45 @@ import sage.misc.misc as misc cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): r""" + Generic sparse matrix. + The ``Matrix_generic_sparse`` class derives from - ``Matrix``, and defines functionality for sparse - matrices over any base ring. A generic sparse matrix is represented - using a dictionary with keys pairs `(i,j)` and values in - the base ring. + :class:`~sage.matrix.matrix_sparse.Matrix_sparse`, and defines functionality + for sparse matrices over any base ring. A generic sparse matrix is + represented using a dictionary whose keys are pairs of integers `(i,j)` and + values in the base ring. The values of the dictionary must never be zero. + + EXAMPLES:: - The values of the dictionary must never be zero. + sage: R. = PolynomialRing(ZZ,'a,b') + sage: M = MatrixSpace(R,5,5,sparse=True) + sage: M({(0,0):5*a+2*b, (3,4): -a}) + [5*a + 2*b 0 0 0 0] + [ 0 0 0 0 0] + [ 0 0 0 0 0] + [ 0 0 0 0 -a] + [ 0 0 0 0 0] + sage: M(3) + [3 0 0 0 0] + [0 3 0 0 0] + [0 0 3 0 0] + [0 0 0 3 0] + [0 0 0 0 3] + sage: V = FreeModule(ZZ, 5,sparse=True) + sage: m = M([V({0:3}), V({2:2, 4:-1}), V(0), V(0), V({1:2})]) + sage: m + [ 3 0 0 0 0] + [ 0 0 2 0 -1] + [ 0 0 0 0 0] + [ 0 0 0 0 0] + [ 0 2 0 0 0] + + .. NOTE:: + + The datastructure can potentially be optimized. Firstly, as noticed in + :trac:`17663`, we lose time in using 2-tuples to store indices. + Secondly, there is no fast way to access non-zero elements in a given + row/column. """ ######################################################################## # LEVEL 1 functionality @@ -84,81 +116,154 @@ cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): self._entries = {} # crucial so that pickling works def __init__(self, parent, entries=None, coerce=True, copy=True): - cdef Py_ssize_t i, j - matrix.Matrix.__init__(self, parent) + r""" + TESTS:: + + sage: R. = PolynomialRing(ZZ,'a') + sage: M = MatrixSpace(R,2,3,sparse=True) + sage: m = M([4,1,0,0,0,2]); m + [4 1 0] + [0 0 2] + sage: m2 = copy(m) + sage: m2[0,0] = -1 + sage: m[0,0] + 4 + sage: loads(dumps(m)) == m + True + + sage: R2. = PolynomialRing(QQ,'a','b') + sage: M2 = MatrixSpace(R2,2,3,sparse=True) + sage: M2(m) + [4 1 0] + [0 0 2] + sage: M2.has_coerce_map_from(M) + True + + sage: M3 = M2.change_ring(R2.fraction_field()) + sage: M3.has_coerce_map_from(M2) + True + + + Check that it is not possible to use wrong indices:: + + sage: M = MatrixSpace(R,2,2,sparse=True) + sage: M({(3,0): 1}) + Traceback (most recent call last): + ... + IndexError: matrix indices (3, 0) out of range + + sage: M({(0,-3): 1}) + Traceback (most recent call last): + ... + IndexError: matrix indices (0, -3) out of range + + But negative indices are valid:: + sage: M({(-1,-1): 1}) + [0 0] + [0 1] + """ + matrix.Matrix.__init__(self, parent) R = self._base_ring - self._zero = R(0) - if not isinstance(entries, (list, dict)): - if entries is None: - x = R.zero_element() - else: - x = R(entries) - entries = {} - if x != self._zero: - if self._nrows != self._ncols: - raise TypeError, "scalar matrix must be square" - for i from 0 <= i < self._nrows: - entries[(int(i),int(i))] = x - - if isinstance(entries, list) and len(entries) > 0 and \ - hasattr(entries[0], "is_vector"): - entries = _convert_sparse_entries_to_dict(entries) - - if isinstance(entries, list): - if len(entries) != self.nrows() * self.ncols(): - raise TypeError, "entries has the wrong length" - x = entries - entries = {} - k = 0 - for i from 0 <= i < self._nrows: - for j from 0 <= j < self._ncols: - if x[k] != 0: - entries[(int(i),int(j))] = x[k] - k = k + 1 - copy = False + self._zero = R.zero() + + if entries is None or not entries: + # be careful here. We might get entries set to be an empty list + # because of the code implemented in matrix_space.MatrixSpace + # So the condtion + # if entries is None or not entries: + # ... + # is valid. But + # if entries is None or entries == 0: + # ... + # is not! + return + + cdef Py_ssize_t i, j, k if not isinstance(entries, dict): - raise TypeError, "entries must be a dict" + # assume that entries is a scalar + x = R(entries) + entries = {} + if self._nrows != self._ncols: + raise TypeError("scalar matrix must be square") + for i from 0 <= i < self._nrows: + entries[(i,i)] = x if coerce: - try: - v = {} - for k, x in entries.iteritems(): - w = R(x) - if w != 0: - i, j = k - v[(int(i),int(j))] = w - entries = v - except TypeError: - raise TypeError, "Unable to coerce entries to %s"%R + v = {} + for key, x in entries.iteritems(): + i,j = key + if i < 0: i += self._nrows + if j < 0: j += self._ncols + if (i < 0 or i >= self._nrows or j < 0 or j >= self._ncols): + raise IndexError("matrix indices {} out of range".format(key)) + w = R(x) + if w: + v[(i,j)] = w + entries = v else: + # Here we do not pay attention to the indices. We just check that it + # *converts* to a pair of Py_ssize_t. In particular it is possible + # to do: + # + # sage: R = QQ['a','b'] + # sage: M = MatrixSpace(R, 3, 3, sparse=True) + # sage: m = M({(Zmod(3)(1), Zmod(6)(2)): R.one()}, coerce=False) + # + # and this is bad since: + # + # sage: map(type,m.dict().keys()[0]) + # [, + # ] + # + # But not that setting coerce=False is advanced usage and we assume + # that in such case the user knows what he/she is doing. if copy: - # Make a copy - entries = dict(entries) - for k in entries.keys(): - if entries[k].is_zero(): - del entries[k] + entries = entries.copy() + for key in entries.keys(): + i,j = key + if i < 0: i += self._nrows + if j < 0: j += self._ncols + if (i < 0 or i >= self._nrows or j < 0 or j >= self._ncols): + raise IndexError("matrix indices {} out of range".format(key)) + if not entries[key]: + del entries[key] self._entries = entries + def __nonzero__(self): + r""" + Test wether this matrix is non-zero. + + TESTS:: + + sage: R. = Zmod(5)['a','b'] + sage: m = matrix(R,3,4,sparse=True) + sage: bool(m) # indirect doctest + False + sage: m[0,3] = 1 + sage: bool(m) # indirect doctest + True + sage: m[0,3] = 0 # indirect doctest + sage: bool(m) + False + sage: m.is_zero() # indirect doctest + True + """ + return bool(self._entries) + cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, value): - # TODO: maybe make faster with Python/C API - k = (int(i),int(j)) - if value.is_zero(): + if not value: try: - del self._entries[k] + del self._entries[(i,j)] except KeyError: pass else: - self._entries[k] = value + self._entries[(i,j)] = value cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j): - # TODO: maybe make faster with Python/C API - try: - return self._entries[(int(i),int(j))] - except KeyError: - return self._zero + return self._entries.get((i,j), self._zero) def _pickle(self): version = 0 @@ -174,16 +279,15 @@ cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): sage: loads(dumps(a)) == a True """ - cdef Py_ssize_t i, j, k - if version == 0: self._entries = data self._zero = self._base_ring(0) else: - raise RuntimeError, "unknown matrix version (=%s)"%version + raise RuntimeError("unknown matrix version (=%s)"%version) def __richcmp__(matrix.Matrix self, right, int op): # always need for mysterious reasons. return self._richcmp(right, op) + def __hash__(self): return self._hash() @@ -228,36 +332,36 @@ cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): cdef Py_ssize_t i, j, len_v, len_w cdef Matrix_generic_sparse other other = _other - v = self._entries.items() + cdef list v = self._entries.items() v.sort() - w = other._entries.items() + cdef list w = other._entries.items() w.sort() s = {} i = 0 # pointer into self j = 0 # pointer into other - len_v = len(v) # could be sped up with Python/C API?? + len_v = len(v) len_w = len(w) while i < len_v and j < len_w: vi = v[i][0] wj = w[j][0] if vi < wj: s[vi] = v[i][1] - i = i + 1 + i += 1 elif vi > wj: s[wj] = w[j][1] - j = j + 1 + j += 1 else: # equal sm = v[i][1] + w[j][1] - if not sm.is_zero(): + if sm: s[vi] = sm - i = i + 1 - j = j + 1 + i += 1 + j += 1 while i < len(v): s[v[i][0]] = v[i][1] - i = i + 1 + i += 1 while j < len(w): s[w[j][0]] = w[j][1] - j = j + 1 + j += 1 cdef Matrix_generic_sparse A A = Matrix_generic_sparse.__new__(Matrix_generic_sparse, self._parent, 0,0,0) @@ -279,19 +383,30 @@ cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): Return all entries of self as a list of numbers of rows times number of columns entries. """ - x = self.fetch('list') - if not x is None: - return x - v = [self._base_ring(0)]*(self._nrows * self._ncols) - for ij, x in self._entries.iteritems(): - i, j = ij # todo: optimize - v[i*self._ncols + j] = x - self.cache('list', v) + cdef Py_ssize_t i,j + cdef list v = self.fetch('list') + if v is None: + v = [self._zero]*(self._nrows * self._ncols) + for (i,j), x in self._entries.iteritems(): + v[i*self._ncols + j] = x + self.cache('list', v) return v def _dict(self): """ Return the underlying dictionary of self. + + This is used in comparisons. + + TESTS:: + + sage: R. = Zmod(6)['a','b'] + sage: M = MatrixSpace(R, 4,3) + sage: m = M({(0,3): a+3*b*a, (1,1): -b}) + sage: m == m # indirect doctest + True + sage: M(0) == m # indirect doctest + False """ return self._entries @@ -300,34 +415,41 @@ cdef class Matrix_generic_sparse(matrix_sparse.Matrix_sparse): ######################################################################## def _nonzero_positions_by_row(self, copy=True): - x = self.fetch('nonzero_positions') - if x is not None: - if copy: - return list(x) - return x - - v = self._entries.keys() - v.sort() - - self.cache('nonzero_positions', v) + r""" + TESTS:: + + sage: R. = PolynomialRing(Zmod(8), 'a') + sage: M = MatrixSpace(R,4,3,sparse=True) + sage: m = M({(3,0): 1, (3,1): 2*a^2 + 1, (2,0): -1, (0,1): -2}) + sage: m._nonzero_positions_by_row() + [(0, 1), (2, 0), (3, 0), (3, 1)] + """ + cdef list v = self.fetch('nonzero_positions') + if v is None: + v = self._entries.keys() + v.sort() + self.cache('nonzero_positions', v) if copy: - return list(v) - + return v[:] return v def _nonzero_positions_by_column(self, copy=True): - x = self.fetch('nonzero_positions_by_column') - if x is not None: - if copy: - return list(x) - return x - - v = self._entries.keys() - v.sort(_cmp_backward) - - self.cache('nonzero_positions_by_column', v) + r""" + TESTS:: + + sage: R. = PolynomialRing(Zmod(8), 'a') + sage: M = MatrixSpace(R,4,3,sparse=True) + sage: m = M({(3,0): 1, (3,1): 2*a^2 + 1, (2,0): -1, (0,1): -2}) + sage: m._nonzero_positions_by_column() + [(2, 0), (3, 0), (0, 1), (3, 1)] + """ + cdef list v = self.fetch('nonzero_positions_by_column') + if v is None: + v = self._entries.keys() + v.sort(_cmp_backward) + self.cache('nonzero_positions_by_column', v) if copy: - return list(v) + return v[:] return v ###################### @@ -483,9 +605,9 @@ def Matrix_sparse_from_rows(X): cdef Py_ssize_t i, j if not isinstance(X, (list, tuple)): - raise TypeError, "X (=%s) must be a list or tuple"%X + raise TypeError("X (=%s) must be a list or tuple"%X) if len(X) == 0: - raise ArithmeticError, "X must be nonempty" + raise ArithmeticError("X must be nonempty") entries = {} R = X[0].base_ring() ncols = X[0].degree() @@ -495,32 +617,26 @@ def Matrix_sparse_from_rows(X): M = matrix_space.MatrixSpace(R, len(X), ncols, sparse=True) return M(entries, coerce=False, copy=False) - -## def _sparse_dot_product(v, w): -## """ -## INPUT: -## v and w are dictionaries with integer keys. -## """ -## x = set(v.keys()).intersection(set(w.keys())) -## a = 0 -## for k in x: -## a = a + v[k]*w[k] -## return a - -cdef _convert_sparse_entries_to_dict(entries): - e = {} - for i in xrange(len(entries)): - for j, x in (entries[i].dict()).iteritems(): - e[(i,j)] = x - return e - - - -def _cmp_backward(x,y): # todo: speed up via Python/C API - cdef int c +def _cmp_backward(x, y): # todo: speed up via Python/C API + r""" + TESTS:: + + sage: from sage.matrix.matrix_generic_sparse import _cmp_backward + sage: l0 = [(-1,-1), (0,0), (1,0), (-1,1), (0,1), (1,1), (-1,2)] + sage: l = l0[:] + sage: for _ in range(10): + ....: shuffle(l) + ....: l.sort(_cmp_backward) + ....: assert l0 == l + """ # compare two 2-tuples, but in reverse order, i.e., second entry than first - c = cmp(x[1],y[1]) - if c: return c - c = cmp(x[0],y[0]) - if c: return c - return 0 + cdef Py_ssize_t i,j + i = x[1] + j = y[1] + if i < j: + return -1 + elif i > j: + return 1 + i = x[0] + j = y[0] + return i-j diff --git a/src/sage/matrix/matrix_integer_sparse.pyx b/src/sage/matrix/matrix_integer_sparse.pyx index c11016c6240..0187f3f7605 100644 --- a/src/sage/matrix/matrix_integer_sparse.pyx +++ b/src/sage/matrix/matrix_integer_sparse.pyx @@ -186,7 +186,8 @@ cdef class Matrix_integer_sparse(matrix_sparse.Matrix_sparse): [ 9 12 15] """ cdef Py_ssize_t i - cdef mpz_vector* self_row, *M_row + cdef mpz_vector *self_row + cdef mpz_vector *M_row cdef Matrix_integer_sparse M cdef Integer _x _x = Integer(right) @@ -199,7 +200,8 @@ cdef class Matrix_integer_sparse(matrix_sparse.Matrix_sparse): cpdef ModuleElement _add_(self, ModuleElement right): cdef Py_ssize_t i, j - cdef mpz_vector* self_row, *M_row + cdef mpz_vector *self_row + cdef mpz_vector *M_row cdef Matrix_integer_sparse M M = Matrix_integer_sparse.__new__(Matrix_integer_sparse, self._parent, None, None, None) @@ -213,7 +215,8 @@ cdef class Matrix_integer_sparse(matrix_sparse.Matrix_sparse): cpdef ModuleElement _sub_(self, ModuleElement right): cdef Py_ssize_t i, j - cdef mpz_vector* self_row, *M_row + cdef mpz_vector *self_row + cdef mpz_vector *M_row cdef Matrix_integer_sparse M M = Matrix_integer_sparse.__new__(Matrix_integer_sparse, self._parent, None, None, None) diff --git a/src/sage/matrix/matrix_misc.py b/src/sage/matrix/matrix_misc.py index e1e87102e14..966a7228ea5 100644 --- a/src/sage/matrix/matrix_misc.py +++ b/src/sage/matrix/matrix_misc.py @@ -101,7 +101,7 @@ def weak_popov_form(M,ascend=True): num = matrix([(lambda x : map(numerator, x))(v) for v in map(list,(M*den).rows())]) else: # No need to clear denominators - den = R.one_element() + den = R.one() num = M r = [list(v) for v in num.rows()] diff --git a/src/sage/matrix/matrix_mod2_dense.pyx b/src/sage/matrix/matrix_mod2_dense.pyx index b7934b51f9b..cbe6fd70e8d 100644 --- a/src/sage/matrix/matrix_mod2_dense.pyx +++ b/src/sage/matrix/matrix_mod2_dense.pyx @@ -572,7 +572,7 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse if from_list: return self.rows(copy=False)[i] cdef Py_ssize_t j - cdef Vector_mod2_dense z = PY_NEW(Vector_mod2_dense) + cdef Vector_mod2_dense z = Vector_mod2_dense.__new__(Vector_mod2_dense) z._init(self._ncols, VectorSpace(self.base_ring(),self._ncols)) if self._ncols: mzd_submatrix(z._entries, self._entries, i, 0, i+1, self._ncols) @@ -662,7 +662,7 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse raise ArithmeticError("number of columns of matrix must equal degree of vector") VS = VectorSpace(self._base_ring, self._nrows) - cdef Vector_mod2_dense c = PY_NEW(Vector_mod2_dense) + cdef Vector_mod2_dense c = Vector_mod2_dense.__new__(Vector_mod2_dense) c._init(self._nrows, VS) c._entries = mzd_init(1, self._nrows) if c._entries.nrows and c._entries.ncols: diff --git a/src/sage/matrix/matrix_mod2e_dense.pyx b/src/sage/matrix/matrix_mod2e_dense.pyx index 05e8e34fb6b..934ca1df193 100644 --- a/src/sage/matrix/matrix_mod2e_dense.pyx +++ b/src/sage/matrix/matrix_mod2e_dense.pyx @@ -178,7 +178,7 @@ cdef class Matrix_mod2e_dense(matrix_dense.Matrix_dense): if poly in _m4rie_finite_field_cache: self._entries = mzed_init((_m4rie_finite_field_cache[poly]).ff, self._nrows, self._ncols) else: - FF = PY_NEW(M4RIE_finite_field) + FF = M4RIE_finite_field.__new__(M4RIE_finite_field) FF.ff = gf2e_init(poly) self._entries = mzed_init(FF.ff, self._nrows, self._ncols) _m4rie_finite_field_cache[poly] = FF diff --git a/src/sage/matrix/matrix_modn_dense.pyx b/src/sage/matrix/matrix_modn_dense.pyx index 5899a3a983e..3994b7868be 100644 --- a/src/sage/matrix/matrix_modn_dense.pyx +++ b/src/sage/matrix/matrix_modn_dense.pyx @@ -302,12 +302,12 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): v = self._matrix[i] for j from 0 <= j < self._ncols: x = entries[k] - if PY_TYPE_CHECK_EXACT(x, int): + if type(x) is int: tmp = (x) % p v[j] = tmp + (tmp<0)*p - elif PY_TYPE_CHECK_EXACT(x, IntegerMod_int) and (x)._parent is R: + elif type(x) is IntegerMod_int and (x)._parent is R: v[j] = (x).ivalue - elif PY_TYPE_CHECK_EXACT(x, Integer): + elif type(x) is Integer: if coerce: v[j] = mpz_fdiv_ui((x).value, p) else: @@ -648,7 +648,8 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): M.p = p sig_on() - cdef mod_int *row_self, *row_ans + cdef mod_int *row_self + cdef mod_int *row_ans for i from 0 <= i < self._nrows: row_self = self._matrix[i] row_ans = M._matrix[i] @@ -697,7 +698,8 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): M.p = p sig_on() - cdef mod_int *row_self, *row_ans + cdef mod_int *row_self + cdef mod_int *row_ans for i from 0 <= i < self._nrows: row_self = self._matrix[i] row_ans = M._matrix[i] @@ -750,7 +752,9 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): p = self.p sig_on() - cdef mod_int *row_self, *row_right, *row_ans + cdef mod_int *row_self + cdef mod_int *row_right + cdef mod_int *row_ans for i from 0 <= i < self._nrows: row_self = self._matrix[i] row_right = ( right)._matrix[i] @@ -791,7 +795,9 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): p = self.p sig_on() - cdef mod_int *row_self, *row_right, *row_ans + cdef mod_int *row_self + cdef mod_int *row_right + cdef mod_int *row_ans for i from 0 <= i < self._nrows: row_self = self._matrix[i] row_right = ( right)._matrix[i] @@ -835,7 +841,8 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): cdef int cmp sig_on() - cdef mod_int *row_self, *row_right + cdef mod_int *row_self + cdef mod_int *row_right for i from 0 <= i < self._nrows: row_self = self._matrix[i] row_right = ( right)._matrix[i] @@ -1102,7 +1109,8 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): row1 + t \* row2 where g = sa + tb """ cdef mod_int p = self.p - cdef mod_int * row1_p, * row2_p + cdef mod_int * row1_p + cdef mod_int * row2_p cdef mod_int tmp cdef int g, s, t, v, w cdef Py_ssize_t nc, i @@ -1256,7 +1264,8 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): cdef _add_multiple_of_row_c(self, Py_ssize_t row_to, Py_ssize_t row_from, mod_int multiple, Py_ssize_t start_col): cdef mod_int p - cdef mod_int *v_from, *v_to + cdef mod_int *v_from + cdef mod_int *v_to p = self.p v_from = self._matrix[row_from] @@ -1649,7 +1658,8 @@ cdef class Matrix_modn_dense(matrix_dense.Matrix_dense): cdef int ndigits = len(str(self.p)) cdef Py_ssize_t i, n - cdef char *s, *t + cdef char *s + cdef char *t if self._nrows == 0 or self._ncols == 0: data = '' diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index a6a53d8d019..bc2d0df7c9b 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -504,12 +504,12 @@ cdef class Matrix_modn_dense_template(matrix_dense.Matrix_dense): v = self._matrix[i] for j in range(self._ncols): x = entries[k] - if PY_TYPE_CHECK_EXACT(x, int): + if type(x) is int: tmp = (x) % p v[j] = tmp + (tmp<0)*p - elif PY_TYPE_CHECK_EXACT(x, IntegerMod_int) and (x)._parent is R: + elif type(x) is IntegerMod_int and (x)._parent is R: v[j] = (x).ivalue - elif PY_TYPE_CHECK_EXACT(x, Integer): + elif type(x) is Integer: if coerce: v[j] = mpz_fdiv_ui((x).value, p) else: @@ -2427,7 +2427,8 @@ cdef class Matrix_modn_dense_template(matrix_dense.Matrix_dense): row1 + t \* row2 where g = sa + tb """ cdef int p = self.p - cdef celement * row1_p, * row2_p + cdef celement *row1_p + cdef celement *row2_p cdef celement tmp cdef int g, s, t, v, w cdef Py_ssize_t nc, i @@ -2587,7 +2588,8 @@ cdef class Matrix_modn_dense_template(matrix_dense.Matrix_dense): [34 19 14 11 35 30 35 34 25 33] """ cdef celement p - cdef celement *v_from, *v_to + cdef celement *v_from + cdef celement *v_to p = self.p v_from = self._matrix[row_from] @@ -2826,7 +2828,8 @@ cdef class Matrix_modn_dense_template(matrix_dense.Matrix_dense): cdef int ndigits = len(str(self.p)) cdef Py_ssize_t i, n - cdef char *s, *t + cdef char *s + cdef char *t if self._nrows == 0 or self._ncols == 0: data = '' diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index 25a145f13fe..de38885f400 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -76,7 +76,7 @@ from sage.rings.arith import gcd from matrix2 import cmp_pivots, decomp_seq from matrix0 import Matrix as Matrix_base -from sage.misc.misc import verbose, get_verbose, prod +from sage.misc.all import verbose, get_verbose, prod ######################################################### # PARI C library @@ -214,7 +214,7 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j): cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_set(x.value, self._matrix[i][j]) return x @@ -259,7 +259,9 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): """ cdef Py_ssize_t i, j, len_so_far, m, n cdef char *a - cdef char *s, *t, *tmp + cdef char *s + cdef char *t + cdef char *tmp if self._nrows == 0 or self._ncols == 0: data = '' @@ -412,7 +414,8 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): return M cdef int _cmp_c_impl(self, Element right) except -2: - cdef mpq_t *a, *b + cdef mpq_t *a + cdef mpq_t *b cdef Py_ssize_t i, j cdef int k for i from 0 <= i < self._nrows: @@ -1205,7 +1208,7 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): mpq_add(s, s, self._matrix[row][c]) mpq_mul(pr, pr, s) cdef Rational _pr - _pr = PY_NEW(Rational) + _pr = Rational.__new__(Rational) mpq_set(_pr.value, pr) mpq_clear(s) mpq_clear(pr) @@ -1646,7 +1649,8 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): E = self._echelon_form_multimodular(height_guess, proof=proof, **kwds) self._clear_cache() cdef Py_ssize_t i, j - cdef mpq_t *row0, *row1 + cdef mpq_t *row0 + cdef mpq_t *row1 for i from 0 <= i < self._nrows: row0 = self._matrix[i] row1 = E._matrix[i] @@ -2419,7 +2423,8 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): cdef Py_ssize_t n cdef Rational _s _s = Rational(s) - cdef mpq_t *row_i, *row_j + cdef mpq_t *row_i + cdef mpq_t *row_j row_i = self._matrix[i] row_j = self._matrix[j] for n from 0 <= n < self._ncols: @@ -2629,7 +2634,7 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): cdef Py_ssize_t j from sage.modules.free_module import FreeModule parent = FreeModule(self._base_ring, self._ncols) - cdef Vector_rational_dense v = PY_NEW(Vector_rational_dense) + cdef Vector_rational_dense v = Vector_rational_dense.__new__(Vector_rational_dense) v._init(self._ncols, parent) for j in range(self._ncols): mpq_init(v._entries[j]); mpq_set(v._entries[j], self._matrix[i][j]) @@ -2663,7 +2668,7 @@ cdef class Matrix_rational_dense(matrix_dense.Matrix_dense): cdef Py_ssize_t j from sage.modules.free_module import FreeModule parent = FreeModule(self._base_ring, self._nrows) - cdef Vector_rational_dense v = PY_NEW(Vector_rational_dense) + cdef Vector_rational_dense v = Vector_rational_dense.__new__(Vector_rational_dense) v._init(self._nrows, parent) for j in range(self._nrows): mpq_init(v._entries[j]); mpq_set(v._entries[j], self._matrix[j][i]) diff --git a/src/sage/matrix/matrix_rational_sparse.pyx b/src/sage/matrix/matrix_rational_sparse.pyx index 4fb65b315aa..43bd26cdc95 100644 --- a/src/sage/matrix/matrix_rational_sparse.pyx +++ b/src/sage/matrix/matrix_rational_sparse.pyx @@ -698,7 +698,8 @@ cdef class Matrix_rational_sparse(matrix_sparse.Matrix_sparse): cdef Py_ssize_t l, n - cdef mpq_vector *v, *w + cdef mpq_vector *v + cdef mpq_vector *w v = &self._matrix[i] w = &_A._matrix[r] diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 639100acfcb..3037670f7d9 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -25,6 +25,7 @@ """ # System imports +import sys import types import weakref import operator @@ -124,21 +125,21 @@ class MatrixSpace(UniqueRepresentation, parent_gens.ParentWithGens): Full MatrixSpace of 10 by 5 dense matrices over Integer Ring sage: MatrixSpace(ZZ,10,5).category() Category of modules over (euclidean domains and infinite enumerated sets) - - sage: MatrixSpace(ZZ,10,2^31) - Traceback (most recent call last): # 32-bit - ... # 32-bit - ValueError: number of rows and columns must be less than 2^31 (on a 32-bit computer -- use a 64-bit computer for matrices with up to 2^63-1 rows and columns) # 32-bit - Full MatrixSpace of 10 by 2147483648 dense matrices over Integer Ring # 64-bit - sage: MatrixSpace(ZZ,2^31,10) - Traceback (most recent call last): # 32-bit - ... # 32-bit - ValueError: number of rows and columns must be less than 2^31 (on a 32-bit computer -- use a 64-bit computer for matrices with up to 2^63-1 rows and columns) # 32-bit - Full MatrixSpace of 2147483648 by 10 dense matrices over Integer Ring # 64-bit sage: MatrixSpace(ZZ,10,10).category() Category of algebras over (euclidean domains and infinite enumerated sets) sage: MatrixSpace(QQ,10).category() Category of algebras over quotient fields + + TESTS:: + + sage: MatrixSpace(ZZ, 1, 2^63) + Traceback (most recent call last): + ... + ValueError: number of rows and columns may be at most... + sage: MatrixSpace(ZZ, 2^100, 10) + Traceback (most recent call last): + ... + ValueError: number of rows and columns may be at most... """ _no_generic_basering_coercion = True @@ -282,10 +283,8 @@ def __init__(self, base_ring, if ncols < 0: raise ArithmeticError("ncols must be nonnegative") - if nrows >= 2**63 or ncols >= 2**63: - raise ValueError("number of rows and columns must be less than 2^63") - elif (nrows >= 2**31 or ncols >= 2**31) and not sage.misc.misc.is_64_bit: - raise ValueError("number of rows and columns must be less than 2^31 (on a 32-bit computer -- use a 64-bit computer for matrices with up to 2^63-1 rows and columns)") + if nrows > sys.maxsize or ncols > sys.maxsize: + raise ValueError("number of rows and columns may be at most %s" % sys.maxsize) self.__nrows = nrows self.__is_sparse = sparse @@ -732,11 +731,11 @@ def __iter__(self): :: sage: i = iter(ZZ) - sage: i.next() + sage: next(i) 0 - sage: i.next() + sage: next(i) 1 - sage: i.next() + sage: next(i) -1 Some more examples:: @@ -809,7 +808,7 @@ def __iter__(self): sage: MS = MatrixSpace(ZZ, 2, 3) sage: i = iter(MS) - sage: a = [ i.next() for _ in range(6) ] + sage: a = [ next(i) for _ in range(6) ] sage: a[0] [0 0 0] [0 0 0] @@ -861,13 +860,13 @@ def __iter__(self): #through and yield the matrices by "weight", which is #the total number of iterations that need to be done #on the base ring to reach the matrix. - base_elements = [ base_iter.next() ] + base_elements = [ next(base_iter) ] weight = 0 while True: for iv in sage.combinat.integer_vector.IntegerVectors(weight, number_of_entries): yield self(entries=[base_elements[i] for i in iv]) weight += 1 - base_elements.append( base_iter.next() ) + base_elements.append( next(base_iter) ) else: #In the finite case, we do a similar thing except that #the "weight" of each entry is bounded by the number diff --git a/src/sage/matrix/matrix_window.pyx b/src/sage/matrix/matrix_window.pyx index 4a3f8ee4622..6ca206f205b 100644 --- a/src/sage/matrix/matrix_window.pyx +++ b/src/sage/matrix/matrix_window.pyx @@ -11,11 +11,6 @@ Matrix windows from cpython.tuple cimport * -include 'sage/ext/stdsage.pxi' -cdef extern from "stdsage.h": - object PY_NEW(PyObject *) - - ######################################################################### # Generic matrix windows, which are used for block echelon and strassen # # algorithms. # @@ -34,8 +29,8 @@ cdef class MatrixWindow: is that self._matrix and matrix are over the same base ring (so share the zero). """ - cdef MatrixWindow M - M = PY_NEW(PY_TYPE(self)) + cdef type t = type(self) + cdef MatrixWindow M = t.__new__(t) M._matrix = matrix M._row = row M._col = col diff --git a/src/sage/matroids/basis_exchange_matroid.pyx b/src/sage/matroids/basis_exchange_matroid.pyx index bffb4d2bad4..9edee0fb462 100644 --- a/src/sage/matroids/basis_exchange_matroid.pyx +++ b/src/sage/matroids/basis_exchange_matroid.pyx @@ -1030,7 +1030,8 @@ cdef class BasisExchangeMatroid(Matroid): [1, 8, 22, 14, 1] """ - cdef bitset_t *flats, *todo + cdef bitset_t *flats + cdef bitset_t *todo if self._matroid_rank == 0: return [0] flats = sage_malloc((self.full_rank() + 1) * sizeof(bitset_t)) @@ -1100,7 +1101,8 @@ cdef class BasisExchangeMatroid(Matroid): sage: len(M.flats(4)) 1 """ - cdef bitset_t *flats, *todo + cdef bitset_t *flats + cdef bitset_t *todo if r < 0 or r > self.full_rank(): return SetSystem(self._E) if r == self.full_rank(): @@ -1174,7 +1176,8 @@ cdef class BasisExchangeMatroid(Matroid): sage: len(M.coflats(4)) 1 """ - cdef bitset_t *coflats, *todo + cdef bitset_t *coflats + cdef bitset_t *todo if r < 0 or r > self.full_corank(): return SetSystem(self._E) if r == self.full_corank(): @@ -1222,7 +1225,8 @@ cdef class BasisExchangeMatroid(Matroid): """ Compute a flat-element invariant of the matroid. """ - cdef bitset_t *flats, *todo + cdef bitset_t *flats + cdef bitset_t *todo if self._groundset_size == 0: return {}, tuple() flats = sage_malloc((k + 1) * sizeof(bitset_t)) diff --git a/src/sage/matroids/lean_matrix.pxd b/src/sage/matroids/lean_matrix.pxd index 16caaadf958..1cce7e863ec 100644 --- a/src/sage/matroids/lean_matrix.pxd +++ b/src/sage/matroids/lean_matrix.pxd @@ -64,7 +64,8 @@ cdef class BinaryMatrix(LeanMatrix): cdef class TernaryMatrix(LeanMatrix): - cdef bitset_t *_M0, *_M1 # _M0[i] = support of row i, _M1[i] = negative support of row i + cdef bitset_t *_M0 # _M0[i] = support of row i + cdef bitset_t *_M1 # _M1[i] = negative support of row i cdef bitset_t _s, _t, _u # registers cdef inline long get(self, long r, long c) # Not a Sage matrix operation @@ -79,7 +80,8 @@ cdef class TernaryMatrix(LeanMatrix): cdef class QuaternaryMatrix(LeanMatrix): - cdef bitset_t *_M0, *_M1 # _M0[i] = 1-support of row i, _M1[i] = x- support of row i + cdef bitset_t *_M0 # _M0[i] = 1-support of row i + cdef bitset_t *_M1 # _M1[i] = x- support of row i cdef bitset_t _s, _t, _u # registers cdef object _gf4, _zero, _one, _x_zero, _x_one diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 6990075d5d1..ff3a28d1ac4 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -2719,6 +2719,21 @@ cdef class Matroid(SageObject): """ return self.dual().flats(r) + def lattice_of_flats(self): + """ + Return the lattice of flats of the matroid. + + EXAMPLES:: + + sage: M = matroids.named_matroids.Fano() + sage: M.lattice_of_flats() + Finite lattice containing 16 elements + """ + from sage.combinat.posets.lattices import LatticePoset + F = [X for i in range(self.rank() + 1) + for X in self.flats(i)] + return LatticePoset((F, lambda x, y: x < y)) + cpdef hyperplanes(self): """ Return the set of hyperplanes of the matroid. diff --git a/src/sage/misc/all.py b/src/sage/misc/all.py index ed3399d332e..755fbd7f47b 100644 --- a/src/sage/misc/all.py +++ b/src/sage/misc/all.py @@ -6,18 +6,23 @@ BackslashOperator, getitem, cputime, verbose, set_verbose, set_verbose_files, get_verbose_files, unset_verbose_files, get_verbose, - version, banner, add, union, uniq, powerset, subsets, + union, uniq, powerset, subsets, exists, forall, is_iterator, - random_sublist, mul, walltime, generic_cmp, + random_sublist, walltime, generic_cmp, repr_lincomb, pad_zeros, attrcall, SAGE_DB, SAGE_TMP, - is_32_bit, is_64_bit, newton_method_sizes, compose, + newton_method_sizes, compose, self_compose, nest) +from banner import version, banner + from temporary_file import tmp_dir, tmp_filename from misc_c import prod, running_total, balanced_sum +lazy_import('sage.misc.misc_c', ['is_32_bit', 'is_64_bit'], deprecation=17460) +mul = prod +add = sum from dev_tools import runsnake, import_statements diff --git a/src/sage/misc/binary_matrix.pxi b/src/sage/misc/binary_matrix.pxi deleted file mode 100644 index af145f27ab0..00000000000 --- a/src/sage/misc/binary_matrix.pxi +++ /dev/null @@ -1,113 +0,0 @@ -r""" -A binary matrix datatype in Cython - -It's almost a copy of the bitset datatype, but allows a differentiation of the -rows of the matrix. That's the only advantage compared to storing all the rows -of a matrix in a loooooonng bitset. - -a ``binary_matrix_t`` structure contains : - -- ``long n_cols`` -- number of columns - -- ``long n_rows`` -- number of rows - -- ``long width`` -- number of ``unsigned long`` per row - -- ``unsigned long ** rows`` -- ``rows[i]`` points toward the ``width`` blocks of - type ``unsigned long`` containing the bits of row `i`. - -.. NOTE:: - - The rows are stored contiguously in memory, i.e. ``row[i] = row[i-1] + - width``. -""" -include "binary_matrix_pxd.pxi" -include "sage/ext/stdsage.pxi" - -cdef inline binary_matrix_init(binary_matrix_t m, long n_rows, long n_cols): - r""" - Allocates the binary matrix. - """ - cdef int i - - m.n_cols = n_cols - m.n_rows = n_rows - m.width = (n_cols - 1)/(8*sizeof(unsigned long)) + 1 - m.rows = sage_malloc(n_rows * sizeof(unsigned long *)) - if m.rows == NULL: - raise MemoryError - - m.rows[0] = sage_malloc(n_rows * m.width * sizeof(unsigned long)) - if m.rows[0] == NULL: - sage_free(m.rows) - raise MemoryError - - for i in range(1,n_rows): - m.rows[i] = m.rows[i-1] + m.width - m.rows[i][m.width-1] = 0 - -cdef inline binary_matrix_free(binary_matrix_t m): - r""" - Frees the memory allocated by the matrix - """ - sage_free(m.rows[0]) - sage_free(m.rows) - -cdef inline binary_matrix_fill(binary_matrix_t m, bint bit): - r""" - Fill the whole matrix with a bit - """ - memset(m.rows[0],-( bit),m.width * m.n_rows * sizeof(unsigned long)) - -cdef inline binary_matrix_complement(binary_matrix_t m): - r""" - Complements all of the matrix' bits. - """ - cdef int i,j - for i in range(m.n_rows): - for j in range(m.width): - m.rows[i][j] = ~m.rows[i][j] - - # Set the "useless" bits to 0 too. - if ((m.n_cols) & offset_mask): - m.rows[i][m.width-1] &= ( 1<<((m.n_cols) & offset_mask))-1 - -cdef inline binary_matrix_set1(binary_matrix_t m, long row, long col): - r""" - Sets an entry to 1 - """ - m.rows[row][col >> index_shift] |= (1) << (col & offset_mask) - -cdef inline binary_matrix_set0(binary_matrix_t m, long row, long col): - r""" - Sets an entry to 0 - """ - m.rows[row][col >> index_shift] &= ~((1) << (col & offset_mask)) - -cdef inline binary_matrix_set(binary_matrix_t m, long row, long col, bint value): - r""" - Sets an entry - """ - binary_matrix_set0(m,row,col) - m.rows[row][col >> index_shift] |= (1) << (value & offset_mask) - -cdef inline bint binary_matrix_get(binary_matrix_t m, long row, long col): - r""" - Returns the value of a given entry - """ - return (m.rows[row][col >> index_shift] >> (col & offset_mask)) & 1 - -cdef inline binary_matrix_print(binary_matrix_t m): - r""" - Prints the binary matrix - """ - cdef int i,j - import sys - for i in range(m.n_rows): - # If you want to print the *whole* matrix, including the useless bits, - # use the following line instead - # - # for j in (m.width*8*sizeof(unsigned long)): - for j in range(m.n_cols): - sys.stdout.write("1" if binary_matrix_get(m, i, j) else ".",) - print "" diff --git a/src/sage/misc/binary_matrix_pxd.pxi b/src/sage/misc/binary_matrix_pxd.pxi deleted file mode 100644 index ac106fa0561..00000000000 --- a/src/sage/misc/binary_matrix_pxd.pxi +++ /dev/null @@ -1,24 +0,0 @@ -include 'sage/ext/stdsage.pxi' -include 'sage/ext/cdefs.pxi' - -cdef extern from *: - int __builtin_popcountl(unsigned long) - void *memset(void *, int, size_t) - -# Constants from bitset.pxd -cdef extern from *: - int index_shift "(sizeof(unsigned long)==8 ? 6 : 5)" - unsigned long offset_mask "(sizeof(unsigned long)==8 ? 0x3F : 0x1F)" - - -cdef struct binary_matrix_s: - long n_cols - long n_rows - - # Number of "unsigned long" per row - long width - - unsigned long ** rows - -ctypedef binary_matrix_s[1] binary_matrix_t - diff --git a/src/sage/misc/binary_tree.pyx b/src/sage/misc/binary_tree.pyx index 04d408966fc..5b18c93ecf9 100644 --- a/src/sage/misc/binary_tree.pyx +++ b/src/sage/misc/binary_tree.pyx @@ -84,7 +84,8 @@ cdef object binary_tree_delete(binary_tree_node *self, int key): return binary_tree_delete(self.right, key) cdef binary_tree_node *binary_tree_left_excise(binary_tree_node *self): - cdef binary_tree_node *left, *cur + cdef binary_tree_node *left + cdef binary_tree_node *cur if self.left == NULL: left = self.right elif self.right == NULL: @@ -101,7 +102,8 @@ cdef binary_tree_node *binary_tree_left_excise(binary_tree_node *self): cdef binary_tree_node *binary_tree_right_excise(binary_tree_node *self): - cdef binary_tree_node *right, *cur + cdef binary_tree_node *right + cdef binary_tree_node *cur if self.right == NULL: right = self.left elif self.left == NULL: diff --git a/src/sage/misc/db.py b/src/sage/misc/db.py index 50a2856556c..1f821f744f6 100644 --- a/src/sage/misc/db.py +++ b/src/sage/misc/db.py @@ -20,9 +20,9 @@ import cPickle import os -import misc +from sage.env import SAGE_ROOT -PATH = misc.SAGE_ROOT + "/db" +PATH = os.path.join(SAGE_ROOT, "db") USE_DB = False diff --git a/src/sage/misc/decorators.py b/src/sage/misc/decorators.py index 97bb0ba8dd5..5ed7bb2298c 100644 --- a/src/sage/misc/decorators.py +++ b/src/sage/misc/decorators.py @@ -99,13 +99,13 @@ def sage_wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES): sage: P. = QQ[] sage: I = P*[x,y] sage: sage_getfile(I.interreduced_basis) - '...sage/rings/polynomial/multi_polynomial_ideal.py' + '.../sage/interfaces/singular.py' sage: sage_getsourcelines(I.interreduced_basis) - ([' @singular_standard_options\n', - ' @libsingular_standard_options\n', + ([' @singular_gb_standard_options\n', + ' @libsingular_gb_standard_options\n', ' def interreduced_basis(self):\n', ... - ' return ret\n'], ...) + ' return self.basis.reduced()\n'], ...) Demonstrate that sage_wraps works for non-function callables (:trac:`9919`):: diff --git a/src/sage/misc/dev_tools.py b/src/sage/misc/dev_tools.py index 0d2e33ef23c..f4cbc23ee9b 100644 --- a/src/sage/misc/dev_tools.py +++ b/src/sage/misc/dev_tools.py @@ -75,7 +75,8 @@ def runsnake(command): """ import cProfile, os - from sage.misc.misc import tmp_filename, get_main_globals + from sage.misc.temporary_file import tmp_filename + from sage.misc.misc import get_main_globals from sage.repl.preparse import preparse tmpfile = tmp_filename() cProfile.runctx(preparse(command.lstrip().rstrip()), get_main_globals(), locals(), filename=tmpfile) diff --git a/src/sage/misc/interpreter.py b/src/sage/misc/interpreter.py index 513bb13a35a..eb07a897011 100644 --- a/src/sage/misc/interpreter.py +++ b/src/sage/misc/interpreter.py @@ -1,2 +1,3 @@ -# to support sagenb -from sage.repl.interpreter import _do_preparse as do_preparse +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.repl.interpreter', '_do_preparse', 'do_preparse', deprecation=17460) diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index 029ea3dde2d..cce84eac047 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -27,15 +27,25 @@ sage: 'func' in globals() False +Test deprecation:: + + sage: sage.misc.misc.mul([3,4]) + doctest:...: DeprecationWarning: + Importing prod from here is deprecated. If you need to use it, please import it directly from sage.misc.all + See http://trac.sagemath.org/17460 for details. + 12 """ -######################################################################## +#***************************************************************************** # Copyright (C) 2006 William Stein # -# Distributed under the terms of the GNU General Public License (GPL) -# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -######################################################################## +#***************************************************************************** + __doc_exclude=["cached_attribute", "cached_class_attribute", "lazy_prop", "generic_cmp", "to_gmp_hex", "todo", @@ -43,16 +53,20 @@ "assert_attribute", "LOGFILE"] from warnings import warn -import operator, os, stat, socket, sys, signal, time, weakref, resource, math +import os, stat, sys, signal, time, resource, math import sage.misc.prandom as random from lazy_string import lazy_string -from sage.misc.temporary_file import tmp_dir, tmp_filename, delete_tmpfiles +from sage.misc.lazy_import import lazy_import +lazy_import('sage.misc.temporary_file', ('tmp_dir', 'tmp_filename', 'delete_tmpfiles'), deprecation=17460) +lazy_import('sage.misc.banner', ('version', 'banner'), deprecation=17460) +lazy_import('sage.env', '*', deprecation=17460) +lazy_import('sage.misc.decorators', ('infix_operator', 'decorator_defaults', 'sage_wraps'), deprecation=17460) +lazy_import('sage.misc.all', ('prod', 'running_total', 'balanced_sum', 'is_64_bit', 'is_32_bit'), deprecation=17460) +mul = prod -from banner import version, banner -# for backwards compatiblity -from sage.env import * +from sage.env import DOT_SAGE, HOSTNAME LOCAL_IDENTIFIER = '%s.%s'%(HOSTNAME , os.getpid()) @@ -570,53 +584,6 @@ def cmp_props(left, right, props): if c: return c return 0 -from sage.misc.misc_c import prod, running_total, balanced_sum, is_64_bit, is_32_bit - -# alternative name for prod -mul = prod - -add = sum - -## def add(x, z=0): -## """ -## Return the sum of the elements of x. If x is empty, -## return z. - -## INPUT: -## x -- iterable -## z -- the "0" that will be returned if x is empty. - -## OUTPUT: -## object - -## EXAMPLES: - -## A very straightforward usage: -## sage: add([1,2,3]) -## 6 - -## In the following example, xrange is an iterator: -## sage: add(xrange(101)) -## 5050 - -## Append two sequences. -## sage: add([[1,1], [-1,0]]) -## [1, 1, -1, 0] - -## The zero can be anything: -## sage: add([], "zero") -## 'zero' -## """ -## if len(x) == 0: -## return z -## if not isinstance(x, list): -## m = x.__iter__() -## y = m.next() -## return reduce(operator.add, m, y) -## else: -## return reduce(operator.add, x[1:], x[0]) - - def union(x, y=None): """ Return the union of x and y, as a list. The resulting list need not @@ -792,12 +759,10 @@ def repr_lincomb(terms, coeffs = None, is_latex=False, scalar_mult="*", strip_on s = "" first = True - i = 0 if scalar_mult is None: scalar_mult = "" if is_latex else "*" - all_atomic = True for (monomial,c) in terms: if c != 0: coeff = coeff_repr(c) @@ -1468,15 +1433,15 @@ def ellipsis_iter(*args, **kwds): EXAMPLES:: sage: A = ellipsis_iter(1,2,Ellipsis) - sage: [A.next() for _ in range(10)] + sage: [next(A) for _ in range(10)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - sage: A.next() + sage: next(A) 11 sage: A = ellipsis_iter(1,3,5,Ellipsis) - sage: [A.next() for _ in range(10)] + sage: [next(A) for _ in range(10)] [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] sage: A = ellipsis_iter(1,2,Ellipsis,5,10,Ellipsis) - sage: [A.next() for _ in range(10)] + sage: [next(A) for _ in range(10)] [1, 2, 3, 4, 5, 10, 11, 12, 13, 14] TESTS: @@ -1557,7 +1522,6 @@ def ellipsis_iter(*args, **kwds): yield args[step_magic-2] # now onto the rest - L = [] for i in range(step_magic, len(args)): if skip: skip = False @@ -1850,14 +1814,6 @@ def __get__(self, inst, cls): setattr(inst, self.name, result) return result -class cached_class_attribute(cached_attribute): - """ - Computes attribute value and caches it in the class. - """ - def __get__(self, inst, cls): - # just delegate to CachedAttribute, with 'cls' as ``instance'' - return super(CachedClassAttribute, self).__get__(cls, cls) - class lazy_prop(object): def __init__(self, calculate_function): self._calculate = calculate_function @@ -2474,7 +2430,3 @@ def inject_variable_test(name, value, depth): inject_variable(name, value) else: inject_variable_test(name, value, depth - 1) - -#For backward compatibility -- see #9907. -from sage.misc.decorators import infix_operator, decorator_defaults, sage_wraps - diff --git a/src/sage/misc/mrange.py b/src/sage/misc/mrange.py index af7ccf53784..eb03223dbf6 100644 --- a/src/sage/misc/mrange.py +++ b/src/sage/misc/mrange.py @@ -10,15 +10,17 @@ - Jon Hanke """ -######################################################################## +#***************************************************************************** # Copyright (C) 2006 William Stein # -# Distributed under the terms of the GNU General Public License (GPL) -# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -######################################################################## +#***************************************************************************** -import misc +from sage.misc.all import prod def _len(L): """ @@ -97,23 +99,23 @@ def _xmrange_iter( iter_list, typ=list ): doc-test to prove this:: sage: iter = sage.misc.mrange._xmrange_iter( [[1,2],[1,3]] ) - sage: l1 = iter.next() - sage: l2 = iter.next() + sage: l1 = next(iter) + sage: l2 = next(iter) sage: l1 is l2 False However, if you would like to re-use the list object:: sage: iter = sage.misc.mrange._xmrange_iter( [[1,2],[1,3]], lambda x: x ) - sage: l1 = iter.next() - sage: l2 = iter.next() + sage: l1 = next(iter) + sage: l2 = next(iter) sage: l1 is l2 # eeek, this is freaky! True We check that :trac:`14285` has been resolved:: sage: iter = sage.misc.mrange._xmrange_iter([ZZ,[]]) - sage: iter.next() + sage: next(iter) Traceback (most recent call last): ... StopIteration @@ -132,12 +134,12 @@ def _xmrange_iter( iter_list, typ=list ): if n == 0: return curr_iters = [iter(i) for i in iter_list] - curr_elt = [i.next() for i in curr_iters[:-1]] + [None] + curr_elt = [next(i) for i in curr_iters[:-1]] + [None] place = len(iter_list) - 1 while True: try: while True: - curr_elt[place] = curr_iters[place].next() + curr_elt[place] = next(curr_iters[place]) if place < len(iter_list) - 1: place += 1 curr_iters[place] = iter(iter_list[place]) @@ -581,7 +583,7 @@ def __len__(self): for i in sizes: if i <= 0: return 0 - return misc.prod(sizes, 1) + return prod(sizes, 1) def __iter__(self): return _xmrange(self.sizes, self.typ) diff --git a/src/sage/misc/preparser.py b/src/sage/misc/preparser.py index 2013c6293f5..07b7d253089 100644 --- a/src/sage/misc/preparser.py +++ b/src/sage/misc/preparser.py @@ -4,8 +4,6 @@ TESTS:: sage: import sage.misc.preparser - sage: sage.misc.preparser.preparse('1') - 'Integer(1)' sage: sage.misc.preparser.is_loadable_filename('foo.sage') doctest:...: DeprecationWarning: Importing is_loadable_filename from here is deprecated. If you need to use it, please import it directly from sage.repl.load @@ -17,6 +15,3 @@ lazy_import('sage.repl.preparse', '*', deprecation=17396) lazy_import('sage.repl.load', '*', deprecation=17396) - -# To support sagenb, import these *without* deprecation -lazy_import('sage.repl.preparse', ['strip_string_literals', 'preparse', 'preparse_file']) diff --git a/src/sage/misc/randstate.pyx b/src/sage/misc/randstate.pyx index 57026be40c9..030261272f4 100644 --- a/src/sage/misc/randstate.pyx +++ b/src/sage/misc/randstate.pyx @@ -1,3 +1,5 @@ +# distutils: libraries = gmp + r""" Random Number States diff --git a/src/sage/misc/remote_file.py b/src/sage/misc/remote_file.py index 2e2c30fcbb3..b5c7825a664 100644 --- a/src/sage/misc/remote_file.py +++ b/src/sage/misc/remote_file.py @@ -3,24 +3,28 @@ def get_remote_file(filename, verbose=True): """ INPUT: - filename -- the URL of a file on the web, e.g., - "http://modular.math.washington.edu/myfile.txt" - verbose -- whether to display download status + + - ``filename`` -- the URL of a file on the web, e.g., + ``"http://modular.math.washington.edu/myfile.txt"`` + + - ``verbose`` -- whether to display download status OUTPUT: - creates a file in the temp directory and returns the - absolute path to that file. - EXAMPLES: + creates a file in the temp directory and returns the absolute path + to that file. + + EXAMPLES:: + sage: g = get_remote_file("http://sagemath.org/ack.html", verbose=False) # optional - internet - sage: len(open(g).read()) # optional; randomly growing. + sage: len(open(g).read()) # optional - internet; random 10198 """ if verbose: print("Attempting to load remote file: " + filename) - import misc - temp_name = misc.tmp_filename() + '.' + os.path.splitext(filename)[1][1:] + from sage.misc.temporary_file import tmp_filename + temp_name = tmp_filename() + '.' + os.path.splitext(filename)[1][1:] # IMPORTANT -- urllib takes a long time to load, # so do not import it in the module scope. import urllib diff --git a/src/sage/misc/sage_input.py b/src/sage/misc/sage_input.py index d36f7eac315..157625d5dee 100644 --- a/src/sage/misc/sage_input.py +++ b/src/sage/misc/sage_input.py @@ -1,169 +1,171 @@ r""" Sage Input Formatting -AUTHORS: - -- Carl Witty (2008-04): new file - -This module provides a function \function{sage_input}. This function -takes an arbitrary \sage value and produces a sequence of commands -that, if typed at the \code{sage:} prompt, will recreate the value. -(If this is not implemented for a particular value, then an exception -is raised instead.) This might be useful in understanding a part of -Sage, or for debugging. (For instance, if you have a value produced -in a complicated way in the middle of a debugging session, you could -use \function{sage_input} to find a simple way to produce the same -value.) We attempt to produce commands that are readable and -idiomatic. - -sage: sage_input(3) -3 -sage: sage_input((polygen(RR) + RR(pi))^2, verify=True) -# Verified -R. = RR[] -x^2 + 6.2831853071795862*x + 9.869604401089358 - -With \code{verify=True}, \function{sage_input} also verifies the -results, by calling sage_eval on the result and verifying that it is -equal to the input. - -sage: sage_input(GF(2)(1), verify=True) -# Verified -GF(2)(1) +This module provides the function :func:`sage_input` that takes an +arbitrary sage value and produces a sequence of commands that, if typed +at the ``sage:`` prompt, will recreate the value. If this is not +implemented for a particular value, then an exception is raised instead. +This might be useful in understanding a part of Sage, or for debugging. +For instance, if you have a value produced in a complicated way in the +middle of a debugging session, you could use :func:`sage_input` to find +a simple way to produce the same value. We attempt to produce commands +that are readable and idiomatic.:: + + sage: sage_input(3) + 3 + sage: sage_input((polygen(RR) + RR(pi))^2, verify=True) + # Verified + R. = RR[] + x^2 + 6.2831853071795862*x + 9.869604401089358 + +With ``verify=True``, :func:`sage_input` also verifies the results, by +calling :func:`~sage.misc.sage_eval.sage_eval` on the result and +verifying that it is equal to the input.:: + + sage: sage_input(GF(2)(1), verify=True) + # Verified + GF(2)(1) We can generate code that works without the preparser, with -\code{preparse=False}; or we can generate code that will work whether -or not the preparser is enabled, with \code{preparse=None}. -Generating code with \code{preparse=False} may be useful to see how to -create a certain value in a Python or Cython source file. - -sage: sage_input(5, verify=True) -# Verified -5 -sage: sage_input(5, preparse=False) -ZZ(5) -sage: sage_input(5, preparse=None) -ZZ(5) -sage: sage_input(5r, verify=True) -# Verified -5r -sage: sage_input(5r, preparse=False) -5 -sage: sage_input(5r, preparse=None) -int(5) - -Adding \function{sage_input} support to your own classes is -straightforward. You need to add a \method{_sage_input_} method which -returns a \class{SageInputExpression} (henceforth abbreviated as SIE) +``preparse=False``; or we can generate code that will work whether or +not the preparser is enabled, with ``preparse=None``. Generating code +with ``preparse=False`` may be useful to see how to create a certain +value in a Python or Cython source file.:: + + sage: sage_input(5, verify=True) + # Verified + 5 + sage: sage_input(5, preparse=False) + ZZ(5) + sage: sage_input(5, preparse=None) + ZZ(5) + sage: sage_input(5r, verify=True) + # Verified + 5r + sage: sage_input(5r, preparse=False) + 5 + sage: sage_input(5r, preparse=None) + int(5) + +Adding :func:`sage_input` support to your own classes is +straightforward. You need to add a :func:`_sage_input_` method which +returns a :class:`SageInputExpression` (henceforth abbreviated as SIE) which will reconstruct this instance of your class. -A \method{_sage_input_} method takes two parameters, conventionally -named \var{sib} and \var{coerced}. The first argument is a -\class{SageInputBuilder}; it has methods to build SIEs. The second -argument, \var{coerced}, is a boolean. This is only useful if your -class is a subclass of \class{Element} (although it is always -present). If \var{coerced} is \code{False}, then your method must -generate an expression which will evaluate to a value of the correct -type with the correct parent. If \var{coerced} is \code{True}, then -your method may generate an expression of a type that has a canonical -coercion to your type; and if \var{coerced} is 2, then your method -may generate an expression of a type that has a conversion to your type. +A ``_sage_input_`` method takes two parameters, conventionally named +``sib`` and ``coerced``. The first argument is a +:class:`SageInputBuilder`; it has methods to build SIEs. The second +argument, ``coerced``, is a boolean. This is only useful if your class +is a subclass of :class:`Element` (although it is always present). If +``coerced`` is ``False``, then your method must generate an expression +which will evaluate to a value of the correct type with the correct +parent. If ``coerced`` is ``True``, then your method may generate an +expression of a type that has a canonical coercion to your type; and if +``coerced`` is 2, then your method may generate an expression of a type +that has a conversion to your type. Let's work through some examples. We'll build a sequence of functions -that would be acceptable as \method{_sage_input_} methods for the -\class{Rational} class. +that would be acceptable as ``_sage_input_`` methods for the +:class:`~sage.rings.rational.Rational` class. -Here's the first and simplest version. +Here's the first and simplest version.:: -sage: def qq_sage_input_v1(self, sib, coerced): -... return sib(self.numerator())/sib(self.denominator()) + sage: def qq_sage_input_v1(self, sib, coerced): + ....: return sib(self.numerator())/sib(self.denominator()) -We see that given a \class{SageInputBuilder} \var{sib}, you can -construct a SIE for a value \var{v} simply with \code{sib(v)}, and you -can construct a SIE for a quotient with the division operator. Of course, -the other operators also work, and so do function calls, method calls, -subscripts, etc. +We see that given a :class:`SageInputBuilder` ``sib``, you can construct +a SIE for a value ``v`` simply with ``sib(v)``, and you can construct a +SIE for a quotient with the division operator. Of course, the other +operators also work, and so do function calls, method calls, subscripts, +etc. We'll test with the following code, which you don't need to understand. -(It produces a list of 8 results, showing the formatted versions of --5/7 and 3, with the preparser either enabled or disabled and either -with or without an automatic coercion to QQ.) - -sage: from sage.misc.sage_input import SageInputBuilder -sage: def test_qq_formatter(fmt): -... results = [] -... for v in [-5/7, QQ(3)]: -... for pp in [False, True]: -... for coerced in [False, True]: -... sib = SageInputBuilder(preparse=pp) -... results.append(sib.result(fmt(v, sib, coerced))) -... return results - -sage: test_qq_formatter(qq_sage_input_v1) -[-ZZ(5)/ZZ(7), -ZZ(5)/ZZ(7), -5/7, -5/7, ZZ(3)/ZZ(1), ZZ(3)/ZZ(1), 3/1, 3/1] +(It produces a list of 8 results, showing the formatted versions of -5/7 +and 3, with the preparser either enabled or disabled and either with or +without an automatic coercion to QQ.):: + + sage: from sage.misc.sage_input import SageInputBuilder + sage: def test_qq_formatter(fmt): + ....: results = [] + ....: for v in [-5/7, QQ(3)]: + ....: for pp in [False, True]: + ....: for coerced in [False, True]: + ....: sib = SageInputBuilder(preparse=pp) + ....: results.append(sib.result(fmt(v, sib, coerced))) + ....: return results + + sage: test_qq_formatter(qq_sage_input_v1) + [-ZZ(5)/ZZ(7), -ZZ(5)/ZZ(7), -5/7, -5/7, ZZ(3)/ZZ(1), ZZ(3)/ZZ(1), 3/1, 3/1] Let's try for some shorter, perhaps nicer-looking output. We'll start -by getting rid of the \code{ZZ} in the denominators; even without the -preparser, \code{-ZZ(5)/7 == -ZZ(5)/ZZ(7)}. +by getting rid of the ``ZZ`` in the denominators; even without the +preparser, ``-ZZ(5)/7 == -ZZ(5)/ZZ(7)``.:: -sage: def qq_sage_input_v2(self, sib, coerced): -... return sib(self.numerator())/sib.int(self.denominator()) + sage: def qq_sage_input_v2(self, sib, coerced): + ....: return sib(self.numerator())/sib.int(self.denominator()) -The \method{int} method on \class{SageInputBuilder} returns a SIE for -an integer that is always represented in the simple way, without -coercions. (So, depending on the preparser mode, it might read in as an -\class{Integer}, an \class{int}, or a \class{long}.) +The ``int`` method on :class:`SageInputBuilder` returns a SIE for an +integer that is always represented in the simple way, without coercions. +(So, depending on the preparser mode, it might read in as an +:class:`~sage.rings.integer.Integer`, an ``int``, or a ``long``.):: -sage: test_qq_formatter(qq_sage_input_v2) -[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, ZZ(3)/1, ZZ(3)/1, 3/1, 3/1] + sage: test_qq_formatter(qq_sage_input_v2) + [-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, ZZ(3)/1, ZZ(3)/1, 3/1, 3/1] Next let's get rid of the divisions by 1. These are more complicated, -since if we're not careful we'll get results in \ZZ instead of \QQ. +since if we're not careful we'll get results in \ZZ instead of \QQ.:: -sage: def qq_sage_input_v3(self, sib, coerced): -... if self.denominator() == 1: -... if coerced: -... return sib.int(self.numerator()) -... else: -... return sib.name('QQ')(sib.int(self.numerator())) -... return sib(self.numerator())/sib.int(self.denominator()) + sage: def qq_sage_input_v3(self, sib, coerced): + ....: if self.denominator() == 1: + ....: if coerced: + ....: return sib.int(self.numerator()) + ....: else: + ....: return sib.name('QQ')(sib.int(self.numerator())) + ....: return sib(self.numerator())/sib.int(self.denominator()) We see that the \method{name} method gives an SIE representing a \sage -constant or function. +constant or function.:: -sage: test_qq_formatter(qq_sage_input_v3) -[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3] + sage: test_qq_formatter(qq_sage_input_v3) + [-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3] This is the prettiest output we're going to get, but let's make one -further refinement. Other \class{_sage_input_} methods, like the one +further refinement. Other :class:`_sage_input_` methods, like the one for polynomials, analyze the structure of SIEs; they work better (give -prettier output) if negations are at the outside. If the above code were -used for rationals, then \code{sage_input(polygen(QQ) - 2/3)} would produce -\code{x + (-2/3)}; if we change to the following code, then we would get -\code{x - 2/3} instead. - -sage: def qq_sage_input_v4(self, sib, coerced): -... num = self.numerator() -... neg = (num < 0) -... if neg: num = -num -... if self.denominator() == 1: -... if coerced: -... v = sib.int(num) -... else: -... v = sib.name('QQ')(sib.int(num)) -... else: -... v = sib(num)/sib.int(self.denominator()) -... if neg: v = -v -... return v - -sage: test_qq_formatter(qq_sage_input_v4) -[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3] +prettier output) if negations are at the outside. If the above code +were used for rationals, then ``sage_input(polygen(QQ) - 2/3)`` would +produce ``x + (-2/3)``; if we change to the following code, then we +would get ``x - 2/3`` instead.:: + + sage: def qq_sage_input_v4(self, sib, coerced): + ....: num = self.numerator() + ....: neg = (num < 0) + ....: if neg: num = -num + ....: if self.denominator() == 1: + ....: if coerced: + ....: v = sib.int(num) + ....: else: + ....: v = sib.name('QQ')(sib.int(num)) + ....: else: + ....: v = sib(num)/sib.int(self.denominator()) + ....: if neg: v = -v + ....: return v + + sage: test_qq_formatter(qq_sage_input_v4) + [-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3] + +AUTHORS: +- Carl Witty (2008-04): new file + +- Vincent Delecroix (2015-02): documentation formatting """ ########################################################################## # # Copyright (C) 2008 Carl Witty +# 2015 Vincent Delecroix <20100.delecroix@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # @@ -173,29 +175,33 @@ class is a subclass of \class{Element} (although it is always def sage_input(x, preparse=True, verify=False, allow_locals=False): r""" - INPUTS: - x -- the value we want to find an ``input form'' for - preparse -- (default \code{True}) Whether to generate code - that requires the preparser. With \code{True}, generated - code requires the preparser. With \code{False}, generated - code requires that the preparser not be used. With \code{None}, - generated code will work whether or not the preparser is used. - verify -- (default \code{False}) If \code{True}, then the - answer will be evaluated with \function{sage_eval}, and - an exception will be raised if the result is not equal to - the original value. (In fact, for \code{verify=True}, - \function{sage_input} is effectively run three times, - with \var{preparse} set to \code{True}, \code{False}, and - \code{None}, and all three results are checked.) This is - particularly useful for doctests. - allow_locals -- (default \code{False}) If \code{True}, then - values that \function{sage_input} cannot handle are returned - in a dictionary, and the returned code assumes that this - dictionary is passed as the \var{locals} parameter of - \function{sage_eval}. (Otherwise, if \function{sage_input} - cannot handle a value, an exception is raised.) - - EXAMPLES: + Return a sequence of commands that can be used to rebuild the object ``x``. + + INPUT: + + - ``x`` - the value we want to find an input form for + + - ``preparse`` - (default ``True``) Whether to generate code that requires + the preparser. With ``True``, generated code requires the preparser. + With ``False``, generated code requires that the preparser not be used. + With ``None``, generated code will work whether or not the preparser is + used. + + - ``verify`` - (default ``False``) If ``True``, then the answer will be + evaluated with :func:`sage_eval`, and an exception will be raised if the + result is not equal to the original value. (In fact, for ``verify=True``, + :func:`sage_input` is effectively run three times, with ``preparse`` set + to ``True``, ``False``, and ``None``, and all three results are checked.) + This is particularly useful for doctests. + + - ``allow_locals`` - (default ``False``) If ``True``, then values that + :func:`sage_input` cannot handle are returned in a dictionary, and the + returned code assumes that this dictionary is passed as the ``locals`` + parameter of :func:`sage_eval`. (Otherwise, if :func:`sage_input` cannot + handle a value, an exception is raised.) + + EXAMPLES:: + sage: sage_input(GF(2)(1)) GF(2)(1) sage: sage_input((GF(2)(0), GF(2)(1)), verify=True) @@ -203,7 +209,7 @@ def sage_input(x, preparse=True, verify=False, allow_locals=False): GF_2 = GF(2) (GF_2(0), GF_2(1)) - When the preparser is enabled, we use the \sage generator syntax. + When the preparser is enabled, we use the \sage generator syntax.:: sage: K. = GF(5)[] sage: sage_input(x^3 + 2*x, verify=True) @@ -215,8 +221,8 @@ def sage_input(x, preparse=True, verify=False, allow_locals=False): x = R.gen() x**3 + 2*x - The result of \function{sage_input} is actually a pair of strings with - a special \method{__repr__} method to print nicely. + The result of :func:`sage_input` is actually a pair of strings with a + special ``__repr__`` method to print nicely.:: sage: r = sage_input(RealField(20)(pi), verify=True) sage: r @@ -229,16 +235,15 @@ def sage_input(x, preparse=True, verify=False, allow_locals=False): sage: tuple(r) ('# Verified\n', 'RealField(20)(3.1415939)') - We cannot find an input form for a function. + We cannot find an input form for a function.:: sage: sage_input((3, lambda x: x)) Traceback (most recent call last): ... ValueError: Can't convert at 0x...> to sage_input form - But we can have \function{sage_input} continue anyway, and return - an input form for the rest of the expression, with - \code{allow_locals=True}. + But we can have :func:`sage_input` continue anyway, and return an input form + for the rest of the expression, with ``allow_locals=True``.:: sage: r = sage_input((3, lambda x: x), verify=True, allow_locals=True) sage: r @@ -269,22 +274,23 @@ def sage_input(x, preparse=True, verify=False, allow_locals=False): class SageInputBuilder: r""" - An instance of this class is passed to \method{_sage_input_} methods. - It keeps track of the current state of the \method{_sage_input_} process, - and contains many utility methods for building \class{SageInputExpression} + An instance of this class is passed to ``_sage_input_`` methods. + It keeps track of the current state of the ``_sage_input_`` process, + and contains many utility methods for building :class:`SageInputExpression` objects. - In normal use, instances of \class{SageInputBuilder} are created - internally by \function{sage_input}, but it may be useful to create + In normal use, instances of :class:`SageInputBuilder` are created + internally by :func:`sage_input`, but it may be useful to create an instance directly for testing or doctesting. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder - We can create a \class{SageInputBuilder}, use it to create some - \class{SageInputExpression}s, and get a result. (As mentioned + We can create a :class:`SageInputBuilder`, use it to create some + :class:`SageInputExpression` s, and get a result. (As mentioned above, this is only useful for testing or doctesting; normally - you would just use \function{sage_input}.) + you would just use :func:`sage_input`.):: sage: sib = SageInputBuilder() sage: sib.result((sib(3) + sib(4)) * (sib(5) + sib(6))) @@ -293,24 +299,27 @@ class SageInputBuilder: def __init__(self, allow_locals=False, preparse=True): r""" - Initialize an instance of \class{SageInputBuilder}. + Initialize an instance of :class:`SageInputBuilder`. - In normal use, instances of \class{SageInputBuilder} are created - internally by \function{sage_input}, but it may be useful to create + In normal use, instances of :class:`SageInputBuilder` are created + internally by :func:`sage_input`, but it may be useful to create an instance directly for testing or doctesting. - INPUTS: - allow_locals -- (default \code{False}) If true, then values + INPUT: + + - ``allow_locals`` - (default ``False``) If true, then values that cannot be converted to input form will be stored in - a dictionary, which must be passed as the \var{locals} + a dictionary, which must be passed as the ``locals`` when evaluating the result. - preparse -- (default \code{True}) If true, then the result - will assume that the preparser is enabled. If false, then - the result will assume that the preparser is disabled. - If \code{None}, then the result will work whether or - not the preparser is enabled. - EXAMPLES: + - ``preparse`` -- (default ``True``) If true, then the result + will assume that the preparser is enabled. If false, then + the result will assume that the preparser is disabled. + If ``None``, then the result will work whether or + not the preparser is enabled. + + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: SageInputBuilder().preparse() True @@ -328,24 +337,25 @@ def __init__(self, allow_locals=False, preparse=True): def __call__(self, x, coerced=False): r""" - Tries to convert an arbitrary value \var{x} into a - \class{SageInputExpression} (an SIE). + Tries to convert an arbitrary value ``x`` into a + :class:`SageInputExpression` (an SIE). - We first check to see if an SIE has been cached for \var{x}; - if so, we return it. If \var{x} is already an SIE, we return + We first check to see if an SIE has been cached for ``x``; + if so, we return it. If ``x`` is already an SIE, we return it unchanged. - If \var{x} has a \method{_sage_input_} method, we call that + If ``x`` has a \method{_sage_input_} method, we call that method. - Otherwise, if \var{x} is a value of some Python type that + Otherwise, if ``x`` is a value of some Python type that we know how to deal with, we convert it directly. Finally, for values we don't know how to convert, if - \code{self._allow_locals} is true, we add it to a - ``locals'' dictionary. + ``self._allow_locals`` is true, we add it to a + ``locals`` dictionary. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -356,8 +366,9 @@ def __call__(self, x, coerced=False): sage: sib.result(sib(GF(17)(5))) GF(17)(5) - The argument \code{coerced=True} or \code{coerced=2} will get - passed to the \method{_sage_input_} method of the argument. + The argument ``coerced=True`` or ``coerced=2`` will get + passed to the \method{_sage_input_} method of the argument.:: + sage: sib = SageInputBuilder() sage: sib.result(sib(GF(17)(5), True)) 5 @@ -366,8 +377,9 @@ def __call__(self, x, coerced=False): sage: sib.result(sib(RealField(200)(1.5), 2)) 1.5 - Since \function{sage_input} directly calls this method, all - of the following are indirect doctests. + Since :func:`sage_input` directly calls this method, all + of the following are indirect doctests.:: + sage: sage_input(True) True sage: sage_input(-5r, verify=True) @@ -543,16 +555,18 @@ def __call__(self, x, coerced=False): def preparse(self): r""" - Checks the preparse status of this \class{SageInputBuilder}. - (\code{True} if the preparser will be enabled, \code{False} - if it will be disabled, and \code{None} if the result must - work whether or not the preparser is enabled.) + Checks the preparse status. + + It returns ``True`` if the preparser will be enabled, ``False`` if it + will be disabled, and ``None`` if the result must work whether or not + the preparser is enabled. For example, this is useful in the \method{_sage_input_} - methods of \class{Integer} and \class{RealNumber}; but most + methods of :class:`~sage.rings.integer.Integer` and :class:`RealNumber`; but most \method{_sage_input_} methods will not need to examine this. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: SageInputBuilder().preparse() True @@ -563,14 +577,17 @@ def preparse(self): def int(self, n): r""" - Given an integer (an \class{Integer}, an \class{int}, or a - \class{long}), produce a \class{SageInputExpression} that displays - the integer with no marking for what kind of integer it is - (so it may read back as an \class{Integer}, an \class{int}, or - a \class{long}, depending on its size and whether the preparser - is enabled). + Return a raw SIE from the integer ``n`` + + As it is raw, it may read back as a Sage Integer, a Python int or a + Python long, depending on its size and whether the preparser is enabled. + + INPUT: + + - ``n`` - a Sage Integer, a Python int or a Python long + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -593,10 +610,11 @@ def int(self, n): def float_str(self, n): r""" Given a string representing a floating-point number, - produces a \class{SageInputExpression} that formats as that + produces a :class:`SageInputExpression` that formats as that string. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -608,9 +626,10 @@ def float_str(self, n): def name(self, n): r""" Given a string representing a Python name, - produces a \class{SageInputExpression} for that name. + produces a :class:`SageInputExpression` for that name. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -621,14 +640,17 @@ def name(self, n): def cache(self, x, sie, name): r""" - INPUTS: - x -- an arbitrary value - sie -- a \class{SageInputExpression} - name -- a requested variable name + INPUT: + + - ``x`` - an arbitrary value - Enters \var{x} and \var{sie} in a cache, so that subsequent calls - \code{self(x)} will directly return \var{sie}. Also, marks the - requested name of this \var{sie} to be \var{name}. + - ``sie`` - a :class:`SageInputExpression` + + - ``name`` - a requested variable name + + Enters ``x`` and ``sie`` in a cache, so that subsequent calls + ``self(x)`` will directly return ``sie``. Also, marks the + requested name of this ``sie`` to be ``name``. This should almost always be called as part of the \method{_sage_input_} method of a parent. It may also be called @@ -636,7 +658,8 @@ def cache(self, x, sie, name): are both large and likely to be used multiple times in a single expression. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -647,7 +670,8 @@ def cache(self, x, sie, name): the_ultimate_answer + the_ultimate_answer Note that we don't assign the result to a variable if the value - is only used once. + is only used once.:: + sage: sib = SageInputBuilder() sage: sie42 = sib(GF(101)(42)) sage: sib.cache(GF(101)(42), sie42, 'the_ultimate_answer') @@ -663,16 +687,19 @@ def cache(self, x, sie, name): def id_cache(self, x, sie, name): r""" - INPUTS: - x -- an arbitrary value - sie -- a \class{SageInputExpression} - name -- a requested variable name + INPUT: + + - ``x`` - an arbitrary value + + - ``sie`` - a :class:`SageInputExpression` - Enters \var{x} and \var{sie} in a cache, so that subsequent calls - \code{self(x)} will directly return \var{sie}. Also, marks the - requested name of this \var{sie} to be \var{name}. Differs from + - ``name`` - a requested variable name + + Enters ``x`` and ``sie`` in a cache, so that subsequent calls + ``self(x)`` will directly return ``sie``. Also, marks the + requested name of this ``sie`` to be ``name``. Differs from the \method{cache} method in that the cache is keyed by - \code{id(x)} instead of by \code{x}. + ``id(x)`` instead of by ``x``. This may be called on values of an arbitrary type, which may be useful if the values are both large and likely to be used @@ -680,7 +707,8 @@ def id_cache(self, x, sie, name): \method{cache} if equality on the values is difficult or impossible to compute. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: x = polygen(ZZ) @@ -694,12 +722,14 @@ def id_cache(self, x, sie, name): the_ultimate_answer + the_ultimate_answer Since id_cache keys off of object identity ("is"), the - following does not trigger the cache. + following does not trigger the cache.:: + sage: sib.result(sib(42*x) + sib(42*x)) 42*x + 42*x Note that we don't assign the result to a variable if the value - is only used once. + is only used once.:: + sage: sib = SageInputBuilder() sage: my_42 = 42*x sage: sie42 = sib(my_42) @@ -717,13 +747,15 @@ def id_cache(self, x, sie, name): def import_name(self, module, name, alt_name=None): r""" - INPUTS: - module, name, alt_name -- strings + INPUT: + + - ``module``, ``name``, ``alt_name`` -- strings Creates an expression that will import a name from a module and then use that name. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -734,7 +766,7 @@ def import_name(self, module, name, alt_name=None): from sage.foo.bar import ZZ as not_the_real_ZZ baz + not_the_real_ZZ - We adjust the names if there is a conflict. + We adjust the names if there is a conflict.:: sage: sib = SageInputBuilder() sage: v1 = sib.import_name('sage.foo', 'poly') @@ -748,15 +780,16 @@ def import_name(self, module, name, alt_name=None): def assign(self, e, val): r""" - INPUTS: - e, val -- SageInputExpression + Constructs a command that performs the assignment ``e=val``. - Constructs a command that performs the assignment e=val. + Can only be used as an argument to the ``command`` method. - Can only be used as an argument to the \method{command} - method. + INPUT: + + - ``e``, ``val`` -- SageInputExpression + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -774,13 +807,15 @@ def assign(self, e, val): def command(self, v, cmd): r""" - INPUTS: - v, cmd -- SageInputExpression + INPUT: + + - ``v``, ``cmd`` -- SageInputExpression Attaches a command to v, which will be executed before v is used. Multiple commands will be executed in the order added. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -801,10 +836,11 @@ def command(self, v, cmd): def dict(self, entries): r""" Given a dictionary, or a list of (key, value) pairs, - produces a \class{SageInputExpression} representing + produces a :class:`SageInputExpression` representing the dictionary. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -820,14 +856,15 @@ def dict(self, entries): def getattr(self, sie, attr): r""" - Given a \class{SageInputExpression} representing \code{foo} - and an attribute name bar, produce a \class{SageInputExpression} - representing \code{foo.bar}. Normally, you could just use + Given a :class:`SageInputExpression` representing ``foo`` + and an attribute name bar, produce a :class:`SageInputExpression` + representing ``foo.bar``. Normally, you could just use attribute-access syntax, but that doesn't work if bar is some attribute that bypasses __getattr__ (such as if bar is '__getattr__' itself). - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -840,19 +877,21 @@ def getattr(self, sie, attr): def empty_subscript(self, parent): r""" - Given a \class{SageInputExpression} representing \code{foo}, - produces a \class{SageInputExpression} representing \code{foo[]}. + Given a :class:`SageInputExpression` representing ``foo``, + produces a :class:`SageInputExpression` representing ``foo[]``. Since this is not legal Python syntax, it is useful only for producing the \sage generator syntax for a polynomial ring. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() sage: sib.result(sib.empty_subscript(sib(2) + sib(3))) (2 + 3)[] - The following calls this method indirectly. + The following calls this method indirectly.:: + sage: sage_input(polygen(ZZ['y'])) R. = ZZ['y'][] x @@ -861,12 +900,12 @@ def empty_subscript(self, parent): def use_variable(self, sie, name): r""" - Marks the \class{SageInputExpression} \var{sie} to use a - variable even if it is only referenced once. (If \var{sie} - is the final top-level expression, though, it will not use - a variable.) + Marks the :class:`SageInputExpression` ``sie`` to use a variable + even if it is only referenced once. (If ``sie`` is the final + top-level expression, though, it will not use a variable.) + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -876,15 +915,14 @@ def use_variable(self, sie, name): MS = MatrixSpace(ZZ, 10, 10) MS.zero_matrix() - Without the call to use_variable, we get this instead: + Without the call to use_variable, we get this instead:: sage: sib = SageInputBuilder() sage: e = sib.name('MatrixSpace')(ZZ, 10, 10) sage: sib.result(e.zero_matrix()) MatrixSpace(ZZ, 10, 10).zero_matrix() - And even with the call to use_variable, we don't use a variable - here: + And even with the call to use_variable, we don't use a variable here:: sage: sib = SageInputBuilder() sage: e = sib.name('MatrixSpace')(ZZ, 10, 10) @@ -901,16 +939,19 @@ def share(self, sie): by a variable if it occurs multiple times in the expression. (Most non-single-token expressions are already sharable.) - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder - Without explicitly using .share(), string literals are not shared: + Without explicitly using .share(), string literals are not shared:: + sage: sib = SageInputBuilder() sage: e = sib('hello') sage: sib.result(sib((e, e))) ('hello', 'hello') - See the difference if we use .share(): + See the difference if we use .share():: + sage: sib = SageInputBuilder() sage: e = sib('hello') sage: sib.share(e) @@ -923,17 +964,18 @@ def share(self, sie): def parent_with_gens(self, parent, sie, gen_names, name, gens_syntax=None): r""" This method is used for parents with generators, to manage the - \sage preparser generator syntax (like \code{K. = QQ[]}). + \sage preparser generator syntax (like ``K. = QQ[]``). The \method{_sage_input_} method of a parent class with - generators should construct a \class{SageInputExpression} for + generators should construct a :class:`SageInputExpression` for the parent, and then call this method with the parent itself, the constructed SIE, a sequence containing the names of the generators, and (optionally) another SIE to use if the \sage generator syntax is used; typically this will be the same as - the first SIE except omitting a \var{names} parameter. + the first SIE except omitting a ``names`` parameter. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder @@ -995,10 +1037,11 @@ def parent_with_gens(self, parent, sie, gen_names, name, gens_syntax=None): def gen(self, parent, n=0): r""" - Given a parent, returns a \class{SageInputExpression} for - the $n$th (default 0) generator of the parent. + Given a parent, returns a :class:`SageInputExpression` for + the `n`-th (default 0) generator of the parent. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1020,18 +1063,19 @@ def gen(self, parent, n=0): def prod(self, factors, simplify=False): r""" - Given a sequence, returns a \class{SageInputExpression} + Given a sequence, returns a :class:`SageInputExpression` for the product of the elements. - With \code{simplify=True}, performs some simplifications - first. If any element is formatted as a string \code{'0'}, + With ``simplify=True``, performs some simplifications + first. If any element is formatted as a string ``'0'``, then that element is returned directly. If any element is - formatted as a string \code{'1'}, then it is removed + formatted as a string ``'1'``, then it is removed from the sequence (unless it is the only element in the sequence). And any negations are removed from the elements and moved to the outside of the product. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1084,16 +1128,17 @@ def prod(self, factors, simplify=False): def sum(self, terms, simplify=False): r""" - Given a sequence, returns a \class{SageInputExpression} + Given a sequence, returns a :class:`SageInputExpression` for the product of the elements. - With \code{simplify=True}, performs some simplifications - first. If any element is formatted as a string \code{'0'}, + With ``simplify=True``, performs some simplifications + first. If any element is formatted as a string ``'0'``, then it is removed from the sequence (unless it is the only - element in the sequence); and any instances of \code{a + -b} - are changed to \code{a - b}. + element in the sequence); and any instances of ``a + -b`` + are changed to ``a - b``. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1134,12 +1179,13 @@ def sum(self, terms, simplify=False): def result(self, e): r""" - Given a \class{SageInputExpression} constructed using \code{self}, + Given a :class:`SageInputExpression` constructed using ``self``, returns a tuple of a list of commands and an expression (and possibly a dictionary of local variables) suitable for - \function{sage_eval}. + :func:`sage_eval`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1190,32 +1236,32 @@ def result(self, e): class SageInputExpression(object): r""" - Subclasses of this class represent expressions for \function{sage_input}. + Subclasses of this class represent expressions for :func:`sage_input`. \sage classes should define a \method{_sage_input_} method, which - will return an instance of \class{SageInputExpression}, created using - methods of \class{SageInputBuilder}. + will return an instance of :class:`SageInputExpression`, created using + methods of :class:`SageInputBuilder`. - To the extent possible, operations on \class{SageInputExpression} objects - construct a new \class{SageInputExpression} representing that operation. - That is, if \var{a} is a \class{SageInputExpression}, then \code{a + b} - constructs a \class{SageInputExpression} representing this sum. + To the extent possible, operations on :class:`SageInputExpression` objects + construct a new :class:`SageInputExpression` representing that operation. + That is, if ``a`` is a :class:`SageInputExpression`, then ``a + b`` + constructs a :class:`SageInputExpression` representing this sum. This also works for attribute access, function calls, subscripts, etc. Since arbitrary attribute accesses might be used to construct a new attribute-access expression, all internal attributes and methods - have names that begin with \code{_sie_} to reduce the chance of + have names that begin with ``_sie_`` to reduce the chance of collisions. It is expected that instances of this class will not be directly created outside this module; instead, instances will be created - using methods of \class{SageInputBuilder} and \class{SageInputExpression}. + using methods of :class:`SageInputBuilder` and :class:`SageInputExpression`. - Values of type \class{SageInputExpression} print in a fairly ugly + Values of type :class:`SageInputExpression` print in a fairly ugly way, that reveals the internal structure of the expression tree. """ def __init__(self, sib): r""" - Initialize a \class{SageInputExpression}. + Initialize a :class:`SageInputExpression`. EXAMPLES:: @@ -1239,7 +1285,7 @@ def __init__(self, sib): def _sie_is_simple(self): r""" - Returns \code{True} if this \class{SageInputExpression} is simple + Returns ``True`` if this :class:`SageInputExpression` is simple enough that duplicate uses are not worth caching. Normally this will be true if the expression represents a single token. @@ -1257,7 +1303,7 @@ def _sie_is_simple(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SageInputExpression}. + :class:`SageInputExpression`. EXAMPLES:: @@ -1313,8 +1359,8 @@ def _sie_prepare(self, sif): def _sie_require_varname(self, sif): r""" - Mark this \class{SageInputExpression} as requiring a variable name, - and register it with a \class{SageInputFormatter} (which will + Mark this :class:`SageInputExpression` as requiring a variable name, + and register it with a :class:`SageInputFormatter` (which will allocate a variable name at the end of the preparatory phase). EXAMPLES:: @@ -1334,8 +1380,8 @@ def _sie_require_varname(self, sif): def _sie_get_varname(self, sif): r""" - Get the variable name that the \class{SageInputFormatter} allocated - for this \class{SageInputExpression}. + Get the variable name that the :class:`SageInputFormatter` allocated + for this :class:`SageInputExpression`. EXAMPLES:: @@ -1354,7 +1400,7 @@ def _sie_get_varname(self, sif): def _sie_is_negation(self): r""" - Test whether a \class{SageInputExpression} is a negation. + Test whether a :class:`SageInputExpression` is a negation. Despite the obscure name, this is intended to be a public method. @@ -1373,9 +1419,9 @@ def _sie_is_negation(self): def __call__(self, *args, **kwargs): r""" - Given a \class{SageInputExpression}, build a new - \class{SageInputExpression} representing a function call node - (with \code{self} as the function). + Given a :class:`SageInputExpression`, build a new + :class:`SageInputExpression` representing a function call node + (with ``self`` as the function). EXAMPLES:: @@ -1392,9 +1438,9 @@ def __call__(self, *args, **kwargs): def __getitem__(self, key): r""" - Given a \class{SageInputExpression}, build a new - \class{SageInputExpression} representing a subscript expression - (with \code{self} as the value being subscripted). + Given a :class:`SageInputExpression`, build a new + :class:`SageInputExpression` representing a subscript expression + (with ``self`` as the value being subscripted). Currently, slices are not supported. @@ -1413,8 +1459,8 @@ def __getitem__(self, key): def __getattr__(self, attr): r""" - Given a \class{SageInputExpression}, build a new - \class{SageInputExpression} representing an attribute access. + Given a :class:`SageInputExpression`, build a new + :class:`SageInputExpression` representing an attribute access. EXAMPLES:: @@ -1447,7 +1493,7 @@ def _graphics_(self, **kwds): def __pow__(self, other): r""" - Compute an expression tree for \code{self ** other}. + Compute an expression tree for ``self ** other``. EXAMPLES:: @@ -1461,7 +1507,7 @@ def __pow__(self, other): def __mul__(self, other): r""" - Compute an expression tree for \code{self * other}. + Compute an expression tree for ``self * other``. EXAMPLES:: @@ -1475,7 +1521,7 @@ def __mul__(self, other): def __div__(self, other): r""" - Compute an expression tree for \code{self / other}. + Compute an expression tree for ``self / other``. EXAMPLES:: @@ -1489,7 +1535,7 @@ def __div__(self, other): def __add__(self, other): r""" - Compute an expression tree for \code{self + other}. + Compute an expression tree for ``self + other``. EXAMPLES:: @@ -1503,7 +1549,7 @@ def __add__(self, other): def __sub__(self, other): r""" - Compute an expression tree for \code{self - other}. + Compute an expression tree for ``self - other``. EXAMPLES:: @@ -1517,7 +1563,7 @@ def __sub__(self, other): def _sie_binop(self, op, other): r""" - Compute an expression tree for \code{self OP other}, + Compute an expression tree for ``self OP other``, where OP is a string representing a binary operator (such as '+' or '**'). @@ -1537,7 +1583,7 @@ def _sie_binop(self, op, other): def __neg__(self): r""" - Compute an expression tree for \code{-self}. + Compute an expression tree for ``-self``. EXAMPLES:: @@ -1551,7 +1597,7 @@ def __neg__(self): def __invert__(self): r""" - Compute an expression tree for \code{~self}. + Compute an expression tree for ``~self``. EXAMPLES:: @@ -1565,7 +1611,7 @@ def __invert__(self): def __abs__(self): r""" - Compute an expression tree for \code{abs(self)}. + Compute an expression tree for ``abs(self)``. EXAMPLES:: @@ -1579,7 +1625,7 @@ def __abs__(self): def _sie_unop(self, op): r""" - Compute an expression tree for \code{OP self}, + Compute an expression tree for ``OP self``, where OP is a string representing a unary operator (such as '-' or '~'). @@ -1606,9 +1652,9 @@ def _sie_format(self, sif): EXAMPLES: Actually, all of these are examples of the \method{_sie_format} - method on subclasses of \class{SageInputExpression}; - \class{SageInputExpression} itself is an abstract base class - (that cannot be instantiated). + method on subclasses of :class:`SageInputExpression`; + :class:`SageInputExpression` itself is an abstract base class + (that cannot be instantiated).:: sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -1635,13 +1681,13 @@ def _sie_format_statement(self, sif): Return the formatted string value of this expression, when used as a statement. - On most \class{SageInputExpression}s, this forwards directly + On most :class:`SageInputExpression`s, this forwards directly to the \method{_sie_format} method. However, on - \class{SageInputExpression}s that actually represent - statements (such as \class{SIE_assign}), this method + :class:`SageInputExpression`s that actually represent + statements (such as :class:`SIE_assign`), this method has an implementation and \method{_sie_format} raises an error. (This is to prevent accidental use of - \class{SIE_assign} as a value.) + :class:`SIE_assign` as a value.) EXAMPLES:: @@ -1662,10 +1708,11 @@ def _sie_format_statement(self, sif): class SIE_literal(SageInputExpression): r""" - An abstract base class for ``literals'' (basically, values which + An abstract base class for ``literals`` (basically, values which consist of a single token). - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SIE_literal sage: sib = SageInputBuilder() @@ -1678,11 +1725,12 @@ class SIE_literal(SageInputExpression): def _sie_is_simple(self): r""" - Report that \class{SIE_literal} values are not worth replacing by - variables (for ``common subexpression elimination'') even if they + Report that :class:`SIE_literal` values are not worth replacing by + variables (for ``common subexpression elimination``) even if they occur multiple times in an expression. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1703,12 +1751,13 @@ def _sie_is_simple(self): class SIE_literal_stringrep(SIE_literal): r""" - Values in this class are leaves in a \function{sage_input} expression + Values in this class are leaves in a :func:`sage_input` expression tree. Typically they represent a single token, and consist of the string representation of that token. They are used for integer, floating-point, and string literals, and for name expressions. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SIE_literal_stringrep sage: sib = SageInputBuilder() @@ -1726,13 +1775,16 @@ class SIE_literal_stringrep(SIE_literal): def __init__(self, sib, n): r""" - Initialize a \class{SIE_literal_stringrep} value. + Initialize a :class:`SIE_literal_stringrep` value. - INPUTS: - sib -- a \class{SageInputBuilder} - n -- a string; the value to be printed for this expression + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``n`` - a string; the value to be printed for this expression + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1747,10 +1799,11 @@ def __init__(self, sib, n): def __repr__(self): r""" - Returns a string representing this \class{SIE_literal_stringrep} + Returns a string representing this :class:`SIE_literal_stringrep` value. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1764,9 +1817,10 @@ def __repr__(self): def _sie_format(self, sif): r""" Return the formatted string value of this expression, and an indication - that it is ``atomic'' (never needs to be parenthesized). + that it is ``atomic`` (never needs to be parenthesized). + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -1780,10 +1834,11 @@ def _sie_format(self, sif): class SIE_call(SageInputExpression): r""" - This class represents a function-call node in a \function{sage_input} + This class represents a function-call node in a :func:`sage_input` expression tree. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1794,18 +1849,22 @@ class SIE_call(SageInputExpression): def __init__(self, sib, func, args, kwargs): r""" - Initialize an instance of \class{SIE_call}. + Initialize an instance of :class:`SIE_call`. - INPUTS: - sib -- a \class{SageInputBuilder} - func -- a \class{SageInputExpression} representing a function - args -- a list of \class{SageInputExpression}s representing the - positional arguments - kwargs -- a dictionary mapping strings to - \class{SageInputExpression}s representing the keyword - arguments + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``func`` - a :class:`SageInputExpression` representing a function + + - ``args`` - a list of :class:`SageInputExpression`s representing the + positional arguments + + - ``kwargs`` -- a dictionary mapping strings to + :class:`SageInputExpression`s representing the keyword arguments + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1818,9 +1877,10 @@ def __init__(self, sib, func, args, kwargs): def __repr__(self): r""" - Returns a string representing this \class{SIE_call} value. + Returns a string representing this :class:`SIE_call` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1834,9 +1894,10 @@ def __repr__(self): def _sie_referenced(self): r""" - Returns a list of the immediate subexpressions of this \class{SIE_call}. + Returns a list of the immediate subexpressions of this :class:`SIE_call`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1854,7 +1915,8 @@ def _sie_format(self, sif): Return the formatted string value of this expression, and an indication that it is a function call. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -1872,10 +1934,11 @@ def _sie_format(self, sif): class SIE_subscript(SageInputExpression): r""" - This class represents a subscript node in a \function{sage_input} + This class represents a subscript node in a :func:`sage_input` expression tree. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1886,18 +1949,22 @@ class SIE_subscript(SageInputExpression): def __init__(self, sib, coll, key): r""" - Initialize an instance of \class{SIE_subscript}. + Initialize an instance of :class:`SIE_subscript`. + + INPUT: + + - ``sib`` -- a :class:`SageInputBuilder` - INPUTS: - sib -- a \class{SageInputBuilder} - coll -- a \class{SageInputExpression} representing a collection - key -- a \class{SageInputExpression} representing the subscript/key + - ``coll`` -- a :class:`SageInputExpression` representing a collection - As a special case, \var{key} may be \code{None}; this represents an + - ``key`` -- a :class:`SageInputExpression` representing the subscript/key + + As a special case, ``key`` may be ``None``; this represents an empty subscript. This is not legal Python syntax, but it is legal - in the \sage preparser in examples like \code{K. = QQ[]}. + in the \sage preparser in examples like ``K. = QQ[]``. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1914,9 +1981,10 @@ def __init__(self, sib, coll, key): def __repr__(self): r""" - Returns a string representing this \class{SIE_subscript} value. + Returns a string representing this :class:`SIE_subscript` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1933,9 +2001,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SIE_subscript}. + :class:`SIE_subscript`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1953,7 +2022,8 @@ def _sie_format(self, sif): Return the formatted string value of this expression, and an indication that it is a subscript. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -1972,10 +2042,11 @@ def _sie_format(self, sif): class SIE_getattr(SageInputExpression): r""" - This class represents a getattr node in a \function{sage_input} + This class represents a getattr node in a :func:`sage_input` expression tree. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -1983,17 +2054,20 @@ class SIE_getattr(SageInputExpression): sage: sie {call: {getattr: {atomic:CC}.gen}()} """ - def __init__(self, sib, obj, attr): r""" - Initialize an instance of \class{SIE_getattr}. + Initialize an instance of :class:`SIE_getattr`. - INPUTS: - sib -- a \class{SageInputBuilder} - obj -- a \class{SageInputExpression} representing an object - attr -- a string; the attribute name + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``obj`` - a :class:`SageInputExpression` representing an object + + - ``attr`` - a string; the attribute name + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2006,9 +2080,10 @@ def __init__(self, sib, obj, attr): def __repr__(self): r""" - Returns a string representing this \class{SIE_getattr} value. + Returns a string representing this :class:`SIE_getattr` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2021,9 +2096,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SIE_subscript}. + :class:`SIE_subscript`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2038,7 +2114,8 @@ def _sie_format(self, sif): Return the formatted string value of this expression, and an indication that it is an attribute reference. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2054,10 +2131,11 @@ def _sie_format(self, sif): class SIE_tuple(SageInputExpression): r""" - This class represents a tuple or list node in a \function{sage_input} + This class represents a tuple or list node in a :func:`sage_input` expression tree. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2069,16 +2147,20 @@ class SIE_tuple(SageInputExpression): def __init__(self, sib, values, is_list): r""" - Initialize an instance of \class{SIE_tuple}. + Initialize an instance of :class:`SIE_tuple`. - INPUTS: - sib -- a \class{SageInputBuilder} - values -- a list of \class{SageInputExpression}s representing - the elements of this tuple - is_list -- is True if this class represents a list, False for - a tuple + INPUT: + + - ``sib`` -- a :class:`SageInputBuilder` + + - ``values`` -- a list of :class:`SageInputExpression`s representing the + elements of this tuple + + - ``is_list`` -- is True if this class represents a list, False for a + tuple + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2093,9 +2175,10 @@ def __init__(self, sib, values, is_list): def __repr__(self): r""" - Returns a string representing this \class{SIE_tuple} value. + Returns a string representing this :class:`SIE_tuple` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2111,9 +2194,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SIE_tuple}. + :class:`SIE_tuple`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2128,7 +2212,8 @@ def _sie_format(self, sif): Return the formatted string value of this tuple or list, and an indication that it is atomic (never needs to be parenthesized). - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2155,10 +2240,11 @@ def _sie_format(self, sif): class SIE_dict(SageInputExpression): r""" - This class represents a dict node in a \function{sage_input} + This class represents a dict node in a :func:`sage_input` expression tree. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2170,15 +2256,17 @@ class SIE_dict(SageInputExpression): def __init__(self, sib, entries): r""" - Initialize an instance of \class{SIE_dict}. + Initialize an instance of :class:`SIE_dict`. - INPUTS: - sib -- a \class{SageInputBuilder} - entries -- a list of pairs of - \class{SageInputExpression}s representing the entries of - this dict + INPUT: + + - ``sib`` -- a :class:`SageInputBuilder` + + - ``entries`` -- a list of pairs of :class:`SageInputExpression`s + representing the entries of this dict + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2192,9 +2280,10 @@ def __init__(self, sib, entries): def __repr__(self): r""" - Returns a string representing this \class{SIE_dict} value. + Returns a string representing this :class:`SIE_dict` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2208,9 +2297,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SIE_dict}. + :class:`SIE_dict`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2225,7 +2315,8 @@ def _sie_format(self, sif): Return the formatted string value of this dict, and an indication that it is atomic (never needs to be parenthesized). - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2242,9 +2333,10 @@ def _sie_format(self, sif): class SIE_binary(SageInputExpression): r""" This class represents an arithmetic expression with a binary operator - and its two arguments, in a \function{sage_input} expression tree. + and its two arguments, in a :func:`sage_input` expression tree. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2254,15 +2346,20 @@ class SIE_binary(SageInputExpression): def __init__(self, sib, op, lhs, rhs): r""" - Initialize an instance of \class{SIE_binary}. + Initialize an instance of :class:`SIE_binary`. - INPUTS: - sib -- a \class{SageInputBuilder} - op -- a string representing a binary operator, such as '*' or '%' - lhs -- a \class{SageInputExpression} - rhs -- a \class{SageInputExpression} + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``op`` - a string representing a binary operator, such as '*' or '%' + + - ``lhs`` - a :class:`SageInputExpression` + + - ``rhs`` - a :class:`SageInputExpression` + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2276,9 +2373,10 @@ def __init__(self, sib, op, lhs, rhs): def __repr__(self): r""" - Returns a string representing this \class{SIE_binary} value. + Returns a string representing this :class:`SIE_binary` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2290,9 +2388,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a tuple of the immediate subexpressions of this - \class{SIE_binary}. + :class:`SIE_binary`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2307,7 +2406,8 @@ def _sie_format(self, sif): Return the formatted string value of this expression, and the precedence of the top-level operator in the expression. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2322,7 +2422,8 @@ def _sie_format(self, sif): ('x^y', 32) Note that the printing for $x^y$ varies depending on whether the - preparser is enabled. + preparser is enabled.:: + sage: sibnp = SageInputBuilder(preparse=False) sage: sif = SageInputFormatter() sage: v = x**y @@ -2330,7 +2431,8 @@ def _sie_format(self, sif): sage: v._sie_format(sif) ('x^y', 32) - TESTS: + TESTS:: + sage: x = sib.name('x') sage: y = sib.name('y') sage: z = sib.name('z') @@ -2381,9 +2483,10 @@ def _sie_format(self, sif): class SIE_unary(SageInputExpression): r""" This class represents an arithmetic expression with a unary operator - and its argument, in a \function{sage_input} expression tree. + and its argument, in a :func:`sage_input` expression tree. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2393,14 +2496,18 @@ class SIE_unary(SageInputExpression): def __init__(self, sib, op, operand): r""" - Initialize an instance of \class{SIE_unary}. + Initialize an instance of :class:`SIE_unary`. - INPUTS: - sib -- a \class{SageInputBuilder} - op -- a string representing a unary operator, such as '-' - operand -- a \class{SageInputExpression} + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``op`` - a string representing a unary operator, such as '-' + + - ``operand`` -- a :class:`SageInputExpression` + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2413,9 +2520,10 @@ def __init__(self, sib, op, operand): def __repr__(self): r""" - Returns a string representing this \class{SIE_unary} value. + Returns a string representing this :class:`SIE_unary` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2427,9 +2535,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SIE_unary}. + :class:`SIE_unary`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2437,7 +2546,6 @@ def _sie_referenced(self): sage: sie._sie_referenced() [{atomic:x}] """ - return [self._sie_operand] def _sie_format(self, sif): @@ -2445,7 +2553,8 @@ def _sie_format(self, sif): Return the formatted string value of this expression, and the precedence of the top-level operator in the expression. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2460,7 +2569,8 @@ def _sie_format(self, sif): sage: v._sie_format(sif) ('~x', 30) - TESTS: + TESTS:: + sage: x = sib.name('x') sage: y = sib.name('y') sage: sib.result((-x)+y) @@ -2475,7 +2585,8 @@ def _sie_format(self, sif): x - -y We assume that -(x*y) is always equal to (-x)*y. Using this - assumption, we print -(x*y) as -x*y, which parses as (-x)*y. + assumption, we print -(x*y) as -x*y, which parses as (-x)*y.:: + sage: sib.result(-(x*y)) -x*y sage: sib.result((-x)*y) @@ -2502,16 +2613,17 @@ def _sie_format(self, sif): def _sie_is_negation(self): r""" - Test whether a \class{SageInputExpression} is a negation. + Test whether a :class:`SageInputExpression` is a negation. Despite the obscure name, this is intended to be a public method. This is used in the \method{_sage_input_} method for - \class{ComplexNumber}, so that \code{sage_input(CC(-3))} will - produce \code{-CC(3)} instead of \code{CC(-3)}. (This is preferred - so that you get \code{x - CC(3)} instead of \code{x + CC(-3)}.) + :class:`ComplexNumber`, so that ``sage_input(CC(-3))`` will + produce ``-CC(3)`` instead of ``CC(-3)``. (This is preferred + so that you get ``x - CC(3)`` instead of ``x + CC(-3)``.) + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2535,9 +2647,10 @@ class SIE_gens_constructor(SageInputExpression): r""" This class represents an expression that can create a \sage parent with named generators, optionally using the \sage preparser - generators syntax (like \code{K. = QQ[]}). + generators syntax (like ``K. = QQ[]``). + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2550,18 +2663,22 @@ class SIE_gens_constructor(SageInputExpression): def __init__(self, sib, constr, gen_names, gens_syntax=None): r""" - Initialize an instance of \class{SIE_gens_constructor}. + Initialize an instance of :class:`SIE_gens_constructor`. - INPUTS: - sib -- a \class{SageInputBuilder} - constr -- a \class{SageInputExpression} for constructing - this parent ``normally'' - gen_names -- a tuple of generator names - gens_syntax -- an optional \class{SageInputExpression} - for constructing this parent using the \sage preparser - generators syntax + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``constr`` - a :class:`SageInputExpression` for constructing this + parent ``normally`` + + - ``gen_names`` - a tuple of generator names + + - ``gens_syntax`` -- an optional :class:`SageInputExpression` for + constructing this parent using the \sage preparser generators syntax + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2581,9 +2698,10 @@ def __init__(self, sib, constr, gen_names, gens_syntax=None): def __repr__(self): r""" - Returns a string representing this \class{SIE_gens_constructor} value. + Returns a string representing this :class:`SIE_gens_constructor` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2598,10 +2716,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SIE_gens_constructor}. + :class:`SIE_gens_constructor`. + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2621,10 +2739,11 @@ def _sie_referenced(self): def _sie_gens_referenced(self, sif): r""" Mark that at least one of the generators in this - \class{SIE_gens_constructor} is used. (This means we will actually + :class:`SIE_gens_constructor` is used. (This means we will actually construct all of the generators.) - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2649,7 +2768,8 @@ def _sie_add_command(self, sif): Build commands to construct this parent and (if necessary) its associated generators. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2665,27 +2785,32 @@ def _sie_add_command(self, sif): 'QQx. = QQ[]\n' TESTS: + There are several tricky cases here. - We prefer the \sage preparser generators syntax: + We prefer the \sage preparser generators syntax:: + sage: sage_input(polygen(ZZ)) R. = ZZ[] x - But of course we can't use that without the preparser: + But of course we can't use that without the preparser:: + sage: sage_input(polygen(ZZ), preparse=False) R = ZZ['x'] x = R.gen() x We also can't use the preparser syntax if there is a conflict - between generator names. For example, this works: + between generator names. For example, this works:: + sage: sage_input((polygen(ZZ), polygen(GF(17), 'y'))) R1. = ZZ[] R2. = GF(17)[] (x, y) - but this can't use the preparser syntax. + but this can't use the preparser syntax.:: + sage: sage_input((polygen(ZZ), polygen(GF(17)))) R1 = ZZ['x'] x1 = R1.gen() @@ -2694,7 +2819,8 @@ def _sie_add_command(self, sif): (x1, x2) If we never use the generators, then we don't bother with the - preparser syntax. + preparser syntax.:: + sage: sage_input((ZZ['x'], ZZ['x'], GF(17)['y'])) R = ZZ['x'] (R, R, GF(17)['y']) @@ -2723,7 +2849,8 @@ def _sie_format(self, sif): As a side effect, if the generators of this parent are used, this adds commands to assign the generators to names. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2750,7 +2877,8 @@ class SIE_gen(SageInputExpression): This class represents a named generator of a parent with named generators. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2760,14 +2888,18 @@ class SIE_gen(SageInputExpression): def __init__(self, sib, parent, name): r""" - Initializes an instance of \class{SIE_gen}. + Initializes an instance of :class:`SIE_gen`. - INPUTS: - sib -- a \class{SageInputBuilder} - parent -- a \class{SIE_gens_constructor} - name -- a string with the name of this generator + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``parent`` - a :class:`SIE_gens_constructor` + + - ``name`` - a string with the name of this generator + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2780,9 +2912,10 @@ def __init__(self, sib, parent, name): def __repr__(self): r""" - Returns a string representing this \class{SIE_gen} value. + Returns a string representing this :class:`SIE_gen` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2793,9 +2926,10 @@ def __repr__(self): def _sie_is_simple(self): r""" - Report that \class{SIE_gen} values are single tokens. + Report that :class:`SIE_gen` values are single tokens. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2807,10 +2941,11 @@ def _sie_is_simple(self): def _sie_prepare(self, sif): r""" We override the \method{_sie_prepare} method from - \class{SageInputExpression} to additionally mark the parent of this + :class:`SageInputExpression` to additionally mark the parent of this generator that the generator names must be assigned. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2833,7 +2968,8 @@ def _sie_format(self, sif): As a side effect, this generates commands to assign the generators of the parent to variables. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2850,15 +2986,17 @@ def _sie_format(self, sif): def _sie_got_preferred(self, sif): r""" - Check whether the \class{SageInputFormatter} assigned us a + Check whether the :class:`SageInputFormatter` assigned us a variable name which is the same as the name of the generator name. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter First we verify that if we use two generators with different - names, then they get their preferred names. + names, then they get their preferred names.:: + sage: sib = SageInputBuilder() sage: sif = SageInputFormatter() sage: v = sib.gen(GF(2)['x']); w = sib.gen(GF(3)['y']) @@ -2869,9 +3007,10 @@ def _sie_got_preferred(self, sif): True Now, we repeat the experiment, except that the generators now - have the same names. In this case, the \class{SageInputFormatter} + have the same names. In this case, the :class:`SageInputFormatter` will not use the generator name as the variable name, because - of this conflict. + of this conflict.:: + sage: sib = SageInputBuilder() sage: sif = SageInputFormatter() sage: v = sib.gen(GF(2)['x']); w = sib.gen(GF(3)['x']) @@ -2887,7 +3026,8 @@ class SIE_import_name(SageInputExpression): r""" This class represents a name which has been imported from a module. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2899,16 +3039,21 @@ class SIE_import_name(SageInputExpression): def __init__(self, sib, module, name, alt_name=None): r""" - Initializes an instance of \class{SIE_import_name}. + Initializes an instance of :class:`SIE_import_name`. - INPUTS: - sib -- a \class{SageInputBuilder} - module -- a module name - name -- an object name - alt_name -- an alternate object name, or None (the default) - to use name + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``module`` - a module name + + - ``name`` - an object name + + - ``alt_name`` - an alternate object name, or None (the default) + to use name + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2928,9 +3073,10 @@ def __init__(self, sib, module, name, alt_name=None): def __repr__(self): r""" - Returns a string representing this \class{SIE_import_name} value. + Returns a string representing this :class:`SIE_import_name` value. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2944,9 +3090,10 @@ def __repr__(self): def _sie_is_simple(self): r""" - Report that \class{SIE_import_name} values are single tokens. + Report that :class:`SIE_import_name` values are single tokens. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -2958,9 +3105,10 @@ def _sie_is_simple(self): def _sie_prepare(self, sif): r""" We override the \method{_sie_prepare} method from - \class{SageInputExpression} to request a variable name. + :class:`SageInputExpression` to request a variable name. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -2980,7 +3128,8 @@ def _sie_format(self, sif): Return the formatted string value of this import, and an indication that it is atomic. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -3012,7 +3161,8 @@ class SIE_assign(SageInputExpression): r""" This class represents an assignment command. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -3022,14 +3172,18 @@ class SIE_assign(SageInputExpression): def __init__(self, sib, lhs, rhs): r""" - Initializes an instance of \class{SIE_assign}. + Initializes an instance of :class:`SIE_assign`. - INPUTS: - sib -- a \class{SageInputBuilder} - lhs -- the left-hand side of the assignment - rhs -- the right-hand side of the assignment + INPUT: + + - ``sib`` - a :class:`SageInputBuilder` + + - ``lhs`` - the left-hand side of the assignment + + - ``rhs`` - the right-hand side of the assignment + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -3042,9 +3196,10 @@ def __init__(self, sib, lhs, rhs): def __repr__(self): r""" - Returns a string representing this \class{SIE_assign} command. + Returns a string representing this :class:`SIE_assign` command. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -3056,9 +3211,10 @@ def __repr__(self): def _sie_referenced(self): r""" Returns a list of the immediate subexpressions of this - \class{SIE_assign}. + :class:`SIE_assign`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() @@ -3070,11 +3226,12 @@ def _sie_referenced(self): def _sie_format(self, sif): r""" - Return the formatted string value of this \class{SIE_assign} + Return the formatted string value of this :class:`SIE_assign` as an expression. Since an assignment is a statement, not an expression, always raises an error. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() @@ -3090,12 +3247,12 @@ def _sie_format(self, sif): def _sie_format_statement(self, sif): r""" - Return the formatted string of this \class{SIE_assign} + Return the formatted string of this :class:`SIE_assign` as a statement. - EXAMPLES: - sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() sage: sif = SageInputFormatter() sage: sie = sib.assign(sib.name('foo').x, sib.name('pi')) @@ -3108,17 +3265,17 @@ def _sie_format_statement(self, sif): class SageInputFormatter: r""" An instance of this class is used to keep track of variable names - and a sequence of generated commands during the \function{sage_input} + and a sequence of generated commands during the :func:`sage_input` formatting process. """ def __init__(self): r""" - Initialize an instance of \class{SageInputFormatter}. + Initialize an instance of :class:`SageInputFormatter`. - EXAMPLES: - sage: from sage.misc.sage_input import SageInputFormatter + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputFormatter sage: sif = SageInputFormatter() """ self._commands = '' @@ -3127,28 +3284,32 @@ def __init__(self): def format(self, e, prec): r""" - Format a \class{SageInputExpression} into a string. + Format a Sage input expression into a string. + + INPUT: - INPUTS: - e -- a \class{SageInputExpression} - prec -- an integer representing a precedence level + - ``e`` - a :class:`SageInputExpression` + + - ``prec`` - an integer representing a precedence level - First, we check to see if \var{e} should be replaced by a variable. + First, we check to see if ``e`` should be replaced by a variable. If so, we generate the command to assign the variable, and return the name of the variable. Otherwise, we format the expression by calling its \method{_sie_format} method, and add parentheses if necessary. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter sage: sib = SageInputBuilder() sage: sif = SageInputFormatter() sage: sie = sib(GF(5)) - Here we ``cheat'' by calling \method{_sie_prepare} twice, to make it - use a variable. + Here we ``cheat`` by calling \method{_sie_prepare} twice, to make it + use a variable.:: + sage: sie._sie_prepare(sif) sage: sie._sie_prepare(sif) sage: sif._commands @@ -3159,7 +3320,8 @@ def format(self, e, prec): 'GF_5 = GF(5)\n' We demonstrate the use of commands, by showing how to construct - code that will produce a random matrix: + code that will produce a random matrix:: + sage: sib = SageInputBuilder() sage: sif = SageInputFormatter() sage: sie = sib.name('matrix')(sib.name('ZZ'), 10, 10) @@ -3204,10 +3366,11 @@ def register_name(self, name): requested name; otherwise, we will add numbers to the end of the name to make it unique. - If the input name is \code{None}, then it is treated as a name of - \code{'si'}. + If the input name is ``None``, then it is treated as a name of + ``'si'``. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputFormatter sage: sif = SageInputFormatter() @@ -3235,10 +3398,11 @@ def get_name(self, name): requested name; otherwise, we will add numbers to the end of the name to make it unique. - If the input name is \code{None}, then it is treated as a name of - \code{'si'}. + If the input name is ``None``, then it is treated as a name of + ``'si'``. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputFormatter sage: sif = SageInputFormatter() @@ -3261,14 +3425,15 @@ def get_name(self, name): def verify_same(a, b): r""" - Verify that two \sage values are the same. This is an extended equality + Verify that two Sage values are the same. This is an extended equality test; it checks that the values are equal and that their parents are equal. (For values which are not Elements, the types are checked instead.) - If the values are the same, we return \code{None}; otherwise, + If the values are the same, we return ``None``; otherwise, we raise an exception. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import verify_same sage: verify_same(1, 1) sage: verify_same(1, 2) @@ -3315,21 +3480,26 @@ def verify_same(a, b): def verify_si_answer(x, answer, preparse): r""" - INPUTS: - x -- an arbitrary \sage value - answer -- a string, or a \class{SageInputAnswer} - preparse -- \code{True}, \code{False}, or \code{None} - - Verify that evaluating \var{answer} gives a value equal to \var{x} - (with the same parent/type). If \var{preparse} is \code{True} or - \code{False}, then we evaluate \var{answer} with the preparser - enabled or disabled, respectively; if \var{preparse} is \code{None}, - then we evaluate \var{answer} both with the preparser enabled and + Verify that evaluating ``answer`` gives a value equal to ``x`` + (with the same parent/type). If ``preparse`` is ``True`` or + ``False``, then we evaluate ``answer`` with the preparser + enabled or disabled, respectively; if ``preparse`` is ``None``, + then we evaluate ``answer`` both with the preparser enabled and disabled and check both results. - On success, we return \code{None}; on failure, we raise an exception. + On success, we return ``None``; on failure, we raise an exception. + + INPUT: + + - ``x`` - an arbitrary Sage value + + - ``answer`` - a string, or a :class:`SageInputAnswer` + + - ``preparse`` -- ``True``, ``False``, or ``None`` + + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import verify_si_answer sage: verify_si_answer(1, '1', True) sage: verify_si_answer(1, '1', False) @@ -3348,9 +3518,10 @@ def verify_si_answer(x, answer, preparse): class SageInputAnswer(tuple): r""" This class inherits from tuple, so it acts like a tuple when passed - to \function{sage_eval}; but it prints as a sequence of commands. + to :func:`sage_eval`; but it prints as a sequence of commands. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputAnswer sage: v = SageInputAnswer('x = 22\n', 'x/7'); v x = 22 @@ -3377,9 +3548,10 @@ class SageInputAnswer(tuple): def __new__(cls, cmds, expr, locals=None): r""" - Construct an instance of \class{SageInputAnswer}. + Construct an instance of :class:`SageInputAnswer`. + + EXAMPLES:: - EXAMPLES: sage: from sage.misc.sage_input import SageInputAnswer sage: v = SageInputAnswer('', 'sin(3.14)', {'sin': math.sin}); v LOCALS: @@ -3399,12 +3571,13 @@ def __new__(cls, cmds, expr, locals=None): def __repr__(self): r""" - Return a string representation for a \class{SageInputAnswer}, - such that if you evaluate this \class{SageInputAnswer} at the + Return a string representation for a :class:`SageInputAnswer`, + such that if you evaluate this :class:`SageInputAnswer` at the \sage command line, you get a result in a nice form ready to copy-and-paste. - EXAMPLES: + EXAMPLES:: + sage: from sage.misc.sage_input import SageInputAnswer sage: v = SageInputAnswer('', 'sin(3.14)', {'sin': math.sin}); v LOCALS: diff --git a/src/sage/misc/sage_itertools.py b/src/sage/misc/sage_itertools.py index 93177dbd06c..6b2c78c2713 100644 --- a/src/sage/misc/sage_itertools.py +++ b/src/sage/misc/sage_itertools.py @@ -77,7 +77,7 @@ def min_cmp(L, cmp=None): iterator = iter(L) try: - m = iterator.next() + m = next(iterator) except StopIteration: raise ValueError("min_cmp() arg is an empty sequence") for item in iterator: @@ -132,7 +132,7 @@ def max_cmp(L, cmp=None): iterator = iter(L) try: - m = iterator.next() + m = next(iterator) except StopIteration: raise ValueError("max_cmp() arg is an empty sequence") for item in iterator: @@ -149,10 +149,10 @@ def imap_and_filter_none(function, iterable): sage: from sage.misc.sage_itertools import imap_and_filter_none sage: p = imap_and_filter_none(lambda x: x if is_prime(x) else None, range(15)) - sage: [p.next(), p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p), next(p)] [2, 3, 5, 7, 11, 13] sage: p = imap_and_filter_none(lambda x: x+x, ['a','b','c','d','e']) - sage: [p.next(), p.next(), p.next(), p.next(), p.next()] + sage: [next(p), next(p), next(p), next(p), next(p)] ['aa', 'bb', 'cc', 'dd', 'ee'] """ for x in iterable: diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index 95c3b4d9773..2bc1cc5ecae 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -37,7 +37,7 @@ import os, re, sys import pydoc from sage.misc.viewer import browser -from sage.misc.misc import tmp_dir +from sage.misc.temporary_file import tmp_dir import sage.version from sage.env import SAGE_DOC, SAGE_SRC @@ -1036,7 +1036,7 @@ def search_doc(string, extra1='', extra2='', extra3='', extra4='', sage: len(search_doc('tree', interact=False).splitlines()) > 4000 # long time True - sage: len(search_doc('tree', whole_word=True, interact=False).splitlines()) < 1000 # long time + sage: len(search_doc('tree', whole_word=True, interact=False).splitlines()) < 2000 # long time True """ return _search_src_or_doc('doc', string, extra1=extra1, extra2=extra2, diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 2f6df5e62b8..aef66173c07 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -1813,7 +1813,7 @@ def sage_getsourcelines(obj, is_binary=False): ' cpdef object pyobject(self):\n', ...) sage: sage_getsourcelines(x)[0][-1] # last line - ' return self / x\n' + ' return S\n' We show some enhancements provided by :trac:`11768`. First, we use a dummy parent class that has defined an element class by a diff --git a/src/sage/misc/superseded.py b/src/sage/misc/superseded.py index eac9620e944..3fd067fc636 100644 --- a/src/sage/misc/superseded.py +++ b/src/sage/misc/superseded.py @@ -337,7 +337,7 @@ def deprecated_callable_import(trac_number, module_name, globs, locs, fromlist, message = '\nUsing %(name)s from here is deprecated. ' + \ 'If you need to use it, please import it directly from %(module_name)s.' from functools import partial - from sage.misc.misc import sage_wraps + from sage.misc.decorators import sage_wraps if module_name is None: mod_dict = globs else: diff --git a/src/sage/misc/weak_dict.pyx b/src/sage/misc/weak_dict.pyx index 72caa67f96d..7a8810f0818 100644 --- a/src/sage/misc/weak_dict.pyx +++ b/src/sage/misc/weak_dict.pyx @@ -121,7 +121,7 @@ from copy import deepcopy from cpython.dict cimport * from cpython.weakref cimport * from cpython.list cimport * - +from cpython.object cimport PyObject_Hash from cpython cimport Py_XINCREF, Py_XDECREF cdef extern from "Python.h": @@ -142,8 +142,6 @@ cdef extern from "Python.h": #strategy according to Cython/Includes/cpython/__init__.pxd PyObject* PyWeakref_GetObject(PyObject * wr) int PyList_SetItem(object list, Py_ssize_t index,PyObject * item) except -1 - #this one's just missing. - long PyObject_Hash(object obj) except -1 cdef PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL: cdef PyDictEntry* ep @@ -954,7 +952,8 @@ cdef class WeakValueDictionary(dict): [0, 1, 2, 3, 5, 6, 7, 8, 9] """ - cdef PyObject *key, *wr + cdef PyObject *key + cdef PyObject *wr cdef Py_ssize_t pos = 0 try: self._enter_iter() @@ -1059,7 +1058,8 @@ cdef class WeakValueDictionary(dict): <9> """ - cdef PyObject *key, *wr + cdef PyObject *key + cdef PyObject *wr cdef Py_ssize_t pos = 0 try: self._enter_iter() @@ -1159,7 +1159,8 @@ cdef class WeakValueDictionary(dict): [9] <9> """ - cdef PyObject *key, *wr + cdef PyObject *key + cdef PyObject *wr cdef Py_ssize_t pos = 0 try: self._enter_iter() diff --git a/src/sage/modular/abvar/abvar.py b/src/sage/modular/abvar/abvar.py index b8bd4cc1165..efeabb580c8 100644 --- a/src/sage/modular/abvar/abvar.py +++ b/src/sage/modular/abvar/abvar.py @@ -44,7 +44,7 @@ from sage.modules.all import vector from sage.groups.all import AbelianGroup from sage.databases.cremona import cremona_letter_code -from sage.misc.misc import prod +from sage.misc.all import prod from copy import copy diff --git a/src/sage/modular/abvar/finite_subgroup.py b/src/sage/modular/abvar/finite_subgroup.py index 193f4598911..6bc30dc9fc0 100644 --- a/src/sage/modular/abvar/finite_subgroup.py +++ b/src/sage/modular/abvar/finite_subgroup.py @@ -95,10 +95,10 @@ from sage.modules.module import Module_old from sage.modules.free_module import is_FreeModule -from sage.structure.element import ModuleElement -from sage.structure.sequence import Sequence -from sage.rings.all import gcd, lcm, QQ, ZZ, QQbar, Integer, composite_field -from sage.misc.misc import prod +from sage.structure.element import ModuleElement +from sage.structure.sequence import Sequence +from sage.rings.all import gcd, lcm, QQ, ZZ, QQbar, Integer, composite_field +from sage.misc.all import prod import abvar as abelian_variety from sage.categories.fields import Fields diff --git a/src/sage/modular/arithgroup/congroup_gamma.py b/src/sage/modular/arithgroup/congroup_gamma.py index dd7b4b263a9..7787298ffcc 100644 --- a/src/sage/modular/arithgroup/congroup_gamma.py +++ b/src/sage/modular/arithgroup/congroup_gamma.py @@ -15,7 +15,7 @@ ################################################################################ from congroup_generic import CongruenceSubgroup -from sage.misc.misc import prod +from sage.misc.all import prod from sage.rings.all import ZZ, Zmod, gcd, QQ from sage.rings.integer import GCD_list from sage.groups.matrix_gps.finitely_generated import MatrixGroup diff --git a/src/sage/modular/arithgroup/congroup_gamma0.py b/src/sage/modular/arithgroup/congroup_gamma0.py index f00ce991b9e..baaf1f9a12e 100644 --- a/src/sage/modular/arithgroup/congroup_gamma0.py +++ b/src/sage/modular/arithgroup/congroup_gamma0.py @@ -22,7 +22,7 @@ from sage.modular.cusps import Cusp from sage.misc.cachefunc import cached_method from sage.rings.all import (IntegerModRing, kronecker_symbol, ZZ) -from sage.misc.misc import prod +from sage.misc.all import prod import sage.modular.modsym.p1list import sage.rings.arith as arith diff --git a/src/sage/modular/arithgroup/congroup_gamma1.py b/src/sage/modular/arithgroup/congroup_gamma1.py index 152567cc636..c66edf1083c 100644 --- a/src/sage/modular/arithgroup/congroup_gamma1.py +++ b/src/sage/modular/arithgroup/congroup_gamma1.py @@ -16,7 +16,7 @@ from sage.misc.cachefunc import cached_method -from sage.misc.misc import prod +from sage.misc.all import prod from congroup_gammaH import GammaH_class, is_GammaH, GammaH_constructor from sage.rings.all import ZZ, euler_phi as phi, moebius, divisors from sage.modular.dirichlet import DirichletGroup diff --git a/src/sage/modular/cusps.py b/src/sage/modular/cusps.py index 2916976166c..116b0ac5c29 100644 --- a/src/sage/modular/cusps.py +++ b/src/sage/modular/cusps.py @@ -36,6 +36,7 @@ from sage.modular.modsym.p1list import lift_to_sl2z_llong from sage.matrix.matrix import is_Matrix from sage.misc.cachefunc import cached_method +from sage.misc.superseded import deprecated_function_alias class Cusps_class(ParentWithBase): """ @@ -152,7 +153,7 @@ def _coerce_impl(self, x): return self._coerce_try(x, QQ) @cached_method - def zero_element(self): + def zero(self): """ Return the zero cusp. @@ -163,12 +164,14 @@ def zero_element(self): EXAMPLE:: - sage: Cusps.zero_element() + sage: Cusps.zero() 0 """ return Cusp(0, parent=self) + zero_element = deprecated_function_alias(17694, zero) + Cusps = Cusps_class() @@ -678,8 +681,8 @@ def is_gamma0_equiv(self, other, N, transformation = None): u2 = other.__a v2 = other.__b - zero = ZZ.zero_element() - one = ZZ.one_element() + zero = ZZ.zero() + one = ZZ.one() if transformation == "matrix": from sage.matrix.constructor import matrix diff --git a/src/sage/modular/cusps_nf.py b/src/sage/modular/cusps_nf.py index 75c4519989b..780d20916d2 100644 --- a/src/sage/modular/cusps_nf.py +++ b/src/sage/modular/cusps_nf.py @@ -86,6 +86,7 @@ from sage.structure.parent_base import ParentWithBase from sage.structure.element import Element, is_InfinityElement from sage.misc.cachefunc import cached_method +from sage.misc.superseded import deprecated_function_alias _nfcusps_cache = {} @@ -353,7 +354,7 @@ def __call__(self, x): return NFCusp(self.number_field(), x, parent=self) @cached_method - def zero_element(self): + def zero(self): """ Return the zero cusp. @@ -367,12 +368,14 @@ def zero_element(self): sage: k. = NumberField(x^2 + 5) sage: kCusps = NFCusps(k) - sage: kCusps.zero_element() + sage: kCusps.zero() Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5 """ return self(0) + zero_element = deprecated_function_alias(17694, zero) + def number_field(self): """ Return the number field that this set of cusps is attached to. @@ -1265,7 +1268,7 @@ def NFCusps_ideal_reps_for_levelN(N, nlists=1): if not I.is_principal(): Iinv = (I.ideal())**(-1) while check 1: - return misc.mul([d.conductor() for d in self.decomposition()]) + return prod([d.conductor() for d in self.decomposition()]) p = F[0][0] # When p is odd, and x =/= 1, the conductor is the smallest p**r such that # Order(x) divides EulerPhi(p**r) = p**(r-1)*(p-1). @@ -1575,8 +1575,8 @@ def values(self): zeta_order = G.zeta_order() zeta = R.zeta(zeta_order) A = rings.Integers(zeta_order) - A_zero = A.zero_element() - A_one = A.one_element() + A_zero = A.zero() + A_one = A.one() ZZ = rings.ZZ S = G._integers diff --git a/src/sage/modular/hecke/algebra.py b/src/sage/modular/hecke/algebra.py index fe68f649785..e082f0ca84d 100644 --- a/src/sage/modular/hecke/algebra.py +++ b/src/sage/modular/hecke/algebra.py @@ -546,9 +546,9 @@ def gens(self): sage: T = ModularSymbols(1,12).hecke_algebra() sage: g = T.gens() - sage: g.next() + sage: next(g) Hecke operator T_1 on Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field - sage: g.next() + sage: next(g) Hecke operator T_2 on Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field """ n = 1 @@ -769,9 +769,9 @@ def gens(self): sage: T = ModularSymbols(12,2).anemic_hecke_algebra() sage: g = T.gens() - sage: g.next() + sage: next(g) Hecke operator T_1 on Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Rational Field - sage: g.next() + sage: next(g) Hecke operator T_5 on Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Rational Field """ level = self.level() diff --git a/src/sage/modular/modform/eis_series_cython.pyx b/src/sage/modular/modform/eis_series_cython.pyx index d2f6199bf30..2e95ab657f8 100644 --- a/src/sage/modular/modform/eis_series_cython.pyx +++ b/src/sage/modular/modform/eis_series_cython.pyx @@ -163,14 +163,14 @@ cpdef eisenstein_series_poly(int k, int prec = 10) : cdef unsigned long int expt cdef long ind, ppow, int_p cdef int i - cdef Fmpz_poly res = PY_NEW(Fmpz_poly) + cdef Fmpz_poly res = Fmpz_poly.__new__(Fmpz_poly) if k%2 or k < 2: raise ValueError, "k (=%s) must be an even positive integer"%k if prec < 0: raise ValueError, "prec (=%s) must be an even nonnegative integer"%prec if (prec == 0): - return PY_NEW(Fmpz_poly) + return Fmpz_poly.__new__(Fmpz_poly) sig_on() diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index 4656094c335..74c7dc044a0 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -622,11 +622,13 @@ def period(self, M, prec=53): TypeError: matrix [-4 -3] [15 11] is not an element of Congruence Subgroup Gamma0(11) + sage: f = Newforms(Gamma0(15), 4)[0] sage: f.period(g) Traceback (most recent call last): ... ValueError: period pairing only defined for cusp forms of weight 2 + sage: S = Newforms(Gamma1(17), 2, names='a') sage: f = S[1] sage: g = Gamma1(17)([18, 1, 17, 1]) @@ -634,6 +636,7 @@ def period(self, M, prec=53): Traceback (most recent call last): ... NotImplementedError: period pairing only implemented for cusp forms of trivial character + sage: E = ModularForms(Gamma0(4), 2).eisenstein_series()[0] sage: gamma = Gamma0(4)([1, 0, 4, 1]) sage: E.period(gamma) @@ -641,6 +644,11 @@ def period(self, M, prec=53): ... NotImplementedError: Don't know how to compute Atkin-Lehner matrix acting on this space (try using a newform constructor instead) + sage: E = EllipticCurve('19a1') + sage: M = Gamma0(19)([10, 1, 19, 2]) + sage: E.newform().period(M) # abs tol 1e-14 + -1.35975973348831 + 1.09365931898146e-16*I + """ R = rings.RealField(prec) @@ -656,7 +664,7 @@ def period(self, M, prec=53): # coefficients of the matrix M (b, c, d) = (M.b(), M.c() / N, M.d()) if d == 0: - return R.zero_element() + return R.zero() if d < 0: (b, c, d) = (-b, -c, -d) @@ -1416,7 +1424,6 @@ def atkin_lehner_eigenvalue(self, d=None): else: return self.__E.modular_symbol_space().atkin_lehner_operator(d).matrix()[0,0] -###################################################################### class EisensteinSeries(ModularFormElement): """ diff --git a/src/sage/modular/modform/find_generators.py b/src/sage/modular/modform/find_generators.py index bcb968f8bd8..963f7a62233 100644 --- a/src/sage/modular/modform/find_generators.py +++ b/src/sage/modular/modform/find_generators.py @@ -9,10 +9,20 @@ - William Stein (2007-08-24): first version """ - -from sage.rings.all import Integer, QQ, ZZ, PowerSeriesRing -from sage.misc.misc import prod, verbose -from sage.misc.cachefunc import cached_method +#***************************************************************************** +# Copyright (C) 2007 William Stein +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + + +from sage.rings.all import Integer, QQ, ZZ, PowerSeriesRing +from sage.misc.all import prod, verbose +from sage.misc.cachefunc import cached_method from sage.modular.arithgroup.all import Gamma0, is_CongruenceSubgroup from constructor import ModularForms from sage.structure.sage_object import SageObject diff --git a/src/sage/modular/modform/space.py b/src/sage/modular/modform/space.py index b1bb072361b..a729de9a75a 100644 --- a/src/sage/modular/modform/space.py +++ b/src/sage/modular/modform/space.py @@ -1158,7 +1158,7 @@ def __call__(self, x, check=True): elif is_PowerSeries(x): if x.prec() == PlusInfinity(): if x == 0: - return element.ModularFormElement(self, self.free_module().zero_element()) + return element.ModularFormElement(self, self.free_module().zero()) else: raise TypeError("unable to create modular form from exact non-zero polynomial") W = self._q_expansion_module() diff --git a/src/sage/modular/modform_hecketriangle/abstract_ring.py b/src/sage/modular/modform_hecketriangle/abstract_ring.py index e5339998bb5..6577462c05f 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_ring.py +++ b/src/sage/modular/modform_hecketriangle/abstract_ring.py @@ -1802,7 +1802,7 @@ def EisensteinSeries(self, k=None): sage: from sage.modular.modform_hecketriangle.graded_ring import ModularFormsRing, CuspFormsRing sage: MR = ModularFormsRing() - sage: MR.EisensteinSeries() == MR.one_element() + sage: MR.EisensteinSeries() == MR.one() True sage: E8 = MR.EisensteinSeries(k=8) sage: E8 in MR diff --git a/src/sage/modular/modform_hecketriangle/abstract_space.py b/src/sage/modular/modform_hecketriangle/abstract_space.py index dd59d62d004..ec540df6d90 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_space.py +++ b/src/sage/modular/modform_hecketriangle/abstract_space.py @@ -312,9 +312,8 @@ def _coerce_map_from_(self, S): and self.coeff_ring().has_coerce_map_from(S) # Since forms spaces are modules instead of rings - # we have to manually define one_element() and one(). + # we have to manually define one(). # one() allows to take the power 0 of an element - # one_element() allows to take negative powers of elements @cached_method def one(self): r""" @@ -332,7 +331,6 @@ def one(self): sage: (MF.Delta()^0).parent() ModularForms(n=3, k=0, ep=1) over Integer Ring """ - return self.extend_type("holo", ring=True)(1).reduce() def one_element(self): @@ -349,9 +347,12 @@ def one_element(self): sage: (MF.Delta()^(-1)).parent() MeromorphicModularForms(n=3, k=-12, ep=1) over Integer Ring sage: MF.one_element() + doctest:...: DeprecationWarning: .one_element() is deprecated. Use .one() instead. + See http://trac.sagemath.org/17694 for details. 1 + O(q^5) """ - + from sage.misc.superseded import deprecation + deprecation(17694, ".one_element() is deprecated. Use .one() instead.") return self.one() def is_ambient(self): diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py index ce5f8a092ed..97e47474e18 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py @@ -126,21 +126,20 @@ def _latex_(self): return '\\Gamma^{(%s)}'%(latex(self._n)) - def one_element(self): + def one(self): r""" Return the identity element/matrix for ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup - sage: HeckeTriangleGroup(10).one_element() + sage: HeckeTriangleGroup(10).one() [1 0] [0 1] - sage: HeckeTriangleGroup(10).one_element().parent() + sage: HeckeTriangleGroup(10).one().parent() Hecke triangle group for n = 10 """ - return self.I() @cached_method diff --git a/src/sage/modular/modform_hecketriangle/series_constructor.py b/src/sage/modular/modform_hecketriangle/series_constructor.py index 23ad50ef696..827bf07b4b2 100644 --- a/src/sage/modular/modform_hecketriangle/series_constructor.py +++ b/src/sage/modular/modform_hecketriangle/series_constructor.py @@ -236,7 +236,7 @@ def J_inv_ZZ(self): q = self._series_ring.gen() # the current implementation of power series reversion is slow - # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reversion()) + # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reverse()) temp_f = (q*Phi.exp()).polynomial() new_f = temp_f.revert_series(temp_f.degree()+1) diff --git a/src/sage/modular/modsym/ambient.py b/src/sage/modular/modsym/ambient.py index 459221ffbfb..2b6b1d0e165 100644 --- a/src/sage/modular/modsym/ambient.py +++ b/src/sage/modular/modsym/ambient.py @@ -641,7 +641,10 @@ def _modular_symbol_0_to_alpha(self, alpha, i=0): """ if alpha.is_infinity(): return self.manin_symbol((i,0,1), check=False) - v, c = arith.continued_fraction_list(alpha._rational_(), partial_convergents=True) + # v, c = arith.continued_fraction_list(alpha._rational_(), partial_convergents=True) + cf = alpha._rational_().continued_fraction() + v = list(cf) + c = [(cf.p(k),cf.q(k)) for k in xrange(len(cf))] a = self(0) zero = rings.ZZ(0) one = rings.ZZ(1) diff --git a/src/sage/modular/modsym/heilbronn.pyx b/src/sage/modular/modsym/heilbronn.pyx index e1b8b03249b..3edb94b5b8d 100644 --- a/src/sage/modular/modsym/heilbronn.pyx +++ b/src/sage/modular/modsym/heilbronn.pyx @@ -58,7 +58,8 @@ cdef struct list: int n # how much memory has been allocated cdef int* expand(int *v, int n, int new_length) except NULL: - cdef int *w, i + cdef int *w + cdef int i w = sage_malloc(new_length*sizeof(int)) if w == 0: return NULL @@ -548,7 +549,9 @@ def hecke_images_gamma0_weight2(int u, int v, int N, indices, R): R = R.change_ring(QQ) cdef Py_ssize_t i, j - cdef int *a, *b, k + cdef int *a + cdef int *b + cdef int k cdef Heilbronn H @@ -675,7 +678,9 @@ def hecke_images_nonquad_character_weight2(int u, int v, int N, indices, chi, R) T = matrix(K, len(indices), len(P1), sparse=False) cdef Py_ssize_t i, j - cdef int *a, *b, k, scalar + cdef int *a + cdef int *b + cdef int k, scalar cdef Heilbronn H @@ -769,7 +774,9 @@ def hecke_images_quad_character_weight2(int u, int v, int N, indices, chi, R): R = R.change_ring(QQ) cdef Py_ssize_t i, j - cdef int *a, *b, k, scalar + cdef int *a + cdef int *b + cdef int k, scalar cdef Heilbronn H t = sage.misc.misc.verbose("computing non-reduced images of symbol under Hecke operators", @@ -861,7 +868,8 @@ def hecke_images_gamma0_weight_k(int u, int v, int i, int N, int k, indices, R): R = R.change_ring(QQ) cdef Py_ssize_t j, m, z, w, n, p - cdef int *a, *b + cdef int *a + cdef int *b n = len(P1) diff --git a/src/sage/modular/modsym/modular_symbols.py b/src/sage/modular/modsym/modular_symbols.py index c46f143369a..ed2146dabb3 100644 --- a/src/sage/modular/modsym/modular_symbols.py +++ b/src/sage/modular/modsym/modular_symbols.py @@ -36,7 +36,6 @@ import sage.modular.modsym.manin_symbols from sage.structure.sage_object import SageObject import sage.structure.formal_sum as formal_sum -import sage.rings.arith as arith from sage.rings.integer_ring import ZZ from sage.misc.latex import latex @@ -333,7 +332,8 @@ def __manin_symbol_rep(self, alpha): k = space.weight() v = [(0,1), (1,0)] if not alpha.is_infinity(): - v += [(x.numerator(), x.denominator()) for x in arith.convergents(alpha._rational_())] + cf = alpha._rational_().continued_fraction() + v.extend((cf.p(k),cf.q(k)) for k in xrange(len(cf))) sign = 1 apply = sage.modular.modsym.manin_symbols.apply_to_monomial mansym = sage.modular.modsym.manin_symbols.ManinSymbol diff --git a/src/sage/modular/modsym/p1list.pxd b/src/sage/modular/modsym/p1list.pxd index 0628f457687..1a78ab5923c 100644 --- a/src/sage/modular/modsym/p1list.pxd +++ b/src/sage/modular/modsym/p1list.pxd @@ -14,7 +14,9 @@ cdef class P1List: cdef int __N cdef object __list, __end_hash - cdef int *g, *s, *t # xgcd with N table. + cdef int *g + cdef int *s + cdef int *t # xgcd with N table. # Here we use a pointer to a function, so the if logic # for normalizing an element does not need to be used diff --git a/src/sage/modular/modsym/p1list_nf.py b/src/sage/modular/modsym/p1list_nf.py index f98d0f234b6..1b018dd8838 100644 --- a/src/sage/modular/modsym/p1list_nf.py +++ b/src/sage/modular/modsym/p1list_nf.py @@ -1001,9 +1001,9 @@ def p1NFlist(N): c = D.gens_reduced()[0] else: it = k.primes_of_degree_one_iter() - Dp = it.next() + Dp = next(it) while not Dp.is_coprime(N) or not (Dp*D).is_principal(): - Dp = it.next() + Dp = next(it) c = (D*Dp).gens_reduced()[0] #now we find all the (c,d)'s which have associated divisor D I = D + N/D @@ -1100,7 +1100,7 @@ def lift_to_sl2_Ok(N, c, d): it = k.primes_of_degree_one_iter() q = k.ideal(1) while not (q.is_coprime(d) and (q*N).is_principal()): - q = it.next() + q = next(it) m = (q*N).gens_reduced()[0] B = k.ideal(m).element_1_mod(k.ideal(d)) return [(1-B)/d, -B/m, m, d] @@ -1108,7 +1108,7 @@ def lift_to_sl2_Ok(N, c, d): it = k.primes_of_degree_one_iter() q = k.ideal(1) while not (q.is_coprime(c) and (q*N).is_principal()): - q = it.next() + q = next(it) m = (q*N).gens_reduced()[0] B = k.ideal(c).element_1_mod(k.ideal(m)) return [(1-B)/m, -B/c, c, m] @@ -1162,7 +1162,7 @@ def make_coprime(N, c, d): r = k.ideal(1) qN = q*N while not (r.is_coprime(c) and (r*qN).is_principal()): - r = it.next() + r = next(it) m = (r*qN).gens_reduced()[0] d1 = d + m return c, d1 @@ -1191,7 +1191,7 @@ def psi(N): if not N.is_integral(): raise ValueError("psi only defined for integral ideals") - from sage.misc.misc import prod + from sage.misc.all import prod return prod([(np+1)*np**(e-1) \ for np,e in [(p.absolute_norm(),e) \ for p,e in N.factor()]]) diff --git a/src/sage/modular/modsym/space.py b/src/sage/modular/modsym/space.py index d782551da50..d1fee3ab46f 100644 --- a/src/sage/modular/modsym/space.py +++ b/src/sage/modular/modsym/space.py @@ -26,7 +26,7 @@ import sage.modules.free_module as free_module import sage.matrix.matrix_space as matrix_space from sage.modules.free_module_element import is_FreeModuleElement -import sage.misc.misc as misc +import sage.misc.all as misc import sage.modular.hecke.all as hecke import sage.rings.arith as arith import sage.rings.fast_arith as fast_arith diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index f9ac34c759d..09a5f652d4d 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -177,6 +177,7 @@ from sage.matrix.all import matrix, MatrixSpace, diagonal_matrix from sage.misc.misc import verbose from sage.misc.cachefunc import cached_method +from sage.misc.superseded import deprecated_function_alias from sage.modular.all import (DirichletGroup, trivial_character, EtaProduct, j_invariant_qexp, hecke_operator_on_qexp) from sage.modular.arithgroup.all import (Gamma1, is_Gamma0, is_Gamma1) @@ -595,9 +596,9 @@ def gens(self): sage: o = OverconvergentModularForms(3, 12, 1/2) sage: t = o.gens() - sage: t.next() + sage: next(t) 3-adic overconvergent modular form of weight-character 12 with q-expansion 1 - 32760/61203943*q - 67125240/61203943*q^2 - ... - sage: t.next() + sage: next(t) 3-adic overconvergent modular form of weight-character 12 with q-expansion 27*q + 19829193012/61203943*q^2 + 146902585770/61203943*q^3 + ... """ i = 0 @@ -725,18 +726,20 @@ def __call__(self, input): raise TypeError("Don't know how to create an overconvergent modular form from %s" % input) @cached_method - def zero_element(self): + def zero(self): """ Return the zero of this space. EXAMPLE:: sage: K. = Qp(13).extension(x^2-13); M = OverconvergentModularForms(13, 20, radius=1/2, base_ring=K) - sage: K.zero_element() + sage: K.zero() 0 """ return self(0) + zero_element = deprecated_function_alias(17694, zero) + def _coerce_from_ocmf(self, f): r""" Try to convert the overconvergent modular form `f` into an element of self. An error will be raised if this is diff --git a/src/sage/modular/overconvergent/weightspace.py b/src/sage/modular/overconvergent/weightspace.py index 04a15764635..3ee2366b00b 100644 --- a/src/sage/modular/overconvergent/weightspace.py +++ b/src/sage/modular/overconvergent/weightspace.py @@ -68,6 +68,7 @@ from sage.rings.padics.padic_generic_element import pAdicGenericElement from sage.misc.misc import verbose from sage.misc.cachefunc import cached_method +from sage.misc.superseded import deprecated_function_alias from sage.rings.padics.precision_error import PrecisionError import weakref @@ -199,18 +200,20 @@ def __call__(self, arg1, arg2 = None, algebraic=True): return ArbitraryWeight(self, arg1, arg2) @cached_method - def zero_element(self): + def zero(self): """ Return the zero of this weight space. EXAMPLES:: sage: W = pAdicWeightSpace(17) - sage: W.zero_element() + sage: W.zero() 0 """ return self(0) + zero_element = deprecated_function_alias(17694, zero) + def prime(self): r""" Return the prime `p` such that this is a `p`-adic weight space. diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 48af9b3d304..ff1375126ff 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -1159,7 +1159,7 @@ def __iter__(self): return R = self.base_ring() iters = [iter(R) for _ in range(len(G))] - for x in iters: x.next() # put at 0 + for x in iters: next(x) # put at 0 zero = R(0) v = [zero for _ in range(len(G))] n = 0 @@ -1167,12 +1167,12 @@ def __iter__(self): yield z while n < len(G): try: - v[n] = iters[n].next() + v[n] = next(iters[n]) yield self.linear_combination_of_basis(v) n = 0 except StopIteration: iters[n] = iter(R) # reset - iters[n].next() # put at 0 + next(iters[n]) # put at 0 v[n] = zero n += 1 @@ -2256,17 +2256,30 @@ def _mul_(self, other, switch_sides=False): sage: A * m Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: - [1 1 1] - [0 3 6] + [ 3 0 -3] + [ 0 1 2] sage: m * A Free module of degree 3 and rank 2 over Integer Ring Echelon basis matrix: [ 3 0 -3] [ 0 1 2] + + TESTS: + + Check that :trac:`17705` is fixed:: + + sage: V = GF(2)^2 + sage: W = V.subspace([[1, 0]]) + sage: x = matrix(GF(2), [[1, 1], [0, 1]]) + sage: W*x + Vector space of degree 2 and dimension 1 over Finite Field of size 2 + Basis matrix: + [1 1] + """ - if switch_sides: - return self.span([v * other for v in self.basis()]) - return self.span([other * v for v in self.basis()]) + B = self.basis_matrix() + B = other * B if switch_sides else B * other + return self.span(B.rows()) def base_field(self): """ diff --git a/src/sage/modules/free_module_element.pxd b/src/sage/modules/free_module_element.pxd index 345d55901ec..d37e3c9939f 100644 --- a/src/sage/modules/free_module_element.pxd +++ b/src/sage/modules/free_module_element.pxd @@ -2,7 +2,6 @@ from sage.structure.element cimport Vector cdef class FreeModuleElement(Vector): cdef bint _is_mutable - cdef int _cmp_same_ambient_c(left, FreeModuleElement right) except -2 cpdef int hamming_weight(self) cdef class FreeModuleElement_generic_dense(FreeModuleElement): diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index e7008413868..d3e06708282 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -106,40 +106,26 @@ TESTS:: # http://www.gnu.org/licenses/ #***************************************************************************** -import math - -include 'sage/ext/stdsage.pxi' +cimport cython from sage.structure.sequence import Sequence - -from sage.structure.element cimport Element, ModuleElement, RingElement, Vector as element_Vector +from sage.structure.element cimport Element, ModuleElement, RingElement, Vector from sage.structure.element import canonical_coercion -import sage.rings.arith - -from sage.rings.infinity import Infinity -import sage.rings.integer +from sage.rings.ring import is_Ring +from sage.rings.infinity import Infinity, AnInfinity from sage.rings.integer_ring import ZZ from sage.rings.real_double import RDF from sage.rings.complex_double import CDF from sage.misc.derivative import multi_derivative from sage.rings.ring cimport Ring -from sage.rings.integer cimport Integer - -# We define our own faster is_Ring since is_Ring in the -# sage.rings.ring module is slow due to it doing an import every time, -# and creating a category. We should rarely hit the second case -# (is_Ring_slow below). Note that this function will slightly slow -# down in the very rare case when R is not of type Ring, but it is in -# the category of rings. But it gives a big speedup for the most -# common case when R is a Ring. -from sage.rings.ring import is_Ring as is_Ring_slow -cdef is_Ring(R): - return isinstance(R, Ring) or is_Ring_slow(R) - -#For the norm function, we cache a Sage integer "one" -__one__ = sage.rings.integer.Integer(1) +from sage.rings.integer cimport Integer, smallInteger + +# For the norm function, we cache Sage integers 1 and 2 +__one__ = smallInteger(1) +__two__ = smallInteger(2) + def is_FreeModuleElement(x): """ @@ -442,7 +428,7 @@ def vector(arg0, arg1=None, arg2=None, sparse=None): # We first efficiently handle the important special case of the zero vector # over a ring. See trac 11657. # !! PLEASE DO NOT MOVE THIS CODE LOWER IN THIS FUNCTION !! - if arg2 is None and is_Ring(arg0) and (isinstance(arg1, (int, long, Integer))): + if arg2 is None and is_Ring(arg0) and isinstance(arg1, (Integer, int, long)): return (arg0**arg1).zero_vector() # WARNING TO FUTURE OPTIMIZERS: The following two hasattr's take @@ -456,7 +442,7 @@ def vector(arg0, arg1=None, arg2=None, sparse=None): # consider a possible degree specified in second argument degree = None maxindex = None - if sage.rings.integer.is_Integer(arg1) or isinstance(arg1,(int,long)): + if isinstance(arg1, (Integer, int, long)): if arg1 < 0: raise ValueError("cannot specify the degree of a vector as a negative integer (%s)" % arg1) if isinstance(arg2, dict): @@ -804,14 +790,14 @@ def random_vector(ring, degree=None, *args, **kwds): ... ValueError: degree of a random vector must be non-negative, not -9 """ - if sage.rings.integer.is_Integer(ring) or isinstance(ring,(int,long)): + if isinstance(ring, (Integer, int, long)): if not degree is None: arglist = list(args) arglist.insert(0, degree) args = tuple(arglist) degree = ring ring = ZZ - if not (sage.rings.integer.is_Integer(degree) or isinstance(degree,(int,long))): + if not isinstance(degree,(Integer, int, long)): raise TypeError("degree of a random vector must be an integer, not %s" % degree) if degree < 0: raise ValueError("degree of a random vector must be non-negative, not %s" % degree) @@ -823,7 +809,7 @@ def random_vector(ring, degree=None, *args, **kwds): entries = [ring.random_element(*args, **kwds) for _ in range(degree)] return vector(ring, degree, entries, sparse) -cdef class FreeModuleElement(element_Vector): # abstract base class +cdef class FreeModuleElement(Vector): # abstract base class """ An element of a generic free module. """ @@ -962,6 +948,71 @@ cdef class FreeModuleElement(element_Vector): # abstract base class v = ','.join([a._magma_init_(magma) for a in self.list()]) return '%s![%s]' % (R.name(), v) + def numpy(self, dtype=object): + """ + Converts self to a numpy array. + + INPUT: + + - ``dtype`` -- the `numpy dtype `_ + of the returned array + + EXAMPLES:: + + sage: v = vector([1,2,3]) + sage: v.numpy() + array([1, 2, 3], dtype=object) + sage: v.numpy() * v.numpy() + array([1, 4, 9], dtype=object) + + sage: vector(QQ, [1, 2, 5/6]).numpy() + array([1, 2, 5/6], dtype=object) + + By default the ``object`` `dtype `_ is used. + Alternatively, the desired dtype can be passed in as a parameter:: + + sage: v = vector(QQ, [1, 2, 5/6]) + sage: v.numpy() + array([1, 2, 5/6], dtype=object) + sage: v.numpy(dtype=float) + array([ 1. , 2. , 0.83333333]) + sage: v.numpy(dtype=int) + array([1, 2, 0]) + sage: import numpy + sage: v.numpy(dtype=numpy.uint8) + array([1, 2, 0], dtype=uint8) + + Passing a dtype of None will let numpy choose a native type, which can + be more efficient but may have unintended consequences:: + + sage: v.numpy(dtype=None) + array([ 1. , 2. , 0.83333333]) + + sage: w = vector(ZZ, [0, 1, 2^63 -1]); w + (0, 1, 9223372036854775807) + sage: wn = w.numpy(dtype=None); wn + array([ 0, 1, 9223372036854775807]...) + sage: wn.dtype + dtype('int64') + sage: w.dot_product(w) + 85070591730234615847396907784232501250 + sage: wn.dot(wn) # overflow + 2 + + Numpy can give rather obscure errors; we wrap these to give a bit of context:: + + sage: vector([1, 1/2, QQ['x'].0]).numpy(dtype=float) + Traceback (most recent call last): + ... + ValueError: Could not convert vector over Univariate Polynomial Ring in x over Rational Field to numpy array of type : setting an array element with a sequence. + """ + from numpy import array + try: + return array(self, dtype=dtype) + except ValueError as e: + raise ValueError( + "Could not convert vector over %s to numpy array of type %s: %s" % (self.base_ring(), dtype, e)) + def __hash__(self): """ Return hash of this vector. Only mutable vectors are hashable. @@ -1456,13 +1507,15 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: 10*v (0, 0) """ - v = [None]*self.degree() - cdef int i - for i from 0 <= i < self.degree(): - v[i] = self[i].additive_order() - if v[i] == +Infinity: - return +Infinity - return sage.rings.arith.LCM(v) + cdef list v = [] + cdef Py_ssize_t i + for i in range(self._degree): + ord = self[i].additive_order() + if isinstance(ord, AnInfinity): + return ord + v.append(ord) + from sage.rings.arith import lcm + return lcm(v) def iteritems(self): """ @@ -1492,7 +1545,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class """ return sum([x**2 for x in self.list()]).sqrt() - def norm(self, p=sage.rings.integer.Integer(2)): + def norm(self, p=__two__): r""" Return the `p`-norm of ``self``. @@ -1570,9 +1623,9 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: v.norm(0.99) Traceback (most recent call last): ... - ValueError: 0.990000 is not greater than or equal to 1 + ValueError: 0.990000000000000 is not greater than or equal to 1 - Norm works with python integers (see :trac:`13502`). :: + Norm works with Python integers (see :trac:`13502`). :: sage: v = vector(QQ, [1,2]) sage: v.norm(int(2)) @@ -1581,12 +1634,8 @@ cdef class FreeModuleElement(element_Vector): # abstract base class abs_self = [abs(x) for x in self] if p == Infinity: return max(abs_self) - try: - pr = RDF(p) - if pr < 1: - raise ValueError("%f is not greater than or equal to 1" %(pr)) - except TypeError: - pass + if p < 1: + raise ValueError("%s is not greater than or equal to 1" % p) s = sum([a**p for a in abs_self]) return s**(__one__/p) @@ -1610,7 +1659,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class """ cdef Py_ssize_t i cdef int c - for i from 0 <= i < left.degree(): + for i in range(left._degree): c = cmp(left[i], right[i]) if c: return c return 0 @@ -1668,7 +1717,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: len(sage.modules.free_module_element.FreeModuleElement(QQ^2010)) 2010 """ - return self.parent().degree() + return self._degree def __mod__(self, p): """ @@ -1722,7 +1771,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class (x, y, z) """ cdef Py_ssize_t i - return [self[i] for i in range(self.degree())] + return [self[i] for i in range(self._degree)] def list_from_positions(self, positions): """ @@ -1806,7 +1855,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: v._repr_() '(theta^3 + sqrt(2) + 1/2, 1/2)' """ - d = self.degree() + cdef Py_ssize_t d = self._degree if d == 0: return "()" # compute column widths S = [repr(x) for x in self.list(copy=False)] @@ -1869,33 +1918,6 @@ cdef class FreeModuleElement(element_Vector): # abstract base class """ raise NotImplementedError - def __richcmp__(left, right, int op): - """ - EXAMPLES:: - - sage: v = vector([1,2/3,8]) # indirect test - sage: v == v - True - """ - cdef int ld, rd - if not isinstance(left, FreeModuleElement) or not isinstance(right, FreeModuleElement): - # use the generic compare - return (left)._richcmp(right, op) - ld = (left)._degree - rd = (right)._degree - if ld < rd: - return (left)._rich_to_bool(op, -1) - elif ld > rd: - return (left)._rich_to_bool(op, 1) - if (left)._parent.base_ring() is (right)._parent.base_ring(): - return (left)._rich_to_bool(op, ( - left)._cmp_same_ambient_c(right)) - return (left)._richcmp(right, op) - - - cdef int _cmp_same_ambient_c(left, FreeModuleElement right) except -2: - return cmp(left.list(copy=False), right.list(copy=False)) - def degree(self): """ Return the degree of this vector, which is simply the number @@ -1969,8 +1991,9 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: v (18, 0, 3/7) """ - e = {} - for i in xrange(self.degree()): + cdef dict e = {} + cdef Py_ssize_t i + for i in range(self._degree): c = self[i] if c: e[i] = c @@ -2158,6 +2181,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: v.plot_step(eps=eps, xmax=5, hue=0) Graphics object consisting of 1 graphics primitive """ + import math if res is None: res = self.degree() if eps is None: @@ -2177,14 +2201,50 @@ cdef class FreeModuleElement(element_Vector): # abstract base class else: return points(v, **kwds) + cpdef Element _dot_product_coerce_(left, Vector right): + """ + Return the dot product of left and right. + + This function works even if the parents are different, the + degrees have to match however. + + EXAMPLES:: + + sage: R. = ZZ[] + sage: v = vector(RDF, [0,1,2]) + sage: w = vector(R, [x,0,0]) + sage: p = v._dot_product_coerce_(w) + sage: p + 0 + sage: parent(p) + Univariate Polynomial Ring in x over Real Double Field + + Zero-dimensional vectors also work correctly:: + + sage: v = vector(RDF, []) + sage: w = vector(R, []) + sage: parent(v._dot_product_coerce_(w)) + Univariate Polynomial Ring in x over Real Double Field + """ + if left._degree == 0: + return (left.base_ring().zero() + * right.base_ring().zero()) + cdef list a = left.list(copy=False) + cdef list b = right.list(copy=False) + cdef Py_ssize_t i + z = a[0] * b[0] + for i in range(1, left._degree): + z += a[i] * b[i] + return z + def dot_product(self, right): r""" - Return the dot product of ``self`` and ``right``, which is the sum of the - product of the corresponding entries. + Return the dot product of ``self`` and ``right``, which is the + sum of the product of the corresponding entries. INPUT: - - ``right`` - a vector of the same degree as ``self``. + - ``right`` -- a vector of the same degree as ``self``. It does not need to belong to the same parent as ``self``, so long as the necessary products and sums are defined. @@ -2212,6 +2272,17 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: v.dot_product(w) 32 + :: + + sage: R. = QQ[] + sage: v = vector([x,x^2,3*x]); w = vector([2*x,x,3+x]) + sage: v*w + x^3 + 5*x^2 + 9*x + sage: (x*2*x) + (x^2*x) + (3*x*(3+x)) + x^3 + 5*x^2 + 9*x + sage: w*v + x^3 + 5*x^2 + 9*x + The vectors may be from different vector spaces, provided the necessary operations make sense. Notice that coercion will generate a result of @@ -2244,7 +2315,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: v.dot_product('junk') Traceback (most recent call last): ... - TypeError: right must be a free module element + TypeError: Cannot convert str to sage.modules.free_module_element.FreeModuleElement The degrees of the arguments must match. :: @@ -2261,19 +2332,14 @@ cdef class FreeModuleElement(element_Vector): # abstract base class 8.0 """ - if not PY_TYPE_CHECK(right, FreeModuleElement): - raise TypeError("right must be a free module element") - r = right.list(copy=False) - l = self.list(copy=False) - if len(r) != len(l): - raise ArithmeticError("degrees (%s and %s) must be the same"%(len(l),len(r))) - if len(r) == 0: - return self._parent.base_ring()(0) - sum = l[0] * r[0] - cdef Py_ssize_t i - for i from 1 <= i < len(l): - sum += l[i] * r[i] - return sum + cdef FreeModuleElement r = right + if self._parent is r._parent: + # If the parents are equal, the degree is also equal + return self._dot_product_(r) + if self._degree != r._degree: + raise ArithmeticError("degrees (%s and %s) must be the same"%(self.degree(), right.degree())) + # Base rings are not equal => use dot product with coercion + return self._dot_product_coerce_(r) def cross_product(self, right): """ @@ -2367,7 +2433,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class Billy Wonderly (2010-05-11), Added 7-D Cross Product """ - if not PY_TYPE_CHECK(right, FreeModuleElement): + if not isinstance(right, FreeModuleElement): raise TypeError("right must be a free module element") r = right.list(copy=False) l = self.list(copy=False) @@ -2388,8 +2454,6 @@ cdef class FreeModuleElement(element_Vector): # abstract base class else: raise ArithmeticError("Cross product only defined for vectors of length three or seven, not (%s and %s)"%(len(l),len(r))) - - def pairwise_product(self, right): """ Return the pairwise product of self and right, which is a vector of @@ -2498,12 +2562,134 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: w.pairwise_product(v) == v.pairwise_product(w) True """ - if not PY_TYPE_CHECK(right, FreeModuleElement): + if not isinstance(right, FreeModuleElement): raise TypeError("right must be a free module element") if self._parent is not (right)._parent: self, right = canonical_coercion(self, right) return self._pairwise_product_(right) + def _variables(self): + """ + Return the ordered variable of self, as defined by the basering. + + EXAMPLES:: + + sage: R. = QQ[] + sage: vector([x, y, 3])._variables() + [x, y, z] + sage: vector(SR, [x, y, 3])._variables() + Traceback (most recent call last): + ... + ValueError: Unable to determine ordered variable names for Symbolic Ring + sage: v(x, y, z) = (-y, x, 0) + sage: v._variables() + [(x, y, z) |--> x, (x, y, z) |--> y, (x, y, z) |--> z] + """ + R = self._parent.base_ring() + try: + var_names = R.variable_names() + except ValueError: + if hasattr(R, 'arguments'): + var_names = R.arguments() + else: + raise ValueError("Unable to determine ordered variable names for %s" % R) + return [R(x) for x in var_names] + + def div(self, variables=None): + """ + Return the divergence of this vector function. + + EXAMPLES:: + + sage: R. = QQ[] + sage: vector([x, y, z]).div() + 3 + sage: vector([x*y, y*z, z*x]).div() + x + y + z + + sage: R. = QQ[] + sage: vector([x*y, y*z, z*x]).div([x, y, z]) + x + y + z + sage: vector([x*y, y*z, z*x]).div([z, x, y]) + 0 + sage: vector([x*y, y*z, z*x]).div([x, y, w]) + y + z + + sage: vector(SR, [x*y, y*z, z*x]).div() + Traceback (most recent call last): + ... + ValueError: Unable to determine ordered variable names for Symbolic Ring + sage: vector(SR, [x*y, y*z, z*x]).div([x, y, z]) + x + y + z + """ + if variables is None: + variables = self._variables() + if len(variables) != len(self): + raise ValueError("number of variables must equal dimension of self") + return sum(c.derivative(x) for (c, x) in zip(self, variables)) + + def curl(self, variables=None): + """ + Return the curl of this two-dimensional or three-dimensional + vector function. + + EXAMPLES:: + + sage: R. = QQ[] + sage: vector([-y, x, 0]).curl() + (0, 0, 2) + sage: vector([y, -x, x*y*z]).curl() + (x*z, -y*z, -2) + sage: vector([y^2, 0, 0]).curl() + (0, 0, -2*y) + sage: (R^3).random_element().curl().div() + 0 + + For rings where the variable order is not well defined, it must be + defined explicitly:: + + sage: v = vector(SR, [-y, x, 0]) + sage: v.curl() + Traceback (most recent call last): + ... + ValueError: Unable to determine ordered variable names for Symbolic Ring + sage: v.curl([x, y, z]) + (0, 0, 2) + + Note that callable vectors have well defined variable orderings:: + + sage: v(x, y, z) = (-y, x, 0) + sage: v.curl() + (x, y, z) |--> (0, 0, 2) + + In two-dimensions, this returns a scalar value:: + + sage: R. = QQ[] + sage: vector([-y, x]).curl() + 2 + """ + if len(self) == 3: + if variables is None: + variables = self._variables() + if len(variables) != 3: + raise ValueError("exactly 3 variables must be provided") + x, y, z = variables + Fx, Fy, Fz = self + return self.parent([Fz.derivative(y) - Fy.derivative(z), + Fx.derivative(z) - Fz.derivative(x), + Fy.derivative(x) - Fx.derivative(y)]) + + if len(self) == 2: + if variables is None: + variables = self._variables() + if len(variables) != 2: + raise ValueError("exactly 2 variables must be provided") + x, y = variables + Fx, Fy = self + return Fy.derivative(x) - Fx.derivative(y) + + raise TypeError("curl only defined for 2 or 3 dimensions") + def element(self): """ Simply returns self. This is useful, since for many objects, @@ -2561,14 +2747,17 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: v = vector(QQ, [0, 4/3, 5, 1, 2]) sage: v.monic() (0, 1, 15/4, 3/4, 3/2) + sage: v = vector(QQ, []) + sage: v.monic() + () """ cdef Py_ssize_t i - for i from 0 <= i < self._degree: - if self[i] != 0: + for i in range(self._degree): + if self[i]: return (~self[i]) * self return self - def normalized(self, p=sage.rings.integer.Integer(2)): + def normalized(self, p=__two__): """ Return the input vector divided by the p-norm. @@ -2671,7 +2860,6 @@ cdef class FreeModuleElement(element_Vector): # abstract base class """ V = self.parent() R = self.base_ring() - degree = self.degree() if self.is_sparse(): # this could be a dictionary comprehension in Python 3 entries = {} @@ -2679,7 +2867,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class entries[index] = entry.conjugate() else: entries = [entry.conjugate() for entry in self] - return V(vector(R, degree, entries)) + return V(vector(R, self._degree, entries)) def inner_product(self, right): r""" @@ -2895,7 +3083,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class ... TypeError: right operand in an outer product must be a vector, not an element of Integer Ring """ - if not PY_TYPE_CHECK(right, FreeModuleElement): + if not isinstance(right, FreeModuleElement): raise TypeError('right operand in an outer product must be a vector, not an element of %s' % right.parent()) return self.column()*right.row() @@ -3059,15 +3247,6 @@ cdef class FreeModuleElement(element_Vector): # abstract base class """ return '{' + ', '.join([x._mathematica_init_() for x in self.list()]) + '}' -## def zero_out_positions(self, P): -## """ -## Set the positions of self in the list P equal to 0. -## """ -## z = self.base_ring()(0) -## d = self.degree() -## for n in P: -## self[n] = z - def nonzero_positions(self): """ Return the sorted list of integers ``i`` such that ``self[i] != 0``. @@ -3080,7 +3259,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class z = self.base_ring()(0) v = self.list() cdef Py_ssize_t i - return [i for i from 0 <= i < self.degree() if v[i] != z] + return [i for i in range(self._degree) if v[i] != z] def support(self): # do not override. """ @@ -3103,7 +3282,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class sage: vector([-1,0,3,0,0,0,0.01]).hamming_weight() 3 """ - cdef int res=0 + cdef Py_ssize_t res = 0 for x in iter(self.list()): if not x.is_zero(): res += 1 @@ -3367,23 +3546,14 @@ cdef class FreeModuleElement(element_Vector): # abstract base class (r, theta) |--> r*cos(theta)^2 + r*sin(theta)^2 """ if var is None: - if sage.symbolic.callable.is_CallableSymbolicExpressionRing(self.base_ring()): - return sage.calculus.all.jacobian(self, self.base_ring().arguments()) + from sage.symbolic.callable import is_CallableSymbolicExpressionRing + from sage.calculus.all import jacobian + if is_CallableSymbolicExpressionRing(self.base_ring()): + return jacobian(self, self.base_ring().arguments()) else: raise ValueError("No differentiation variable specified.") - # We would just use apply_map, except that Cython doesn't - # allow lambda functions - if self._degree == 0: - from copy import copy - return copy(self) - - if self.is_sparse(): - v = dict([(i,z.derivative(var)) for i,z in self.dict().items()]) - else: - v = [z.derivative(var) for z in self.list()] - - return self.parent().ambient_module()(v) + return self.apply_map(lambda x: x.derivative(var)) def derivative(self, *args): """ @@ -3433,16 +3603,7 @@ cdef class FreeModuleElement(element_Vector): # abstract base class """ from sage.misc.functional import integral - - # If Cython supported lambda functions, we would just do - # return self.apply_map(lambda x: integral(x,*args, **kwds) for x in self) - - if self.is_sparse(): - v = dict([(i,integral(z,*args,**kwds)) for i,z in self.dict(copy=False).items()]) - else: - v = [integral(z,*args,**kwds) for z in self.list()] - - return vector(v,sparse=self.is_sparse()) + return self.apply_map(lambda x: integral(x,*args, **kwds)) integrate=integral @@ -3538,23 +3699,31 @@ def make_FreeModuleElement_generic_dense_v1(parent, entries, degree, is_mutable) cdef class FreeModuleElement_generic_dense(FreeModuleElement): """ A generic dense element of a free module. + + TESTS:: + + sage: V = ZZ^3 + sage: loads(dumps(V)) == V + True + sage: v = V.0 + sage: loads(dumps(v)) == v + True + sage: v = (QQ['x']^3).0 + sage: loads(dumps(v)) == v + True """ - ## these work fine on the command line but fail in doctests :-( -## TESTS: -## sage: V = ZZ^3 -## sage: loads(dumps(V)) == V -## True -## sage: v = V.0 -## sage: loads(dumps(v)) == v -## True -## sage: v = (QQ['x']^3).0 -## sage: loads(dumps(v)) == v -## True cdef _new_c(self, object v): - # Create a new dense free module element with minimal overhead and - # no type checking. - cdef FreeModuleElement_generic_dense x - x = PY_NEW(PY_TYPE(self)) + """ + Create a new dense free module element with minimal overhead and + no type checking. + + INPUT: + + - ``v`` -- a list which is used as the new entries (without + copying) + """ + cdef type t = type(self) + cdef FreeModuleElement_generic_dense x = t.__new__(t) x._is_mutable = 1 x._parent = self._parent x._entries = v @@ -3663,7 +3832,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): FreeModuleElement.__init__(self, parent) R = self.base_ring() if not entries: - entries = [R.zero_element()]*self._degree + entries = [R.zero()]*self._degree else: if type(entries) is not list: if not isinstance(entries, (list, tuple)): @@ -3682,6 +3851,8 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): entries = list(entries) # make a copy/convert to list self._entries = entries + @cython.boundscheck(False) + @cython.wraparound(False) cpdef ModuleElement _add_(left, ModuleElement right): """ Add left and right. @@ -3692,14 +3863,13 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: v._add_(w) (1/3, pi^2 + 2/3, pi + 1) """ - cdef Py_ssize_t i, n - n = len(left._entries) - v = [None]*n - for i from 0 <= i < n: - v[i] = (left._entries[i])._add_( - ((right)._entries[i])) + cdef list a = left._entries + cdef list b = (right)._entries + v = [( a[i])._add_( b[i]) for i in range(left._degree)] return left._new_c(v) + @cython.boundscheck(False) + @cython.wraparound(False) cpdef ModuleElement _sub_(left, ModuleElement right): """ Subtract right from left. @@ -3713,12 +3883,9 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: V.0 - W.0 (1, -1, 0, 0, 0) """ - cdef Py_ssize_t i, n - n = len(left._entries) - v = [None]*n - for i from 0 <= i < n: - v[i] = (left._entries[i])._sub_( - ((right)._entries[i])) + cdef list a = left._entries + cdef list b = (right)._entries + v = [( a[i])._sub_( b[i]) for i in range(left._degree)] return left._new_c(v) cpdef ModuleElement _rmul_(self, RingElement left): @@ -3751,24 +3918,9 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): v = [x * right for x in self._entries] return self._new_c(v) - cpdef Element _dot_product_(left, element_Vector right): - """ - Return the dot product of left and right. - - EXAMPLES:: - - sage: R. = QQ[] - sage: v = vector([x,x^2,3*x]); w = vector([2*x,x,3+x]) - sage: v*w - x^3 + 5*x^2 + 9*x - sage: (x*2*x) + (x^2*x) + (3*x*(3+x)) - x^3 + 5*x^2 + 9*x - sage: w*v - x^3 + 5*x^2 + 9*x - """ - return left.dot_product(right) - - cpdef element_Vector _pairwise_product_(left, element_Vector right): + @cython.boundscheck(False) + @cython.wraparound(False) + cpdef Vector _pairwise_product_(left, Vector right): """ EXAMPLES:: @@ -3779,16 +3931,36 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: w.pairwise_product(v) (2*x^2, x^3, 3*x^2 + 9*x) """ - if not right.parent() == left.parent(): + if not right._parent is left._parent: right = left.parent().ambient_module()(right) - # Component wise vector * vector multiplication. - cdef Py_ssize_t i, n - n = len(left._entries) - v = [None]*n - for i from 0 <= i < n: - v[i] = (left._entries[i])._mul_((right)._entries[i]) + cdef list a = left._entries + cdef list b = (right)._entries + v = [( a[i])._mul_( b[i]) for i in range(left._degree)] return left._new_c(v) + # see sage/structure/element.pyx + def __richcmp__(left, right, int op): + """ + TESTS:: + + sage: v = vector([1,2/3,pi]) + sage: v == v + True + """ + return (left)._richcmp(right, op) + + # __hash__ is not properly inherited if comparison is changed + def __hash__(self): + """ + TESTS:: + + sage: v = vector(RR, [1,2/3,pi]) + sage: v.set_immutable() + sage: isinstance(hash(v), int) + True + """ + return FreeModuleElement.__hash__(self) + def __reduce__(self): """ EXAMPLES:: @@ -3966,18 +4138,6 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): ############################################# # Generic sparse element ############################################# -def _sparse_dot_product(v, w): - """ - v and w are dictionaries with integer keys. - - EXAMPLES:: - - sage: sage.modules.free_module_element._sparse_dot_product({0:5,1:7,2:3}, {0:-1, 2:2}) - 1 - """ - x = set(v.keys()).intersection(set(w.keys())) - return sum([v[k]*w[k] for k in x]) - def make_FreeModuleElement_generic_sparse(parent, entries, degree): """ EXAMPLES:: @@ -4036,10 +4196,17 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): {2: -1} """ cdef _new_c(self, object v): - # Create a new sparse free module element with minimal overhead and - # no type checking. - cdef FreeModuleElement_generic_sparse x - x = PY_NEW(FreeModuleElement_generic_sparse) + """ + Create a new sparse free module element with minimal overhead and + no type checking. + + INPUT: + + - ``v`` -- a dict which is used as the new entries (without + copying) + """ + cdef type t = type(self) + cdef FreeModuleElement_generic_sparse x = t.__new__(t) x._is_mutable = 1 x._parent = self._parent x._entries = v @@ -4248,7 +4415,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): v[i] = prod return self._new_c(v) - cpdef Element _dot_product_(left, element_Vector right): + cpdef Element _dot_product_coerce_(left, Vector right): """ Return the dot product of left and right. @@ -4259,15 +4426,35 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): 10 sage: w * v 10 + + Over different rings:: + + sage: R. = ZZ[] + sage: v = vector(RDF, [0,1,2], sparse=True) + sage: w = vector(R, [x,0,0], sparse=True) + sage: p = v._dot_product_coerce_(w) + sage: p + 0 + sage: parent(p) + Univariate Polynomial Ring in x over Real Double Field + + Zero-dimensional vectors also work correctly:: + + sage: v = vector(RDF, [], sparse=True) + sage: w = vector(R, [], sparse=True) + sage: parent(v._dot_product_coerce_(w)) + Univariate Polynomial Ring in x over Real Double Field """ cdef dict e = (right)._entries - z = left.base_ring()(0) + z = left.base_ring().zero() + if left.base_ring() is not right.base_ring(): + z *= right.base_ring().zero() for i, a in left._entries.iteritems(): if i in e: - z += (a)._mul_( e[i]) + z += a * e[i] return z - cpdef element_Vector _pairwise_product_(left, element_Vector right): + cpdef Vector _pairwise_product_(left, Vector right): """ EXAMPLES:: @@ -4343,6 +4530,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): """ return FreeModuleElement.__hash__(self) + def iteritems(self): """ Return iterator over the entries of self. @@ -4550,10 +4738,8 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): sage: a = v.list(); a [1, 2/3, pi] """ - cdef Py_ssize_t n - n = self._parent.degree() z = self._parent.base_ring()(0) - v = [z]*n + v = [z] * self._degree for i, a in self._entries.iteritems(): v[i] = a return v diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index a056da9a530..fca1f1b3b2a 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -716,6 +716,39 @@ def matrix(self): """ raise NotImplementedError("this method must be overridden in the extension class") + def _matrix_(self): + """ + EXAMPLES: + + Check that this works with the :func:`matrix` function + (:trac:`16844`):: + + sage: H = Hom(ZZ^2, ZZ^3) + sage: x = H.an_element() + sage: matrix(x) + [0 0 0] + [0 0 0] + + TESTS: + + ``matrix(x)`` is immutable:: + + sage: H = Hom(QQ^3, QQ^2) + sage: phi = H(matrix(QQ, 3, 2, list(reversed(range(6))))); phi + Vector space morphism represented by the matrix: + [5 4] + [3 2] + [1 0] + Domain: Vector space of dimension 3 over Rational Field + Codomain: Vector space of dimension 2 over Rational Field + sage: A = phi.matrix() + sage: A[1, 1] = 19 + Traceback (most recent call last): + ... + ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). + """ + return self.matrix() + def rank(self): r""" Returns the rank of the matrix representing this morphism. @@ -1167,11 +1200,15 @@ class MatrixMorphism(MatrixMorphism_abstract): INPUT: - - ``parent`` - a homspace + - ``parent`` -- a homspace + + - ``A`` -- matrix or a :class:`MatrixMorphism_abstract` instance - - ``A`` - matrix or a :class:`MatrixMorphism_abstract` instance + - ``copy_matrix`` -- (default: ``True``) make an immutable copy of + the matrix ``A`` if it is mutable; if ``False``, then this makes + ``A`` immutable """ - def __init__(self, parent, A): + def __init__(self, parent, A, copy_matrix=True): """ Initialize ``self``. @@ -1194,6 +1231,11 @@ def __init__(self, parent, A): raise ArithmeticError("number of rows of matrix (={}) must equal rank of domain (={})".format(A.nrows(), parent.domain().rank())) if A.ncols() != parent.codomain().rank(): raise ArithmeticError("number of columns of matrix (={}) must equal rank of codomain (={})".format(A.ncols(), parent.codomain().rank())) + if A.is_mutable(): + if copy_matrix: + from copy import copy + A = copy(A) + A.set_immutable() self._matrix = A MatrixMorphism_abstract.__init__(self, parent) @@ -1203,8 +1245,8 @@ def matrix(self, side='left'): INPUT: - - ``side`` - default:``'left'`` - the side of the matrix - where a vector is placed to effect the morphism (function). + - ``side`` -- (default: ``'left'``) the side of the matrix + where a vector is placed to effect the morphism (function) OUTPUT: diff --git a/src/sage/modules/vector_double_dense.pyx b/src/sage/modules/vector_double_dense.pyx index 9efe536b57b..cdd129e610f 100644 --- a/src/sage/modules/vector_double_dense.pyx +++ b/src/sage/modules/vector_double_dense.pyx @@ -388,13 +388,13 @@ cdef class Vector_double_dense(free_module_element.FreeModuleElement): 1.0 sage: w*v 1.0 - """ - if not right.parent() == self.parent(): - right = self.parent().ambient_module()(right) - if self._degree == 0: - from copy import copy - return copy(self) + This works correctly for zero-dimensional vectors:: + + sage: v = vector(RDF, []) + sage: v._dot_product_(v) + 0.0 + """ cdef Vector_double_dense _right, _left _right = right _left = self @@ -546,10 +546,15 @@ cdef class Vector_double_dense(free_module_element.FreeModuleElement): return Vector_complex_double_dense(V, scipy.ifft(self._vector_numpy)) - def numpy(self): + def numpy(self, dtype=None): """ Return numpy array corresponding to this vector. + INPUT: + + - ``dtype`` -- if specified, the `numpy dtype `_ + of the returned array. + EXAMPLES:: sage: v = vector(CDF,4,range(4)) @@ -564,9 +569,23 @@ cdef class Vector_double_dense(free_module_element.FreeModuleElement): sage: v = vector(RDF,0) sage: v.numpy() array([], dtype=float64) + + A numpy dtype may be requested manually:: + + sage: import numpy + sage: v = vector(CDF, 3, range(3)) + sage: v.numpy() + array([ 0.+0.j, 1.+0.j, 2.+0.j]) + sage: v.numpy(dtype=numpy.float64) + array([ 0., 1., 2.]) + sage: v.numpy(dtype=numpy.float32) + array([ 0., 1., 2.], dtype=float32) """ - from copy import copy - return copy(self._vector_numpy) + if dtype is None or dtype is self._vector_numpy.dtype: + from copy import copy + return copy(self._vector_numpy) + else: + return super(Vector_double_dense, self).numpy(dtype) cdef _replace_self_with_numpy(self,cnumpy.ndarray numpy_array): """ diff --git a/src/sage/modules/vector_integer_dense.pxd b/src/sage/modules/vector_integer_dense.pxd index e373bf7856d..7bdebe25f09 100644 --- a/src/sage/modules/vector_integer_dense.pxd +++ b/src/sage/modules/vector_integer_dense.pxd @@ -1,9 +1,7 @@ -cimport free_module_element -import free_module_element +from free_module_element cimport FreeModuleElement +from sage.libs.gmp.types cimport mpz_t -include 'sage/ext/cdefs.pxi' - -cdef class Vector_integer_dense(free_module_element.FreeModuleElement): +cdef class Vector_integer_dense(FreeModuleElement): cdef mpz_t* _entries cdef _new_c(self) cdef _init(self, Py_ssize_t degree, parent) diff --git a/src/sage/modules/vector_integer_dense.pyx b/src/sage/modules/vector_integer_dense.pyx index 86287cb363e..895084b4509 100644 --- a/src/sage/modules/vector_integer_dense.pyx +++ b/src/sage/modules/vector_integer_dense.pyx @@ -56,6 +56,9 @@ cimport free_module_element from free_module_element import vector +from sage.libs.gmp.mpz cimport * + + cdef inline _Integer_from_mpz(mpz_t e): cdef Integer z = PY_NEW(Integer) mpz_set(z.value, e) @@ -64,7 +67,7 @@ cdef inline _Integer_from_mpz(mpz_t e): cdef class Vector_integer_dense(free_module_element.FreeModuleElement): cdef _new_c(self): cdef Vector_integer_dense y - y = PY_NEW(Vector_integer_dense) + y = Vector_integer_dense.__new__(Vector_integer_dense) y._init(self._degree, self._parent) return y @@ -168,9 +171,6 @@ cdef class Vector_integer_dense(free_module_element.FreeModuleElement): """ return free_module_element.FreeModuleElement.__hash__(self) - def __len__(self): - return self._degree - def __setitem__(self, i, value): """ EXAMPLES:: @@ -393,7 +393,7 @@ def unpickle_v0(parent, entries, degree): # make_FreeModuleElement_generic_dense_v1 # and changed the reduce method below. cdef Vector_integer_dense v - v = PY_NEW(Vector_integer_dense) + v = Vector_integer_dense.__new__(Vector_integer_dense) v._init(degree, parent) cdef Integer z for i from 0 <= i < degree: @@ -403,7 +403,7 @@ def unpickle_v0(parent, entries, degree): def unpickle_v1(parent, entries, degree, is_mutable): cdef Vector_integer_dense v - v = PY_NEW(Vector_integer_dense) + v = Vector_integer_dense.__new__(Vector_integer_dense) v._init(degree, parent) cdef Integer z for i from 0 <= i < degree: diff --git a/src/sage/modules/vector_mod2_dense.pxd b/src/sage/modules/vector_mod2_dense.pxd index 398a1b6d3cb..69491e2d36a 100644 --- a/src/sage/modules/vector_mod2_dense.pxd +++ b/src/sage/modules/vector_mod2_dense.pxd @@ -1,10 +1,9 @@ -cimport free_module_element -import free_module_element +from free_module_element cimport FreeModuleElement from sage.libs.m4ri cimport mzd_t -cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): - cdef mzd_t *_entries +cdef class Vector_mod2_dense(FreeModuleElement): + cdef mzd_t* _entries cdef object _base_ring cdef _new_c(self) diff --git a/src/sage/modules/vector_mod2_dense.pyx b/src/sage/modules/vector_mod2_dense.pyx index a03e474b898..9c82785c2f4 100644 --- a/src/sage/modules/vector_mod2_dense.pyx +++ b/src/sage/modules/vector_mod2_dense.pyx @@ -49,7 +49,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): """ cdef Vector_mod2_dense y - y = PY_NEW(Vector_mod2_dense) + y = Vector_mod2_dense.__new__(Vector_mod2_dense) y._init(self._degree, self._parent) return y @@ -229,15 +229,6 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): """ return free_module_element.FreeModuleElement.__hash__(self) - def __len__(self): - """ - EXAMPLES:: - - sage: len(vector(GF(2),[0,0,1,1,1])) - 5 - """ - return self._degree - def __setitem__(self, i, value): """ EXAMPLES:: @@ -523,8 +514,8 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): cdef Py_ssize_t i cdef list v = [0]*d K = self.base_ring() - z = K.zero_element() - o = K.one_element() + z = K.zero() + o = K.one() cdef list switch = [z,o] for i in range(d): v[i] = switch[mzd_read_bit(self._entries, 0, i)] @@ -541,7 +532,7 @@ def unpickle_v0(parent, entries, degree, is_mutable): """ # If you think you want to change this function, don't. cdef Vector_mod2_dense v - v = PY_NEW(Vector_mod2_dense) + v = Vector_mod2_dense.__new__(Vector_mod2_dense) v._init(degree, parent) cdef int xi diff --git a/src/sage/modules/vector_modn_dense.pxd b/src/sage/modules/vector_modn_dense.pxd index a28caa71723..b8372dce642 100644 --- a/src/sage/modules/vector_modn_dense.pxd +++ b/src/sage/modules/vector_modn_dense.pxd @@ -1,9 +1,7 @@ +from free_module_element cimport FreeModuleElement from sage.ext.mod_int cimport * -cimport free_module_element -import free_module_element - -cdef class Vector_modn_dense(free_module_element.FreeModuleElement): +cdef class Vector_modn_dense(FreeModuleElement): cdef mod_int* _entries cdef mod_int _p cdef object _base_ring diff --git a/src/sage/modules/vector_modn_dense.pyx b/src/sage/modules/vector_modn_dense.pyx index cb79473f969..8296667a26a 100644 --- a/src/sage/modules/vector_modn_dense.pyx +++ b/src/sage/modules/vector_modn_dense.pyx @@ -93,9 +93,9 @@ from sage.rings.finite_rings.integer_mod cimport ( IntegerMod_abstract, use_32bit_type) cdef mod_int ivalue(IntegerMod_abstract x) except -1: - if PY_TYPE_CHECK_EXACT(x, IntegerMod_int): + if type(x) is IntegerMod_int: return (x).ivalue - elif PY_TYPE_CHECK_EXACT(x, IntegerMod_int64): + elif type(x) is IntegerMod_int64: return (x).ivalue else: raise TypeError, "non-fixed size integer" @@ -108,7 +108,7 @@ from free_module_element import vector cdef class Vector_modn_dense(free_module_element.FreeModuleElement): cdef _new_c(self): cdef Vector_modn_dense y - y = PY_NEW(Vector_modn_dense) + y = Vector_modn_dense.__new__(Vector_modn_dense) y._init(self._degree, self._parent, self._p) return y @@ -216,9 +216,6 @@ cdef class Vector_modn_dense(free_module_element.FreeModuleElement): """ return free_module_element.FreeModuleElement.__hash__(self) - def __len__(self): - return self._degree - def __setitem__(self, i, value): if not self._is_mutable: raise ValueError("vector is immutable; please change a copy instead (use copy())") @@ -370,7 +367,7 @@ def unpickle_v0(parent, entries, degree, p): # make_FreeModuleElement_generic_dense_v1 # and changed the reduce method below. cdef Vector_modn_dense v - v = PY_NEW(Vector_modn_dense) + v = Vector_modn_dense.__new__(Vector_modn_dense) v._init(degree, parent, p) for i from 0 <= i < degree: v._entries[i] = entries[i] @@ -378,7 +375,7 @@ def unpickle_v0(parent, entries, degree, p): def unpickle_v1(parent, entries, degree, p, is_mutable): cdef Vector_modn_dense v - v = PY_NEW(Vector_modn_dense) + v = Vector_modn_dense.__new__(Vector_modn_dense) v._init(degree, parent, p) for i from 0 <= i < degree: v._entries[i] = entries[i] diff --git a/src/sage/modules/vector_rational_dense.pxd b/src/sage/modules/vector_rational_dense.pxd index a79482e7a69..c7320a8c4cb 100644 --- a/src/sage/modules/vector_rational_dense.pxd +++ b/src/sage/modules/vector_rational_dense.pxd @@ -1,9 +1,7 @@ -cimport free_module_element -import free_module_element +from free_module_element cimport FreeModuleElement +from sage.libs.gmp.types cimport mpq_t -include 'sage/ext/cdefs.pxi' - -cdef class Vector_rational_dense(free_module_element.FreeModuleElement): +cdef class Vector_rational_dense(FreeModuleElement): cdef mpq_t* _entries cdef _new_c(self) cdef _init(self, Py_ssize_t degree, parent) diff --git a/src/sage/modules/vector_rational_dense.pyx b/src/sage/modules/vector_rational_dense.pyx index 60f2696a56a..7bcbc70796b 100644 --- a/src/sage/modules/vector_rational_dense.pyx +++ b/src/sage/modules/vector_rational_dense.pyx @@ -57,8 +57,11 @@ from sage.rings.rational cimport Rational cimport free_module_element from free_module_element import vector +from sage.libs.gmp.mpq cimport * + + cdef inline _Rational_from_mpq(mpq_t e): - cdef Rational z = PY_NEW(Rational) + cdef Rational z = Rational.__new__(Rational) mpq_set(z.value, e) return z @@ -70,7 +73,7 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): cdef _new_c(self): cdef Vector_rational_dense y - y = PY_NEW(Vector_rational_dense) + y = Vector_rational_dense.__new__(Vector_rational_dense) y._init(self._degree, self._parent) return y @@ -173,9 +176,6 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): """ return free_module_element.FreeModuleElement.__hash__(self) - def __len__(self): - return self._degree - def __setitem__(self, i, value): if not self._is_mutable: raise ValueError("vector is immutable; please change a copy instead (use copy())") @@ -222,7 +222,7 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): ... IndexError: index out of range """ - cdef Rational z = PY_NEW(Rational) + cdef Rational z = Rational.__new__(Rational) if isinstance(i, slice): start, stop, step = i.indices(len(self)) return vector(self.base_ring(), self.list()[start:stop]) @@ -294,7 +294,7 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): """ cdef Vector_rational_dense r = right cdef Rational z - z = PY_NEW(Rational) + z = Rational.__new__(Rational) cdef mpq_t t mpq_init(t) mpq_set_si(z.value, 0, 1) @@ -329,7 +329,7 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): if PY_TYPE_CHECK(left, Rational): a = left elif PY_TYPE_CHECK(left, Integer): - a = PY_NEW(Rational) + a = Rational.__new__(Rational) mpq_set_z(a.value, (left).value) else: # should not happen @@ -348,7 +348,7 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): if PY_TYPE_CHECK(right, Rational): a = right elif PY_TYPE_CHECK(right, Integer): - a = PY_NEW(Rational) + a = Rational.__new__(Rational) mpq_set_z(a.value, (right).value) else: # should not happen @@ -376,7 +376,7 @@ def unpickle_v0(parent, entries, degree): # make_FreeModuleElement_generic_dense_v1 # and changed the reduce method below. cdef Vector_rational_dense v - v = PY_NEW(Vector_rational_dense) + v = Vector_rational_dense.__new__(Vector_rational_dense) v._init(degree, parent) cdef Rational z for i from 0 <= i < degree: @@ -387,7 +387,7 @@ def unpickle_v0(parent, entries, degree): def unpickle_v1(parent, entries, degree, is_mutable): cdef Vector_rational_dense v - v = PY_NEW(Vector_rational_dense) + v = Vector_rational_dense.__new__(Vector_rational_dense) v._init(degree, parent) cdef Rational z for i from 0 <= i < degree: diff --git a/src/sage/modules/vector_space_homspace.py b/src/sage/modules/vector_space_homspace.py index c054eca1459..94abe20b8fa 100644 --- a/src/sage/modules/vector_space_homspace.py +++ b/src/sage/modules/vector_space_homspace.py @@ -355,7 +355,7 @@ def __call__(self, A, check=True): sage: V = GF(3)^0 sage: W = GF(3)^1 sage: H = V.Hom(W) - sage: H.zero_element().is_zero() + sage: H.zero().is_zero() True Previously the above code resulted in a TypeError because the diff --git a/src/sage/monoids/free_monoid.py b/src/sage/monoids/free_monoid.py index 8257cba1f95..01c25d97ad0 100644 --- a/src/sage/monoids/free_monoid.py +++ b/src/sage/monoids/free_monoid.py @@ -307,19 +307,6 @@ def ngens(self): """ return self.__ngens - @cached_method - def one_element(self): - """ - Returns the identity element in this monoid. - - EXAMPLES:: - - sage: F = FreeMonoid(2005, 'a') - sage: F.one_element() - 1 - """ - return self(1) - def cardinality(self): r""" Return the cardinality of ``self``, which is `\infty`. diff --git a/src/sage/monoids/free_monoid_element.py b/src/sage/monoids/free_monoid_element.py index 7fecaf8f0d6..691f7101659 100644 --- a/src/sage/monoids/free_monoid_element.py +++ b/src/sage/monoids/free_monoid_element.py @@ -200,7 +200,7 @@ def __call__(self, *x, **kwds): # I don't start with 0, because I don't want to preclude evaluation with #arbitrary objects (e.g. matrices) because of funny coercion. - one = P.one_element() + one = P.one() result = None for var_index, exponent in self._element_list: # Take further pains to ensure that non-square matrices are not exponentiated. diff --git a/src/sage/monoids/indexed_free_monoid.py b/src/sage/monoids/indexed_free_monoid.py index 323a8fc3d66..7d3ec7b9e7e 100644 --- a/src/sage/monoids/indexed_free_monoid.py +++ b/src/sage/monoids/indexed_free_monoid.py @@ -734,7 +734,7 @@ def _first_ngens(self, n): [F[0], F[1], F[-1]] """ it = iter(self._indices) - return tuple(self.gen(it.next()) for i in range(n)) + return tuple(self.gen(next(it)) for i in range(n)) def _element_constructor_(self, x=None): """ @@ -781,7 +781,7 @@ def _an_element_(self): try: g = iter(self._indices) for c in range(1,4): - x *= self.gen(g.next()) ** c + x *= self.gen(next(g)) ** c except Exception: pass return x diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index a390eb483c1..79886cf0e3c 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -218,7 +218,7 @@ def __iter__(self): EXAMPLES:: sage: t = AlphabeticStrings()('SHRUBBERY') - sage: t.__iter__().next() + sage: next(t.__iter__()) S sage: list(t) [S, H, R, U, B, B, E, R, Y] diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index 04fb6c6eab2..ec13eea7026 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -2837,26 +2837,3 @@ cdef class MIPVariableParent(Parent): mip_variable_parent = MIPVariableParent() - -def Sum(x): - """ - Only for legacy support, use :meth:`MixedIntegerLinearProgram.sum` instead. - - EXAMPLES:: - - sage: from sage.numerical.mip import Sum - sage: Sum([]) - doctest:...: DeprecationWarning: use MixedIntegerLinearProgram.sum() instead - See http://trac.sagemath.org/13646 for details. - - sage: p = MixedIntegerLinearProgram() - sage: x = p.new_variable(nonnegative=True) - sage: Sum([ x[0]+x[1], x[1]+x[2], x[2]+x[3] ]) # deprecation is only shown once - x_0 + 2*x_1 + 2*x_2 + x_3 - """ - from sage.misc.superseded import deprecation - deprecation(13646, 'use MixedIntegerLinearProgram.sum() instead') - if not x: - return None - parent = x[0].parent() - return parent.sum(x) diff --git a/src/sage/plot/colors.py b/src/sage/plot/colors.py index 0093f8a1044..3324599079d 100644 --- a/src/sage/plot/colors.py +++ b/src/sage/plot/colors.py @@ -43,6 +43,7 @@ import math import collections from colorsys import hsv_to_rgb, hls_to_rgb, rgb_to_hsv, rgb_to_hls +from math import floor # matplotlib color maps, loaded on-demand cm = None @@ -1230,17 +1231,18 @@ def hue(h, s=1, v=1): def float_to_html(r, g, b): """ - Converts a Red-Green-Blue (RGB) color tuple to a HTML hex color. + Convert a Red-Green-Blue (RGB) color tuple to a HTML hex color. + Each input value should be in the interval [0.0, 1.0]; otherwise, the values are first reduced modulo one (see :func:`mod_one`). INPUT: - - ``r`` - a number; the RGB color's "red" intensity + - ``r`` -- a real number; the RGB color's "red" intensity - - ``g`` - a number; the RGB color's "green" intensity + - ``g`` -- a real number; the RGB color's "green" intensity - - ``b`` - a number; the RGB color's "blue" intensity + - ``b`` -- a real number; the RGB color's "blue" intensity OUTPUT: @@ -1262,7 +1264,6 @@ def float_to_html(r, g, b): """ # TODO: figure out why this is necessary from sage.rings.integer import Integer - from math import floor r, g, b = map(mod_one, (r, g, b)) rr = Integer(int(floor(r * 255))).str(base = 16) @@ -1276,6 +1277,46 @@ def float_to_html(r, g, b): return '#' + rr + gg + bb +def float_to_integer(r, g, b): + """ + Convert a Red-Green-Blue (RGB) color tuple to an integer. + + Each input value should be in the interval [0.0, 1.0]; otherwise, + the values are first reduced modulo one (see :func:`mod_one`). + + INPUT: + + - ``r`` -- a real number; the RGB color's "red" intensity + + - ``g`` -- a real number; the RGB color's "green" intensity + + - ``b`` -- a real number; the RGB color's "blue" intensity + + OUTPUT: + + - an integer with encoding `256^2 r + 256 g + b` + + EXAMPLES:: + + sage: from sage.plot.colors import float_to_integer + sage: float_to_integer(1.,1.,0.) + 16776960 + sage: float_to_integer(.03,.06,.02) + 462597 + sage: float_to_integer(*Color('brown').rgb()) + 10824234 + sage: float_to_integer((0.2, 0.6, 0.8)) + Traceback (most recent call last): + ... + TypeError: float_to_integer() takes exactly 3 arguments (1 given) + """ + r, g, b = map(mod_one, (r, g, b)) + rr = int(floor(r * 255)) + gg = int(floor(g * 255)) + bb = int(floor(b * 255)) + return 65536 * rr + 256 * gg + bb + + def rainbow(n, format='hex'): """ Returns a list of colors sampled at equal intervals over the diff --git a/src/sage/plot/misc.py b/src/sage/plot/misc.py index 9015a3e9eb4..0a2ad7cc380 100644 --- a/src/sage/plot/misc.py +++ b/src/sage/plot/misc.py @@ -237,9 +237,13 @@ def _multiple_of_constant(n,pos,const): Graphics object consisting of 1 graphics primitive """ from sage.misc.latex import latex - from sage.rings.arith import convergents - c=[i for i in convergents(n/const.n()) if i.denominator()<12] - return '$%s$'%latex(c[-1]*const) + from sage.rings.continued_fraction import continued_fraction + from sage.rings.infinity import Infinity + cf = continued_fraction(n/const) + k = 1 + while cf.quotient(k) != Infinity and cf.denominator(k) < 12: + k += 1 + return '$%s$'%latex(cf.convergent(k-1)*const) def get_matplotlib_linestyle(linestyle, return_type): @@ -377,4 +381,3 @@ def get_matplotlib_linestyle(linestyle, return_type): "'dashed', 'dotted', dashdot', 'None'}, " "respectively {'-', '--', ':', '-.', ''}"% (linestyle)) - diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index 778509e0f2e..ccf6ce73f0f 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -574,7 +574,7 @@ def xydata_from_point_list(points): ([0.0, 1.0], [0.0, 0.0]) This function should work for anything than can be turned into a - list, such as iterators and such (see ticket #10478):: + list, such as iterators and such (see :trac:`10478`):: sage: xydata_from_point_list(iter([(0,0), (sqrt(3), 2)])) ([0.0, 1.7320508075688772], [0.0, 2.0]) @@ -586,22 +586,23 @@ def xydata_from_point_list(points): ([2.0, 3.0, 5.0, 7.0], [11.0, 13.0, 17.0, 19.0]) """ from sage.rings.complex_number import ComplexNumber - if not isinstance(points, (list,tuple)): + + if not isinstance(points, (list, tuple)): points = list(points) try: points = [[float(z) for z in points]] except TypeError: pass - elif len(points)==2 and not isinstance(points[0],(list,tuple,ComplexNumber)): + elif len(points) == 2 and not isinstance(points[0], (list, tuple, + ComplexNumber)): try: points = [[float(z) for z in points]] except TypeError: pass - if len(points)>0 and len(list(points[0]))!=2: + if len(points) and len(list(points[0])) != 2: raise ValueError("points must have 2 coordinates in a 2d line") - xdata = [float(z[0]) for z in points] ydata = [float(z[1]) for z in points] diff --git a/src/sage/plot/plot3d/implicit_plot3d.py b/src/sage/plot/plot3d/implicit_plot3d.py index 3364adf00fc..f0d10164225 100644 --- a/src/sage/plot/plot3d/implicit_plot3d.py +++ b/src/sage/plot/plot3d/implicit_plot3d.py @@ -1,9 +1,9 @@ """ Implicit Plots """ - from implicit_surface import ImplicitSurface + def implicit_plot3d(f, xrange, yrange, zrange, **kwds): r""" Plots an isosurface of a function. @@ -44,7 +44,7 @@ def implicit_plot3d(f, xrange, yrange, zrange, **kwds): A nested set of spheres with a hole cut out:: sage: implicit_plot3d((x^2 + y^2 + z^2), (x, -2, 2), (y, -2, 2), (z, -2, 2), plot_points=60, contour=[1,3,5], \ - ... region=lambda x,y,z: x<=0.2 or y>=0.2 or z<=0.2).show(viewer='tachyon') + ....: region=lambda x,y,z: x<=0.2 or y>=0.2 or z<=0.2).show(viewer='tachyon') A very pretty example, attributed to Douglas Summers-Stay (`archived page `_):: @@ -82,13 +82,37 @@ def implicit_plot3d(f, xrange, yrange, zrange, **kwds): sage: gy = lambda x, y, z: -(x^2 + 2*y + z^2) sage: gz = lambda x, y, z: -(x^2 + y^2 + 2*z) sage: implicit_plot3d(x^2+y^2+z^2, (x, -2, 2), (y, -2, 2), (z, -2, 2), contour=4, \ - ... plot_points=40, smooth=True, gradient=(gx, gy, gz)).show(viewer='tachyon') + ....: plot_points=40, smooth=True, gradient=(gx, gy, gz)).show(viewer='tachyon') A graph of two metaballs interacting with each other:: sage: def metaball(x0, y0, z0): return 1 / ((x-x0)^2 + (y-y0)^2 + (z-z0)^2) sage: implicit_plot3d(metaball(-0.6, 0, 0) + metaball(0.6, 0, 0), (x, -2, 2), (y, -2, 2), (z, -2, 2), plot_points=60, contour=2) Graphics3d Object + + One can color the surface according to a coloring function and a colormap:: + + sage: t = (sin(2*y+3*z)**2).function(x,y,z) + sage: cm = colormaps.gist_rainbow + sage: G = implicit_plot3d(x^2 + y^2 + z^2, (x,-2, 2), (y,-2, 2), + ....: (z,-2, 2), contour=4, color=(t,cm), plot_points=60) + sage: G.show(viewer='tachyon') + + Here is another colored example:: + + sage: x, y, z = var('x,y,z') + sage: t = (x).function(x,y,z) + sage: cm = colormaps.PiYG + sage: G = implicit_plot3d(x^4 + y^2 + z^2, (x,-2, 2), + ....: (y,-2, 2),(z,-2, 2), contour=4, color=(t,cm), plot_points=40) + sage: G + Graphics3d Object + + .. WARNING:: + + This kind of coloring using a colormap can be visualized using + Jmol, Tachyon (option ``viewer='tachyon'``) and Canvas3D + (option ``viewer='canvas3d'`` in the notebook). MANY MORE EXAMPLES: @@ -276,14 +300,6 @@ def implicit_plot3d(f, xrange, yrange, zrange, **kwds): sage: implicit_plot3d(max_symbolic(x, y^2) - z, (x, -2, 2), (y, -2, 2), (z, -2, 2), plot_points=6) Graphics3d Object """ - - # These options aren't fully implemented yet: - # vertex_color: Either a single callable taking (x,y,z) and returning - # (r,g,b), or a triple of three callables. Not used for jmol. Note that - # Tachyon only lets you specify a single color for its triangles; this will - # be the mean of the three vertex colors of the triangle. If this is None - # (the default), we don't provide separate triangle colors to Tachyon. - # These options, related to rendering with smooth shading, are irrelevant # since IndexFaceSet does not support surface normals: # smooth: (default: False) Whether to use vertex normals to produce a @@ -297,7 +313,6 @@ def implicit_plot3d(f, xrange, yrange, zrange, **kwds): # or a tuple of three callables that each take (x,y,z) and return dx, dy, dz # respectively. - G = ImplicitSurface(f, xrange, yrange, zrange, **kwds) G._set_extra_kwds(kwds) return G diff --git a/src/sage/plot/plot3d/implicit_surface.pyx b/src/sage/plot/plot3d/implicit_surface.pyx index 536dfc9a1c9..c542af23b4c 100644 --- a/src/sage/plot/plot3d/implicit_surface.pyx +++ b/src/sage/plot/plot3d/implicit_surface.pyx @@ -57,7 +57,7 @@ AUTHORS: # show(...) had a prepass where they went through their rendering # trees, found ImplicitSurface objects with the same function, # bounding box, and plot_points (other parameters, such as contours, -# hole, jmol_color, vertex_color, would be allowed to be different), +# hole, color, would be allowed to be different), # and arranged to have them all plotted simultaneously. These # prepasses have not been written yet. Combining multiple # ImplicitSurface plots would be particularly advantageous for animate(...), @@ -66,7 +66,7 @@ AUTHORS: # If you have a reasonably simple surface (not a space-filling fractal), # then if n is your resolution, we have n^3 evaluations of the main # function, about n^2 evaluations of auxiliary functions (hole, gradient, -# vertex_color/jmol_color), and output of size about n^2. +# color), and output of size about n^2. # With this in mind, we pay particular attention to optimizing the n^3 # function evaluations. (But keep in mind that n may be as small as 20 @@ -83,7 +83,7 @@ from cStringIO import StringIO cimport numpy as np import numpy as np -from sage.plot.plot3d.transform cimport point_c, face_c, Transformation +from sage.plot.plot3d.transform cimport point_c, face_c, color_c, Transformation from sage.plot.plot3d.base cimport PrimitiveObject from sage.plot.plot3d.base import RenderParams, default_texture from sage.plot.plot3d.index_face_set cimport IndexFaceSet @@ -127,6 +127,7 @@ cdef void interpolate_point_c(point_c *result, double frac, point_c *inputs): result[0].y = inputs[0].y + frac*(inputs[1].y - inputs[0].y) result[0].z = inputs[0].z + frac*(inputs[1].z - inputs[0].z) + cdef class VertexInfo: # The point in "integer space" cdef point_c pt @@ -134,8 +135,8 @@ cdef class VertexInfo: # The gradient at this point in "evaluation space" cdef point_c gradient - # (R,G,B), so not really a point at all - cdef point_c color + # (R,G,B) color ; a color triple + cdef color_c color # This point in "evaluation space" cdef point_c eval_pt @@ -157,11 +158,12 @@ cdef class VertexInfo: sage: VertexInfo() <0.0, 0.0, 0.0> """ - return '<%s, %s, %s>' % (self.pt.x, self.pt.y, self.pt.z) + return '<{}, {}, {}>'.format(self.pt.x, self.pt.y, self.pt.z) + cdef mk_VertexInfo(double x, double y, double z, point_c *eval_min, point_c *eval_scale): cdef VertexInfo v - v = PY_NEW(VertexInfo) + v = VertexInfo.__new__(VertexInfo) v.pt.x = x v.pt.y = y v.pt.z = z @@ -170,6 +172,7 @@ cdef mk_VertexInfo(double x, double y, double z, point_c *eval_min, point_c *eva return v + cdef class MarchingCubes: r""" Handles marching cube rendering. @@ -195,7 +198,8 @@ cdef class MarchingCubes: cdef readonly object region cdef readonly object gradient cdef readonly bint smooth - cdef readonly object vertex_color + cdef readonly object color_function + cdef readonly object colormap cdef readonly object results # We deal with three coordinate systems. We do most of our work @@ -219,7 +223,8 @@ cdef class MarchingCubes: cdef point_c out_origin, out_plus_x, out_plus_y, out_plus_z def __init__(self, xrange, yrange, zrange, contour, plot_points, - transform=None, region=None, gradient=None, smooth=True, vertex_color=None): + transform=None, region=None, gradient=None, smooth=True, + color_function=None, colormap=None): """ TESTS: @@ -228,7 +233,6 @@ cdef class MarchingCubes: sage: from sage.plot.plot3d.implicit_surface import MarchingCubes sage: cube_marcher = MarchingCubes((0, 1), (0, 1), (0, 1), 1, (10, 10, 10)) """ - self.xrange = xrange self.yrange = yrange self.zrange = zrange @@ -240,7 +244,9 @@ cdef class MarchingCubes: self.region = region self.gradient = gradient self.smooth = smooth - self.vertex_color = vertex_color + + self.color_function = color_function + self.colormap = colormap self.eval_min.x = xrange[0] self.eval_scale.x = (xrange[1] - xrange[0]) / (self.nx - 1) @@ -273,8 +279,10 @@ cdef class MarchingCubes: def finish(self): """ - Returns the results of the marching cubes algorithm as a list. The format - is specific to the subclass implementing this method. + Return the results of the marching cubes algorithm as a list. + + The format is specific to the subclass implementing this + method. TESTS: @@ -287,10 +295,13 @@ cdef class MarchingCubes: """ return self.results + cdef class MarchingCubesTriangles(MarchingCubes): """ A subclass of MarchingCubes that returns its results as a list of triangles, - including their vertices and normals (if smooth=True). + including their vertices and normals (if ``smooth=True``). + + And also their vertex colors if a vertex coloring function is given. """ cdef readonly np.ndarray x_vertices @@ -335,10 +346,10 @@ cdef class MarchingCubesTriangles(MarchingCubes): sage: f = lambda x, y, z: x^2 + y^2 + z^2 sage: slices = np.zeros((10, 10, 10), dtype=np.double) sage: for x in reversed(xrange(0, 10)): - ... for y in xrange(0, 10): - ... for z in xrange(0, 10): - ... slices[x, y, z] = f(*[a * (4 / 9) -2 for a in (x, y, z)]) - ... cube_marcher.process_slice(x, slices[x, :, :]) + ....: for y in xrange(0, 10): + ....: for z in xrange(0, 10): + ....: slices[x, y, z] = f(*[a * (4 / 9) -2 for a in (x, y, z)]) + ....: cube_marcher.process_slice(x, slices[x, :, :]) sage: faces = cube_marcher.finish() sage: faces[0][0] {'x': 1.555555555555..., 'y': -1.111111111111..., 'z': -0.555555555555...} @@ -508,8 +519,9 @@ cdef class MarchingCubesTriangles(MarchingCubes): cur[y+i,z-1] if z>0 else 0, cur[y+i,z+1] if z0 else 0, cur[y,z+i+1] if z+i0 else 0, right[y,z+1] if z= 20 # I should hope so, we're rendering at the default resolution! sage: for vertex, surf_vertex in zip(vertices, G.vertex_list())[0:20]: - ... list.append(points_equal(map(float, vertex.split(' ')[1:]), surf_vertex)) + ....: list.append(points_equal(map(float, vertex.split(' ')[1:]), surf_vertex)) sage: all(list) True """ @@ -1073,7 +1123,7 @@ cdef class ImplicitSurface(IndexFaceSet): sage: var('x,y,z') (x, y, z) sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1)) - sage: show(G, viewer='jmol') + sage: show(G, viewer='jmol') # indirect doctest """ self.triangulate() return IndexFaceSet.jmol_repr(self, render_params) @@ -1096,11 +1146,13 @@ cdef class ImplicitSurface(IndexFaceSet): def triangulate(self, force=False): """ - The IndexFaceSet will be empty until you call this method, which generates - the faces and vertices according to the parameters specified in the - constructor for ImplicitSurface. Note that if you call this method more - than once, subsequent invocations will have no effect (this is an - optimization to avoid repeated work) unless you specify force=True in the + The IndexFaceSet will be empty until you call this method, + which generates the faces and vertices according to the + parameters specified in the constructor for ImplicitSurface. + + Note that if you call this method more than once, subsequent + invocations will have no effect (this is an optimization to + avoid repeated work) unless you specify force=True in the keywords. EXAMPLES:: @@ -1115,6 +1167,7 @@ cdef class ImplicitSurface(IndexFaceSet): sage: len(G.vertex_list()) > 0, len(G.face_list()) > 0 (True, True) sage: G.show() # This should be fast, since the mesh is already triangulated. + """ if self.fcount != 0 and not force: # The mesh is already triangulated @@ -1123,7 +1176,8 @@ cdef class ImplicitSurface(IndexFaceSet): options = dict(xrange=self.xrange, yrange=self.yrange, zrange=self.zrange, region=self.region, smooth=self.smooth, gradient=self.gradient, - vertex_color=self.vertex_color, + color_function=self.color_function, + colormap=self.colormap, plot_points=self.plot_points) cube_marchers = [MarchingCubesTriangles(contour=x, **options) for x in self.contours] results = render_implicit(self.f, self.xrange, self.yrange, self.zrange, @@ -1141,6 +1195,15 @@ cdef class ImplicitSurface(IndexFaceSet): dest_face.n = 3 dest_face.vertices = &self.face_indices[3 * i] + if self.color_function is not None: + clist = [(src_face[j]['r'], + src_face[j]['g'], + src_face[j]['b']) + for j in range(3, 6)] + ct = (sum(clist[j][i] for j in range(3)) / 3 for i in range(3)) + # ct is the mean of the colors of vertices + dest_face.color.r, dest_face.color.g, dest_face.color.b = ct + for j from 0 <= j < 3: dest_face.vertices[j] = (3 * i) + j dest_vertex = &self.vs[(3 * i) + j] diff --git a/src/sage/plot/plot3d/index_face_set.pxd b/src/sage/plot/plot3d/index_face_set.pxd index 0046cff9238..bee67ff6efd 100644 --- a/src/sage/plot/plot3d/index_face_set.pxd +++ b/src/sage/plot/plot3d/index_face_set.pxd @@ -1,9 +1,10 @@ from sage.plot.plot3d.base cimport PrimitiveObject -from transform cimport point_c, face_c +from transform cimport point_c, face_c, color_c cdef class IndexFaceSet(PrimitiveObject): cdef bint enclosed + cdef bint global_texture cdef Py_ssize_t vcount, fcount, icount cdef realloc(self, vcount, fcount, icount) # array of {x,y,z} @@ -13,7 +14,6 @@ cdef class IndexFaceSet(PrimitiveObject): # pointers into face_indices marking the begining of each face cdef face_c* _faces - cdef class FaceIter: cdef Py_ssize_t i cdef IndexFaceSet set diff --git a/src/sage/plot/plot3d/index_face_set.pyx b/src/sage/plot/plot3d/index_face_set.pyx index be7b72fb03b..ba685593fe0 100644 --- a/src/sage/plot/plot3d/index_face_set.pyx +++ b/src/sage/plot/plot3d/index_face_set.pyx @@ -1,16 +1,21 @@ """ +Indexed Face Sets + Graphics3D object that consists of a list of polygons, also used for triangulations of other objects. +Usually these objects are not created directly by users. + AUTHORS: - -- Robert Bradshaw (2007-08-26): initial version - -- Robert Bradshaw (2007-08-28): significant optimizations -TODO: - -- Smooth triangles -""" +- Robert Bradshaw (2007-08-26): initial version +- Robert Bradshaw (2007-08-28): significant optimizations +.. TODO:: + Smooth triangles using vertex normals + +""" #***************************************************************************** # Copyright (C) 2007 Robert Bradshaw # @@ -26,24 +31,23 @@ TODO: # http://www.gnu.org/licenses/ #***************************************************************************** - - include "sage/ext/stdsage.pxi" include "sage/ext/interrupt.pxi" cdef extern from *: - void memset(void *, int, Py_ssize_t) - void memcpy(void * dest, void * src, Py_ssize_t n) - int sprintf_3d "sprintf" (char*, char*, double, double, double) - int sprintf_3i "sprintf" (char*, char*, int, int, int) - int sprintf_4i "sprintf" (char*, char*, int, int, int, int) - int sprintf_5i "sprintf" (char*, char*, int, int, int, int, int) - int sprintf_6i "sprintf" (char*, char*, int, int, int, int, int, int) - int sprintf_9d "sprintf" (char*, char*, double, double, double, double, double, double, double, double, double) + void memset(void *, int, Py_ssize_t) + void memcpy(void * dest, void * src, Py_ssize_t n) + int sprintf_3d "sprintf" (char*, char*, double, double, double) + int sprintf_3i "sprintf" (char*, char*, int, int, int) + int sprintf_4i "sprintf" (char*, char*, int, int, int, int) + int sprintf_5i "sprintf" (char*, char*, int, int, int, int, int) + int sprintf_6i "sprintf" (char*, char*, int, int, int, int, int, int) + int sprintf_7i "sprintf" (char*, char*, int, int, int, int, int, int, int) + int sprintf_9d "sprintf" (char*, char*, double, double, double, double, double, double, double, double, double) # import the double infinity constant cdef extern from "math.h": - enum: INFINITY + enum: INFINITY from cpython.list cimport * from cpython.string cimport * @@ -59,16 +63,24 @@ from sage.rings.real_double import RDF from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector +from sage.plot.colors import Color, float_to_integer from sage.plot.plot3d.base import Graphics3dGroup from transform cimport Transformation - # -------------------------------------------------------------------- # Fast routines for generating string representations of the polygons. # -------------------------------------------------------------------- +cdef inline format_tachyon_texture(color_c rgb): + cdef char rs[200] + cdef Py_ssize_t cr = sprintf_3d(rs, + "TEXTURE\n AMBIENT 0.3 DIFFUSE 0.7 SPECULAR 0 OPACITY 1.0\n COLOR %g %g %g \n TEXFUNC 0", + rgb.r, rgb.g, rgb.b) + return PyString_FromStringAndSize(rs, cr) + + cdef inline format_tachyon_triangle(point_c P, point_c Q, point_c R): cdef char ss[250] # PyString_FromFormat doesn't do floats? @@ -79,13 +91,15 @@ cdef inline format_tachyon_triangle(point_c P, point_c Q, point_c R): R.x, R.y, R.z ) return PyString_FromStringAndSize(ss, r) + cdef inline format_json_vertex(point_c P): cdef char ss[100] cdef Py_ssize_t r = sprintf_3d(ss, "{x:%g,y:%g,z:%g}", P.x, P.y, P.z) return PyString_FromStringAndSize(ss, r) cdef inline format_json_face(face_c face): - return "[%s]" % ",".join([str(face.vertices[i]) for i from 0 <= i < face.n]) + return "[{}]".format(",".join([str(face.vertices[i]) + for i from 0 <= i < face.n])) cdef inline format_obj_vertex(point_c P): cdef char ss[100] @@ -116,60 +130,98 @@ cdef inline format_obj_face_back(face_c face, int off): return "f " + " ".join([str(face.vertices[i] + off) for i from face.n > i >= 0]) return PyString_FromStringAndSize(ss, r) - cdef inline format_pmesh_vertex(point_c P): cdef char ss[100] # PyString_FromFormat doesn't do floats? cdef Py_ssize_t r = sprintf_3d(ss, "%g %g %g", P.x, P.y, P.z) return PyString_FromStringAndSize(ss, r) -cdef inline format_pmesh_face(face_c face): +cdef inline format_pmesh_face(face_c face, int has_color): cdef char ss[100] cdef Py_ssize_t r, i + cdef int color + # if the face has an individual color, has_color is -1 + # otherwise it is 1 + if has_color == -1: + color = float_to_integer(face.color.r, + face.color.g, + face.color.b) + # it seems that Jmol does not like the 0 color at all + if color == 0: + color = 1 + if face.n == 3: - r = sprintf_5i(ss, "%d\n%d\n%d\n%d\n%d", face.n+1, - face.vertices[0], - face.vertices[1], - face.vertices[2], - face.vertices[0]) + if has_color == 1: + r = sprintf_5i(ss, "%d\n%d\n%d\n%d\n%d", has_color * 4, + face.vertices[0], + face.vertices[1], + face.vertices[2], + face.vertices[0]) + else: + r = sprintf_6i(ss, "%d\n%d\n%d\n%d\n%d\n%d", has_color * 4, + face.vertices[0], + face.vertices[1], + face.vertices[2], + face.vertices[0], color) elif face.n == 4: - r = sprintf_6i(ss, "%d\n%d\n%d\n%d\n%d\n%d", face.n+1, - face.vertices[0], - face.vertices[1], - face.vertices[2], - face.vertices[3], - face.vertices[0]) + if has_color == 1: + r = sprintf_6i(ss, "%d\n%d\n%d\n%d\n%d\n%d", has_color * 5, + face.vertices[0], + face.vertices[1], + face.vertices[2], + face.vertices[3], + face.vertices[0]) + else: + r = sprintf_7i(ss, "%d\n%d\n%d\n%d\n%d\n%d\n%d", has_color * 5, + face.vertices[0], + face.vertices[1], + face.vertices[2], + face.vertices[3], + face.vertices[0], color) else: # Naive triangulation all = [] - for i from 1 <= i < face.n-1: - r = sprintf_4i(ss, "4\n%d\n%d\n%d\n%d", face.vertices[0], - face.vertices[i], - face.vertices[i+1], - face.vertices[0]) - PyList_Append(all, PyString_FromStringAndSize(ss, r)) + if has_color == 1: + for i from 1 <= i < face.n - 1: + r = sprintf_5i(ss, "%d\n%d\n%d\n%d\n%d", has_color * 4, + face.vertices[0], + face.vertices[i], + face.vertices[i + 1], + face.vertices[0]) + PyList_Append(all, PyString_FromStringAndSize(ss, r)) + else: + for i from 1 <= i < face.n - 1: + r = sprintf_6i(ss, "%d\n%d\n%d\n%d\n%d\n%d", has_color * 4, + face.vertices[0], + face.vertices[i], + face.vertices[i + 1], + face.vertices[0], color) + PyList_Append(all, PyString_FromStringAndSize(ss, r)) return "\n".join(all) # PyString_FromFormat is almost twice as slow return PyString_FromStringAndSize(ss, r) - - cdef class IndexFaceSet(PrimitiveObject): - """ Graphics3D object that consists of a list of polygons, also used for triangulations of other objects. Polygons (mostly triangles and quadrilaterals) are stored in the - c struct \code{face_c} (see transform.pyx). Rather than storing + c struct ``face_c`` (see transform.pyx). Rather than storing the points directly for each polygon, each face consists a list of pointers into a common list of points which are basically triples - of doubles in a \code{point_c}. + of doubles in a ``point_c``. + + Moreover, each face has an attribute ``color`` which is used to + store color information when faces are colored. The red/green/blue + components are then available as floats between 0 and 1 using + ``color.r,color.g,color.b``. Usually these objects are not created directly by users. - EXAMPLES: + EXAMPLES:: + sage: from sage.plot.plot3d.index_face_set import IndexFaceSet sage: S = IndexFaceSet([[(1,0,0),(0,1,0),(0,0,1)],[(1,0,0),(0,1,0),(0,0,0)]]) sage: S.face_list() @@ -185,19 +237,38 @@ cdef class IndexFaceSet(PrimitiveObject): sage: face_list = [[0,1,n] for n in range(2,10)] sage: S = IndexFaceSet(face_list, point_list, color='red') sage: S.face_list() - [[(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 0.0)], [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)], [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 2.0)], [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 3.0)], [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 4.0)], [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 5.0)], [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 6.0)], [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 7.0)]] + [[(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 0.0)], + [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)], + [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 2.0)], + [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 3.0)], + [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 4.0)], + [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 5.0)], + [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 6.0)], + [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 7.0)]] sage: S.show() - """ + A simple example of colored IndexFaceSet (:trac:`12212`):: + + sage: from sage.plot.plot3d.index_face_set import IndexFaceSet + sage: from sage.plot.plot3d.texture import Texture + sage: point_list = [(2,0,0),(0,2,0),(0,0,2),(0,1,1),(1,0,1),(1,1,0)] + sage: face_list = [[0,4,5],[3,4,5],[2,3,4],[1,3,5]] + sage: col = rainbow(10, 'rgbtuple') + sage: t_list = [Texture(col[i]) for i in range(10)] + sage: S = IndexFaceSet(face_list, point_list, texture_list=t_list) + sage: S.show(viewer='tachyon') + + """ def __cinit__(self): self.vs = NULL self.face_indices = NULL self._faces = NULL - - - def __init__(self, faces, point_list=None, enclosed=False, **kwds): + def __init__(self, faces, point_list=None, + enclosed=False, texture_list=None, **kwds): PrimitiveObject.__init__(self, **kwds) + self.global_texture = (texture_list is None) + self.enclosed = enclosed if point_list is None: @@ -235,6 +306,10 @@ cdef class IndexFaceSet(PrimitiveObject): for i from 0 <= i < self.fcount: self._faces[i].n = len(faces[i]) self._faces[i].vertices = &self.face_indices[cur_pt] + if self.global_texture: + self._faces[i].color.r, self._faces[i].color.g, self._faces[i].color.b = self.texture.color + else: + self._faces[i].color.r, self._faces[i].color.g, self._faces[i].color.b = texture_list[i].color for ix in faces[i]: self.face_indices[cur_pt] = ix cur_pt += 1 @@ -274,14 +349,15 @@ cdef class IndexFaceSet(PrimitiveObject): else: self.face_indices = sage_realloc(self.face_indices, sizeof(int) * icount) if (self.vs == NULL and vcount > 0) or (self.face_indices == NULL and icount > 0) or (self._faces == NULL and fcount > 0): - raise MemoryError, "Out of memory allocating triangulation for %s" % type(self) + raise MemoryError("Out of memory allocating triangulation for %s" % type(self)) def _clean_point_list(self): - # TODO: There is still wasted space where quadrilaterals were converted to triangles... - # but it's so little it's probably not worth bothering with + # TODO: There is still wasted space where quadrilaterals were + # converted to triangles... but it's so little it's probably + # not worth bothering with cdef int* point_map = sage_malloc(sizeof(int) * self.vcount) if point_map == NULL: - raise MemoryError, "Out of memory cleaning up for %s" % type(self) + raise MemoryError("Out of memory cleaning up for %s" % type(self)) memset(point_map, 0, sizeof(int) * self.vcount) # TODO: sage_calloc cdef Py_ssize_t i, j cdef face_c *face @@ -310,9 +386,10 @@ cdef class IndexFaceSet(PrimitiveObject): surfaces but looks bad if one actually has a polyhedron. INPUT: - threshold -- the minimum cosine of the angle between adjacent faces - a higher threshold separates more, all faces if >= 1, - no faces if <= -1 + + ``threshold`` -- the minimum cosine of the angle between adjacent + faces a higher threshold separates more, all faces if >= 1, no + faces if <= -1 """ cdef Py_ssize_t i, j, k cdef face_c *face @@ -320,7 +397,7 @@ cdef class IndexFaceSet(PrimitiveObject): cdef int* point_counts = sage_malloc(sizeof(int) * (self.vcount * 2 + 1)) # For each vertex, get number of faces if point_counts == NULL: - raise MemoryError, "Out of memory in _seperate_creases for %s" % type(self) + raise MemoryError("Out of memory in _seperate_creases for %s" % type(self)) cdef int* running_point_counts = &point_counts[self.vcount] memset(point_counts, 0, sizeof(int) * self.vcount) for i from 0 <= i < self.fcount: @@ -335,13 +412,13 @@ cdef class IndexFaceSet(PrimitiveObject): running_point_counts[i] = running running += point_counts[i] if point_counts[i] > max: - max = point_counts[i] + max = point_counts[i] running_point_counts[self.vcount] = running # Create an array, indexed by running_point_counts[v], to the list of faces containing that vertex. cdef face_c** point_faces = sage_malloc(sizeof(face_c*) * total) if point_faces == NULL: sage_free(point_counts) - raise MemoryError, "Out of memory in _seperate_creases for %s" % type(self) + raise MemoryError("Out of memory in _seperate_creases for %s" % type(self)) sig_on() memset(point_counts, 0, sizeof(int) * self.vcount) for i from 0 <= i < self.fcount: @@ -382,7 +459,7 @@ cdef class IndexFaceSet(PrimitiveObject): sage_free(point_faces) self.vcount = self.fcount = self.icount = 0 # so we don't get segfaults on bad points sig_off() - raise MemoryError, "Out of memory in _seperate_creases for %s, CORRUPTED" % type(self) + raise MemoryError("Out of memory in _seperate_creases for %s, CORRUPTED" % type(self)) ix = self.vcount running = 0 for i from 0 <= i < self.vcount - start: @@ -410,8 +487,6 @@ cdef class IndexFaceSet(PrimitiveObject): sage_free(point_faces) sig_off() - - def _mem_stats(self): return self.vcount, self.fcount, self.icount @@ -425,14 +500,18 @@ cdef class IndexFaceSet(PrimitiveObject): def is_enclosed(self): """ - Whether or not it is necessary to render the back sides of the polygons - (assuming, of course, that they have the correct orientation). + Whether or not it is necessary to render the back sides of the polygons. - This is may be passed in on construction. It is also calculated - in ParametricSurface by verifying the opposite edges of the rendered - domain either line up or are pinched together. + One is assuming, of course, that they have the correct orientation. + + This is may be passed in on construction. It is also + calculated in + :class:`sage.plot.plot3d.parametric_surface.ParametricSurface` + by verifying the opposite edges of the rendered domain either + line up or are pinched together. + + EXAMPLES:: - EXAMPLES: sage: from sage.plot.plot3d.index_face_set import IndexFaceSet sage: IndexFaceSet([[(0,0,1),(0,1,0),(1,0,0)]]).is_enclosed() False @@ -440,14 +519,32 @@ cdef class IndexFaceSet(PrimitiveObject): return self.enclosed def index_faces(self): + """ + Return the list over all faces of the indices of the vertices. + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: S.index_faces() + [[0, 1, 2, 3], + [0, 4, 5, 1], + [0, 3, 6, 4], + [5, 4, 6, 7], + [6, 3, 2, 7], + [2, 1, 5, 7]] + """ cdef Py_ssize_t i, j - return [[self._faces[i].vertices[j] for j from 0 <= j < self._faces[i].n] for i from 0 <= i < self.fcount] + return [[self._faces[i].vertices[j] + for j from 0 <= j < self._faces[i].n] + for i from 0 <= i < self.fcount] def faces(self): """ An iterator over the faces. - EXAMPLES: + EXAMPLES:: + sage: from sage.plot.plot3d.shapes import * sage: S = Box(1,2,3) sage: list(S.faces()) == S.face_list() @@ -456,22 +553,56 @@ cdef class IndexFaceSet(PrimitiveObject): return FaceIter(self) def face_list(self): + """ + Return the list of faces. + + Every face is given as a tuple of vertices. + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: S.face_list()[0] + [(1.0, 2.0, 3.0), (-1.0, 2.0, 3.0), (-1.0, -2.0, 3.0), (1.0, -2.0, 3.0)] + """ points = self.vertex_list() cdef Py_ssize_t i, j - return [[points[self._faces[i].vertices[j]] for j from 0 <= j < self._faces[i].n] for i from 0 <= i < self.fcount] + return [[points[self._faces[i].vertices[j]] + for j from 0 <= j < self._faces[i].n] + for i from 0 <= i < self.fcount] def edges(self): + """ + An iterator over the edges. + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: list(S.edges())[0] + ((1.0, -2.0, 3.0), (1.0, 2.0, 3.0)) + """ return EdgeIter(self) def edge_list(self): - # For consistancy + """ + Return the list of edges. + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: S.edge_list()[0] + ((1.0, -2.0, 3.0), (1.0, 2.0, 3.0)) + """ return list(self.edges()) def vertices(self): """ An iterator over the vertices. - EXAMPLES: + EXAMPLES:: + sage: from sage.plot.plot3d.shapes import * sage: S = Cone(1,1) sage: list(S.vertices()) == S.vertex_list() @@ -480,20 +611,76 @@ cdef class IndexFaceSet(PrimitiveObject): return VertexIter(self) def vertex_list(self): + """ + Return the list of vertices. + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = polygon([(0,0,1), (1,1,1), (2,0,1)]) + sage: S.vertex_list()[0] + (0.0, 0.0, 1.0) + """ cdef Py_ssize_t i return [(self.vs[i].x, self.vs[i].y, self.vs[i].z) for i from 0 <= i < self.vcount] def x3d_geometry(self): + """ + Return the x3d data. + + EXAMPLES: + + A basic test with a triangle:: + + sage: G = polygon([(0,0,1), (1,1,1), (2,0,1)]) + sage: print G.x3d_geometry() + + + + + + + A simple colored one:: + + sage: from sage.plot.plot3d.index_face_set import IndexFaceSet + sage: from sage.plot.plot3d.texture import Texture + sage: point_list = [(2,0,0),(0,2,0),(0,0,2),(0,1,1),(1,0,1),(1,1,0)] + sage: face_list = [[0,4,5],[3,4,5],[2,3,4],[1,3,5]] + sage: col = rainbow(10, 'rgbtuple') + sage: t_list=[Texture(col[i]) for i in range(10)] + sage: S = IndexFaceSet(face_list, point_list, texture_list=t_list) + sage: print S.x3d_geometry() + + + + + + + """ cdef Py_ssize_t i - points = ",".join(["%s %s %s"%(self.vs[i].x, self.vs[i].y, self.vs[i].z) for i from 0 <= i < self.vcount]) + points = ",".join(["%s %s %s" % (self.vs[i].x, + self.vs[i].y, + self.vs[i].z) + for i from 0 <= i < self.vcount]) coordIndex = ",-1,".join([",".join([str(self._faces[i].vertices[j]) for j from 0 <= j < self._faces[i].n]) for i from 0 <= i < self.fcount]) + if not self.global_texture: + colorIndex = ",".join([str(self._faces[i].color.r) + " " + + str(self._faces[i].color.g) + " " + + str(self._faces[i].color.b) + for i from 0 <= i < self.fcount]) + return """ + + + + +""" % (coordIndex, points, colorIndex) return """ -"""%(coordIndex, points) +""" % (coordIndex, points) def bounding_box(self): r""" @@ -508,8 +695,8 @@ cdef class IndexFaceSet(PrimitiveObject): EXAMPLE:: - sage: x,y=var('x,y') - sage: p=plot3d(sqrt(sin(x)*sin(y)), (x,0,2*pi),(y,0,2*pi)) + sage: x,y = var('x,y') + sage: p = plot3d(sqrt(sin(x)*sin(y)), (x,0,2*pi),(y,0,2*pi)) sage: p.bounding_box() ((0.0, 0.0, -0.0), (6.283185307179586, 6.283185307179586, 0.9991889981715697)) """ @@ -529,14 +716,28 @@ cdef class IndexFaceSet(PrimitiveObject): return ((low.x, low.y, low.z), (high.x, high.y, high.z)) def partition(self, f): - """ - Partition the faces of self based on a map $f: \RR^3 \leftarrow \ZZ$ - applied to the center of each face. + r""" + Partition the faces of ``self``. + + The partition is done according to the value of a map + `f: \RR^3 \rightarrow \ZZ` applied to the center of each face. + + INPUT: + + - `f` -- a function from `\RR^3` to `\ZZ` + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: len(S.partition(lambda x,y,z : floor(x+y+z))) + 6 """ cdef Py_ssize_t i, j, ix, face_ix cdef int part cdef point_c P - cdef face_c *face, *new_face + cdef face_c *face + cdef face_c *new_face cdef IndexFaceSet face_set cdef int *partition = sage_malloc(sizeof(int) * self.fcount) @@ -584,10 +785,28 @@ cdef class IndexFaceSet(PrimitiveObject): def tachyon_repr(self, render_params): """ - TESTS: - sage: from sage.plot.plot3d.shapes import * - sage: S = Cone(1,1) - sage: s = S.tachyon_repr(S.default_render_params()) + Return a tachyon object for ``self``. + + EXAMPLES: + + A basic test with a triangle:: + + sage: G = polygon([(0,0,1), (1,1,1), (2,0,1)]) + sage: s = G.tachyon_repr(G.default_render_params()); s + ['TRI V0 0 0 1 V1 1 1 1 V2 2 0 1', ...] + + A simple colored one:: + + sage: from sage.plot.plot3d.index_face_set import IndexFaceSet + sage: from sage.plot.plot3d.texture import Texture + sage: point_list = [(2,0,0),(0,2,0),(0,0,2),(0,1,1),(1,0,1),(1,1,0)] + sage: face_list = [[0,4,5],[3,4,5],[2,3,4],[1,3,5]] + sage: col = rainbow(10, 'rgbtuple') + sage: t_list=[Texture(col[i]) for i in range(10)] + sage: S = IndexFaceSet(face_list, point_list, texture_list=t_list) + sage: S.tachyon_repr(S.default_render_params()) + ['TRI V0 2 0 0 V1 1 0 1 V2 1 1 0', + 'TEXTURE... AMBIENT 0.3 DIFFUSE 0.7 SPECULAR 0 OPACITY 1.0... COLOR 1 0 0 ... TEXFUNC 0',...] """ cdef Transformation transform = render_params.transform lines = [] @@ -606,7 +825,10 @@ cdef class IndexFaceSet(PrimitiveObject): Q = self.vs[face.vertices[1]] R = self.vs[face.vertices[2]] PyList_Append(lines, format_tachyon_triangle(P, Q, R)) - PyList_Append(lines, self.texture.id) + if self.global_texture: + PyList_Append(lines, self.texture.id) + else: + PyList_Append(lines, format_tachyon_texture(face.color)) if face.n > 3: for k from 3 <= k < face.n: Q = R @@ -615,26 +837,45 @@ cdef class IndexFaceSet(PrimitiveObject): else: R = self.vs[face.vertices[k]] PyList_Append(lines, format_tachyon_triangle(P, Q, R)) - PyList_Append(lines, self.texture.id) + if self.global_texture: + PyList_Append(lines, self.texture.id) + else: + PyList_Append(lines, format_tachyon_texture(face.color)) sig_off() return lines def json_repr(self, render_params): """ - TESTS:: + Return a json representation for ``self``. + + TESTS: + + A basic test with a triangle:: sage: G = polygon([(0,0,1), (1,1,1), (2,0,1)]) sage: G.json_repr(G.default_render_params()) - ["{vertices:[{x:0,y:0,z:1},{x:1,y:1,z:1},{x:2,y:0,z:1}],faces:[[0,1,2]],color:'0000ff'}"] - """ + ["{vertices:[{x:0,y:0,z:1},{x:1,y:1,z:1},{x:2,y:0,z:1}],faces:[[0,1,2]],color:'#0000ff'}"] + A simple colored one:: + + sage: from sage.plot.plot3d.index_face_set import IndexFaceSet + sage: from sage.plot.plot3d.texture import Texture + sage: point_list = [(2,0,0),(0,2,0),(0,0,2),(0,1,1),(1,0,1),(1,1,0)] + sage: face_list = [[0,4,5],[3,4,5],[2,3,4],[1,3,5]] + sage: col = rainbow(10, 'rgbtuple') + sage: t_list=[Texture(col[i]) for i in range(10)] + sage: S = IndexFaceSet(face_list, point_list, texture_list=t_list) + sage: S.json_repr(S.default_render_params()) + ["{vertices:[{x:2,y:0,z:0},{x:0,y:2,z:0},{x:0,y:0,z:2},{x:0,y:1,z:1},{x:1,y:0,z:1},{x:1,y:1,z:0}],faces:[[0,4,5],[3,4,5],[2,3,4],[1,3,5]],face_colors:['#ff0000','#ff9900','#cbff00','#33ff00']}"] + """ cdef Transformation transform = render_params.transform cdef point_c res if transform is None: - vertices_str = "[%s]" % ",".join([format_json_vertex(self.vs[i]) - for i from 0 <= i < self.vcount]) + vertices_str = "[{}]".format( + ",".join([format_json_vertex(self.vs[i]) + for i from 0 <= i < self.vcount])) else: vertices_str = "[" for i from 0 <= i < self.vcount: @@ -643,15 +884,28 @@ cdef class IndexFaceSet(PrimitiveObject): vertices_str += "," vertices_str += format_json_vertex(res) vertices_str += "]" - faces_str = "[%s]" % ",".join([format_json_face(self._faces[i]) - for i from 0 <= i < self.fcount]) - color_str = "'%s'" % self.texture.hex_rgb() - return ["{vertices:%s,faces:%s,color:%s}" % - (vertices_str, faces_str, color_str)] + + faces_str = "[{}]".format(",".join([format_json_face(self._faces[i]) + for i from 0 <= i < self.fcount])) + if self.global_texture: + color_str = "'#{}'".format(self.texture.hex_rgb()) + return ["{vertices:%s,faces:%s,color:%s}" % + (vertices_str, faces_str, color_str)] + else: + color_str = "[{}]".format(",".join(["'#{}'".format( + Color(self._faces[i].color.r, + self._faces[i].color.g, + self._faces[i].color.b).__hex__()) + for i from 0 <= i < self.fcount])) + return ["{vertices:%s,faces:%s,face_colors:%s}" % + (vertices_str, faces_str, color_str)] def obj_repr(self, render_params): """ - TESTS: + Return an obj representation for ``self``. + + TESTS:: + sage: from sage.plot.plot3d.shapes import * sage: S = Cylinder(1,1) sage: s = S.obj_repr(S.default_render_params()) @@ -687,10 +941,13 @@ cdef class IndexFaceSet(PrimitiveObject): def jmol_repr(self, render_params): """ - TESTS: - sage: from sage.plot.plot3d.shapes import * - sage: S = Cylinder(1,1) - sage: S.show() + Return a jmol representation for ``self``. + + TESTS:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Cylinder(1,1) + sage: S.show(viewer='jmol') # indirect doctest """ cdef Transformation transform = render_params.transform cdef Py_ssize_t i @@ -700,16 +957,24 @@ cdef class IndexFaceSet(PrimitiveObject): sig_on() if transform is None: - points = [format_pmesh_vertex(self.vs[i]) for i from 0 <= i < self.vcount] + points = [format_pmesh_vertex(self.vs[i]) + for i from 0 <= i < self.vcount] else: points = [] for i from 0 <= i < self.vcount: transform.transform_point_c(&res, self.vs[i]) PyList_Append(points, format_pmesh_vertex(res)) - faces = [format_pmesh_face(self._faces[i]) for i from 0 <= i < self.fcount] + # activation of coloring in jmol + if self.global_texture: + faces = [format_pmesh_face(self._faces[i], 1) + for i from 0 <= i < self.fcount] + else: + faces = [format_pmesh_face(self._faces[i], -1) + for i from 0 <= i < self.fcount] - # If a face has more than 4 vertices, it gets chopped up in format_pmesh_face + # If a face has more than 4 vertices, it gets chopped up in + # format_pmesh_face cdef Py_ssize_t extra_faces = 0 for i from 0 <= i < self.fcount: if self._faces[i].n >= 5: @@ -736,17 +1001,31 @@ cdef class IndexFaceSet(PrimitiveObject): f.write('\n') f.close() - s = 'pmesh %s "%s"\n%s' % (name, filename, self.texture.jmol_str("pmesh")) + if self.global_texture: + s = 'pmesh {} "{}"\n{}'.format(name, filename, + self.texture.jmol_str("pmesh")) + else: + s = 'pmesh {} "{}"'.format(name, filename) # Turn on display of the mesh lines or dots? if render_params.mesh: - s += '\npmesh %s mesh\n'%name + s += '\npmesh %s mesh\n' % name if render_params.dots: - s += '\npmesh %s dots\n'%name + s += '\npmesh %s dots\n' % name return [s] def dual(self, **kwds): + """ + Return the dual. + + EXAMPLES:: + sage: S = cube() + sage: T = S.dual() + sage: len(T.vertex_list()) + 6 + + """ cdef point_c P cdef face_c *face cdef Py_ssize_t i, j, ix, ff @@ -803,37 +1082,47 @@ cdef class IndexFaceSet(PrimitiveObject): return dual - def stickers(self, colors, width, hover): """ - Returns a group of IndexFaceSets + Return a group of IndexFaceSets. INPUT: - colors - list of colors/textures to use (in cyclic order) - width - offset perpendicular into the edge (to create a border) - may also be negative - hover - offset normal to the face (usually have to float above - the original surface so it shows, typically this value - is very small compared to the actual object + + - ``colors`` -- list of colors/textures to use (in cyclic order) + + - ``width`` -- offset perpendicular into the edge (to create a border) + may also be negative + + - ``hover`` -- offset normal to the face (usually have to float above + the original surface so it shows, typically this value is very + small compared to the actual object OUTPUT: - Graphics3dGroup of stickers - EXAMPLE: + Graphics3dGroup of stickers + + EXAMPLE:: + sage: from sage.plot.plot3d.shapes import Box sage: B = Box(.5,.4,.3, color='black') sage: S = B.stickers(['red','yellow','blue'], 0.1, 0.05) sage: S.show() sage: (S+B).show() + """ all = [] - n = self.fcount; ct = len(colors) + n = self.fcount + ct = len(colors) for k in range(len(colors)): if colors[k]: - all.append(self.sticker(range(k,n,ct), width, hover, texture=colors[k])) + all.append(self.sticker(range(k, n, ct), width, hover, + texture=colors[k])) return Graphics3dGroup(all) def sticker(self, face_list, width, hover, **kwds): + """ + Return a sticker on the chosen faces. + """ if not isinstance(face_list, (list, tuple)): face_list = (face_list,) faces = self.face_list() @@ -844,11 +1133,25 @@ cdef class IndexFaceSet(PrimitiveObject): cdef class FaceIter: + """ + A class for iteration over faces + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: len(list(S.faces())) == 6 # indirect doctest + True + """ def __init__(self, face_set): + """ + """ self.set = face_set self.i = 0 + def __iter__(self): return self + def __next__(self): cdef point_c P if self.i >= self.set.fcount: @@ -861,16 +1164,29 @@ cdef class FaceIter: self.i += 1 return face + cdef class EdgeIter: + """ + A class for iteration over edges + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: len(list(S.edges())) == 12 # indirect doctest + True + """ def __init__(self, face_set): self.set = face_set if not self.set.enclosed: - raise TypeError, "Must be closed to use the simple iterator." + raise TypeError("Must be closed to use the simple iterator.") self.i = 0 self.j = 0 self.seen = {} + def __iter__(self): return self + def __next__(self): cdef point_c P, Q cdef face_c face = self.set._faces[self.i] @@ -887,7 +1203,7 @@ cdef class EdgeIter: P = self.set.vs[face.vertices[self.j-1]] Q = self.set.vs[face.vertices[self.j]] self.j += 1 - if self.set.enclosed: # Every edge appears exactly twice, once in each orientation. + if self.set.enclosed: # Every edge appears exactly twice, once in each orientation. if point_c_cmp(P, Q) < 0: return ((P.x, P.y, P.z), (Q.x, Q.y, Q.z)) else: @@ -901,11 +1217,23 @@ cdef class EdgeIter: cdef class VertexIter: + """ + A class for iteration over vertices + + EXAMPLES:: + + sage: from sage.plot.plot3d.shapes import * + sage: S = Box(1,2,3) + sage: len(list(S.vertices())) == 8 # indirect doctest + True + """ def __init__(self, face_set): self.set = face_set self.i = 0 + def __iter__(self): return self + def __next__(self): if self.i >= self.set.vcount: raise StopIteration @@ -913,10 +1241,24 @@ cdef class VertexIter: self.i += 1 return (self.set.vs[self.i-1].x, self.set.vs[self.i-1].y, self.set.vs[self.i-1].z) + def len3d(v): - return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) + """ + Return the norm of a vector in three dimensions. + + EXAMPLES:: + + sage: from sage.plot.plot3d.index_face_set import len3d + sage: len3d((1,2,3)) + 3.7416573867739413 + """ + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) + def sticker(face, width, hover): + """ + Return a sticker over the given face. + """ n = len(face) edges = [] for i from 0 <= i < n: @@ -926,11 +1268,10 @@ def sticker(face, width, hover): sticker = [] for i in range(n): v = -edges[i] - w = edges[i-1] + w = edges[i - 1] N = v.cross_product(w) - lenN = len3d(N) - dv = v*(width*len3d(w)/lenN) - dw = w*(width*len3d(v)/lenN) + lenN = N.norm() + dv = v * (width * w.norm() / lenN) + dw = w * (width * v.norm() / lenN) sticker.append(tuple(vector(RDF, face[i-1]) + dv + dw + N*(hover/lenN))) return sticker - diff --git a/src/sage/plot/plot3d/parametric_plot3d.py b/src/sage/plot/plot3d/parametric_plot3d.py index 07e34c38c1e..1aafa5c317b 100644 --- a/src/sage/plot/plot3d/parametric_plot3d.py +++ b/src/sage/plot/plot3d/parametric_plot3d.py @@ -9,7 +9,9 @@ from sage.ext.fast_eval import fast_float, fast_float_constant -def parametric_plot3d(f, urange, vrange=None, plot_points="automatic", boundary_style=None, **kwds): + +def parametric_plot3d(f, urange, vrange=None, plot_points="automatic", + boundary_style=None, **kwds): r""" Return a parametric three-dimensional space curve or surface. @@ -105,31 +107,59 @@ def parametric_plot3d(f, urange, vrange=None, plot_points="automatic", boundary_ sage: parametric_plot3d(f, (0, 2*pi), (-pi, pi)) Graphics3d Object - #. The surface, but with a mesh: + #. The same surface, but where the defining functions are + symbolic: :: sage: u, v = var('u,v') - sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True) + sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi)) Graphics3d Object - #. The same surface, but where the defining functions are - symbolic: - - :: + The surface, but with a mesh:: sage: u, v = var('u,v') - sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi)) + sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True) Graphics3d Object - We increase the number of plot points, and make the surface green - and transparent: + We increase the number of plot points, and make the surface green + and transparent:: - :: + sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), + ....: color='green', opacity=0.1, plot_points=[30,30]) + Graphics3d Object - sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), color='green', opacity=0.1, plot_points=[30,30]) - Graphics3d Object + One can also color the surface using a coloring function and a colormap:: + + sage: u,v = var('u,v') + sage: def cf(u,v): return sin(u+v/2)**2 + sage: P = parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), + ....: (u, 0, 2*pi), (v, -pi, pi), color=(cf, colormaps.PiYG), plot_points=[60,60]) + sage: P.show(viewer='tachyon') + + Another example, a colored Mobius band:: + + sage: cm = colormaps.ocean + sage: def c(x,y): return sin(x*y)**2 + sage: from sage.plot.plot3d.parametric_surface import MobiusStrip + sage: MobiusStrip(5,1,plot_points=200, color=(c,cm)) + Graphics3d Object + Yet another colored example:: + + sage: from sage.plot.plot3d.parametric_surface import ParametricSurface + sage: cm = colormaps.autumn + sage: def c(x,y): return sin(x*y)**2 + sage: def g(x,y): return x, y+sin(y), x**2 + y**2 + sage: ParametricSurface(g, (srange(-10,10,0.1), srange(-5,5.0,0.1)),color=(c,cm)) + Graphics3d Object + + .. WARNING:: + + This kind of coloring using a colormap can be visualized + using Jmol, Tachyon (option ``viewer='tachyon'``) and + Canvas3D (option ``viewer='canvas3d'`` in the + notebook). We call the space curve function but with polynomials instead of symbolic variables. @@ -158,23 +188,23 @@ def parametric_plot3d(f, urange, vrange=None, plot_points="automatic", boundary_ sage: u, v = var('u,v') sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, pi), (v, 0, pi), - ....: boundary_style={"color": "black", "thickness": 2}) + ....: boundary_style={"color": "black", "thickness": 2}) Graphics3d Object We can plot vectors:: - sage: x,y=var('x,y') + sage: x,y = var('x,y') sage: parametric_plot3d(vector([x-y,x*y,x*cos(y)]), (x,0,2), (y,0,2)) Graphics3d Object - sage: t=var('t') - sage: p=vector([1,2,3]) - sage: q=vector([2,-1,2]) + sage: t = var('t') + sage: p = vector([1,2,3]) + sage: q = vector([2,-1,2]) sage: parametric_plot3d(p*t+q, (t, 0, 2)) Graphics3d Object Any options you would normally use to specify the appearance of a curve are - valid as entries in the boundary_style dict. + valid as entries in the ``boundary_style`` dict. MANY MORE EXAMPLES: @@ -235,7 +265,7 @@ def parametric_plot3d(f, urange, vrange=None, plot_points="automatic", boundary_ sage: parametric_plot3d([fx, fy, fz], (u, -2*pi, 2*pi), (v, 0, pi), plot_points = [90,90], frame=False, color="orange") # long time -- about 30 seconds Graphics3d Object - Maeder's_Owl (pretty but can't find an internet reference):: + Maeder's Owl (pretty but can't find an internet reference):: sage: u, v = var('u,v') sage: fx = v *cos(u) - 0.5* v^2 * cos(2* u) @@ -514,14 +544,14 @@ def parametric_plot3d(f, urange, vrange=None, plot_points="automatic", boundary_ ValueError: range variables should be distinct, but there are duplicates - From Trac #2858:: + From :trac:`2858`:: sage: parametric_plot3d((u,-u,v), (u,-10,10),(v,-10,10)) Graphics3d Object sage: f(u)=u; g(v)=v^2; parametric_plot3d((g,f,f), (-10,10),(-10,10)) Graphics3d Object - From Trac #5368:: + From :trac:`5368`:: sage: x, y = var('x,y') sage: plot3d(x*y^2 - sin(x), (x,-1,1), (y,-1,1)) diff --git a/src/sage/plot/plot3d/parametric_surface.pxd b/src/sage/plot/plot3d/parametric_surface.pxd index 2572ce2da73..ea2cc22d85c 100644 --- a/src/sage/plot/plot3d/parametric_surface.pxd +++ b/src/sage/plot/plot3d/parametric_surface.pxd @@ -4,6 +4,8 @@ from transform cimport point_c, face_c cdef class ParametricSurface(IndexFaceSet): cdef object f cdef object render_grid + cdef object color_function + cdef object colormap cdef int eval_grid(self, urange, vrange) except -1 cdef int eval_c(self, point_c *res, double u, double v) except -1 diff --git a/src/sage/plot/plot3d/parametric_surface.pyx b/src/sage/plot/plot3d/parametric_surface.pyx index ea958357cc0..c6f1e206174 100644 --- a/src/sage/plot/plot3d/parametric_surface.pyx +++ b/src/sage/plot/plot3d/parametric_surface.pyx @@ -25,18 +25,48 @@ EXAMPLES:: False sage: S.show() +By default, the surface is colored with one single color. :: + + sage: P = ParametricSurface(f, (srange(0,10,0.1), srange(-5,5.0,0.1)), + ....: color="red") + sage: P.show() + +One can instead provide a coloring function and a colormap:: + + sage: def f(x,y): return x+y, x-y, x*y + sage: def c(x,y): return sin((x+y)/2)**2 + sage: cm = colormaps.RdYlGn + sage: P = ParametricSurface(f, (srange(-5,5,0.1), srange(-5,5.0,0.1)), color=(c,cm)) + sage: P.show(viewer='tachyon') + +Note that the coloring function should rather have values between 0 and 1. +This value is passed to the chosen colormap. + +Another colored example:: + + sage: colm = colormaps.autumn + sage: def g(x,y): return x, y, x**2 + y**2 + sage: P = ParametricSurface(g, (srange(-10,10,0.1), srange(-5,5.0,0.1)), color=(c,colm)) + sage: P.show(viewer='tachyon') + +.. WARNING:: + + This kind of coloring using a colormap can be visualized using + Jmol, Tachyon (option ``viewer='tachyon'``) and Canvas3D + (option ``viewer='canvas3d'`` in the notebook). + .. NOTE:: One may override ``eval()`` or ``eval_c()`` in a subclass rather than passing in a function for greater speed. One also would want to override get_grid. -TODO: actually remove unused points, fix the below code:: +.. TODO:: - S = ParametricSurface(f=(lambda (x,y):(x,y,0)), domain=(range(10),range(10))) + actually remove unused points, fix the below code:: + S = ParametricSurface(f=(lambda (x,y):(x,y,0)), domain=(range(10),range(10))) """ - #***************************************************************************** # Copyright (C) 2007 Robert Bradshaw # @@ -51,9 +81,6 @@ TODO: actually remove unused points, fix the below code:: # # http://www.gnu.org/licenses/ #***************************************************************************** - - - include "sage/ext/stdsage.pxi" include "sage/ext/interrupt.pxi" @@ -67,7 +94,6 @@ from sage.ext.fast_eval cimport FastDoubleFunc from sage.ext.interpreters.wrapper_rdf cimport Wrapper_rdf from sage.ext.fast_eval import fast_float - cdef inline bint smash_edge(point_c* vs, face_c* f, int a, int b): if point_c_eq(vs[f.vertices[a]], vs[f.vertices[b]]): f.vertices[b] = f.vertices[a] @@ -76,6 +102,7 @@ cdef inline bint smash_edge(point_c* vs, face_c* f, int a, int b): else: return 0 + cdef class ParametricSurface(IndexFaceSet): """ Base class that initializes the ParametricSurface @@ -84,13 +111,18 @@ cdef class ParametricSurface(IndexFaceSet): INPUT: - - ``f`` - (default: None) The defining function. Either a tuple of + - ``f`` - (default: ``None``) The defining function. Either a tuple of three functions, or a single function which returns a tuple, taking - two python floats as input. To subclass, pass None for f and override - eval_c or eval instead. + two python floats as input. To subclass, pass ``None`` for ``f`` and + override ``eval_c`` or ``eval`` instead. - - ``domain`` - (default: None) A tuple of two lists, defining the - grid of `u,v` values. If None, this will be calculate automatically. + - ``domain`` - (default: ``None``) A tuple of two lists, defining the + grid of `u,v` values. If ``None``, this will be calculated automatically. + + - ``color`` - (default: ``None``) A pair `(h,c)` where `h` is + a function with values in `[0,1]` and `c` is a colormap. The + color of a point `p` is then defined as the composition + `c(h(p))` EXAMPLES:: @@ -107,18 +139,27 @@ cdef class ParametricSurface(IndexFaceSet): :: sage: def f(u,v): - ... a = 1 - ... from math import cos, sin, sinh, cosh - ... x = cos(a)*(cos(u)*sinh(v)-cos(3*u)*sinh(3*v)/3) + sin(a)*( - ... sin(u)*cosh(v)-sin(3*u)*cosh(3*v)/3) - ... y = cos(a)*(sin(u)*sinh(v)+sin(3*u)*sinh(3*v)/3) + sin(a)*( - ... -cos(u)*cosh(v)-cos(3*u)*cosh(3*v)/3) - ... z = cos(a)*cos(2*u)*cosh(2*v)+sin(a)*sin(2*u)*sinh(2*v) - ... return (x,y,z) + ....: a = 1 + ....: from math import cos, sin, sinh, cosh + ....: x = cos(a)*(cos(u)*sinh(v)-cos(3*u)*sinh(3*v)/3) + sin(a)*( + ....: sin(u)*cosh(v)-sin(3*u)*cosh(3*v)/3) + ....: y = cos(a)*(sin(u)*sinh(v)+sin(3*u)*sinh(3*v)/3) + sin(a)*( + ....: -cos(u)*cosh(v)-cos(3*u)*cosh(3*v)/3) + ....: z = cos(a)*cos(2*u)*cosh(2*v)+sin(a)*sin(2*u)*sinh(2*v) + ....: return (x,y,z) sage: v = srange(float(0),float((3/2)*pi),float(0.1)) sage: S = ParametricSurface(f, (srange(float(0),float(pi),float(0.1)), - ... srange(float(-1),float(1),float(0.1))), color="blue") + ....: srange(float(-1),float(1),float(0.1))), color="blue") sage: show(S) + + A colored example using the ``color`` keyword:: + + sage: def g(x,y): return x, y, - x**2 + y**2 + sage: def c(x,y): return sin((x-y/2)*y/4)**2 + sage: cm = colormaps.gist_rainbow + sage: P = ParametricSurface(g, (srange(-10,10,0.1), + ....: srange(-5,5.0,0.1)),color=(c,cm)) + sage: P.show(viewer='tachyon') """ def __init__(self, f=None, domain=None, **kwds): @@ -136,11 +177,27 @@ cdef class ParametricSurface(IndexFaceSet): f = tuple(f) self.f = f self.render_grid = domain - IndexFaceSet.__init__(self, [], [], **kwds) + color_data = None + if 'color' in kwds: + try: + if len(kwds['color']) == 2 and callable(kwds['color'][0]): + color_data = kwds['color'] + kwds.pop('color') + except TypeError, AttributeError: + pass + if color_data is None: + # case of a global color + self.color_function = None + IndexFaceSet.__init__(self, [], [], **kwds) + else: + # case of a color depending on parameters + self.color_function = color_data[0] + self.colormap = color_data[1] + IndexFaceSet.__init__(self, [], [], texture_list=[], **kwds) def default_render_params(self): """ - Returns an instance of RenderParams suitable for plotting this object. + Return an instance of RenderParams suitable for plotting this object. TEST:: @@ -152,7 +209,7 @@ cdef class ParametricSurface(IndexFaceSet): def x3d_geometry(self): r""" - Returns XML-like representation of the coordinates of all points + Return XML-like representation of the coordinates of all points in a triangulation of the object along with an indexing of those points. @@ -160,7 +217,7 @@ cdef class ParametricSurface(IndexFaceSet): sage: _ = var('x,y') sage: P = plot3d(x^2-y^2, (x, -2, 2), (y, -2, 2)) - sage: s = P.x3d_str() + sage: s = P.x3d_str() # indirect doctest sage: s[:100] "\n 1: - for file in v: - load(file, globals, attach=attach) - return - - filename = filename.strip() + try: + for f in v: + load(f, globals, attach=attach) + except IOError: + # Splitting the filename didn't work, pretend it + # didn't happen :-) + pass + else: + # Only show deprecation message if the filename + # splitting worked. + from sage.misc.superseded import deprecation + deprecation(17654, 'using multiple filenames separated by spaces as load() argument is dangerous and deprecated') + return + else: + from sage.misc.superseded import deprecation + deprecation(17654, 'using unevaluated expressions as argument to load() is dangerous and deprecated') if filename.lower().startswith(('http://', 'https://')): if attach: @@ -224,34 +250,26 @@ def load(filename, globals, attach=False): # we will do this. # http://www.diveintopython.net/http_web_services/etags.html raise NotImplementedError("you can't attach a URL") - from remote_file import get_remote_file + from sage.misc.remote_file import get_remote_file filename = get_remote_file(filename, verbose=False) - if not is_loadable_filename(filename): - raise ValueError('argument (=%r) to load or attach must have extension py, pyx, sage, spyx, or m' % filename) - - fpath = os.path.expanduser(filename) - if os.path.isabs(fpath): - if not os.path.exists(fpath): - raise IOError('did not find file %r to load or attach' % filename) + from sage.repl.attach import load_attach_path + for path in load_attach_path(): + fpath = os.path.join(path, filename) + fpath = os.path.expanduser(fpath) + if os.path.isfile(fpath): + break else: - from sage.repl.attach import load_attach_path - for path in load_attach_path(): - fpath = os.path.join(path, filename) - fpath = os.path.expanduser(fpath) - if os.path.exists(fpath): - break - else: - raise IOError('did not find file %r in load / attach search path' \ - % filename) + raise IOError('did not find file %r to load or attach' % filename) - if fpath.endswith('.py'): + ext = os.path.splitext(fpath)[1].lower() + if ext == '.py': if attach: add_attached_file(fpath) with open(fpath) as f: code = compile(f.read(), fpath, 'exec') exec(code, globals) - elif fpath.endswith('.sage'): + elif ext == '.sage': from sage.repl.attach import load_attach_mode from sage.repl.preparse import preparse_file_named, preparse_file load_debug_mode, attach_debug_mode = load_attach_mode() @@ -270,17 +288,23 @@ def load(filename, globals, attach=False): if attach: add_attached_file(fpath) exec(preparse_file(open(fpath).read()) + "\n", globals) - elif fpath.endswith('.spyx') or fpath.endswith('.pyx'): + elif ext == '.spyx' or ext == '.pyx': if attach: add_attached_file(fpath) exec(load_cython(fpath), globals) - elif fpath.endswith('.m'): + elif ext == '.f' or ext == '.f90': + from sage.misc.inline_fortran import fortran + with open(fpath) as f: + fortran(f.read(), globals) + elif ext == '.m': # Assume magma for now, though maybe .m is used by maple and # mathematica too, and we should really analyze the file # further. s = globals['magma'].load(fpath) i = s.find('\n'); s = s[i+1:] print(s) + else: + raise ValueError('unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)' % ext) def load_wrap(filename, attach=False): diff --git a/src/sage/repl/preparse.py b/src/sage/repl/preparse.py index 6e5b1e1ac5b..16e33375db7 100644 --- a/src/sage/repl/preparse.py +++ b/src/sage/repl/preparse.py @@ -521,6 +521,14 @@ def parse_ellipsis(code, preparse_step=True): 'for i in (ellipsis_iter(f(x) ,Ellipsis, L[10])):' sage: [1.0..2.0] [1.00000000000000, 2.00000000000000] + + TESTS: + + Check that nested ellipsis is processed correctly (:trac:`17378`):: + + sage: preparse('[1,..,2,..,len([1..3])]') + '(ellipsis_range(Integer(1),Ellipsis,Integer(2),Ellipsis,len((ellipsis_range(Integer(1),Ellipsis,Integer(3))))))' + """ ix = code.find('..') while ix != -1: @@ -534,6 +542,16 @@ def parse_ellipsis(code, preparse_step=True): code = code[:ix] + "Ellipsis" + code[ix+3:] else: start_list, end_list = containing_block(code, ix, ['()','[]']) + + #search the current containing block for other '..' occurrences that may + #be contained in proper subblocks. Those need to be processed before + #we can deal with the present level of ellipses. + ix = code.find('..',ix+2,end_list) + while ix != -1: + if code[ix-1]!='.' and code[ix+2]!='.': + start_list,end_list = containing_block(code,ix,['()','[]']) + ix = code.find('..',ix+2,end_list) + arguments = code[start_list+1:end_list-1].replace('...', ',Ellipsis,').replace('..', ',Ellipsis,') arguments = re.sub(r',\s*,', ',', arguments) if preparse_step: @@ -1491,7 +1509,7 @@ def preparse_file_named(name): Preparse file named \code{name} (presumably a .sage file), outputting to a temporary file. Returns name of temporary file. """ - from sage.misc.misc import tmp_filename + from sage.misc.temporary_file import tmp_filename tmpfilename = tmp_filename(os.path.basename(name)) + '.py' out = open(tmpfilename, 'w') preparse_file_named_to_stream(name, out) diff --git a/src/sage/rings/algebraic_closure_finite_field.py b/src/sage/rings/algebraic_closure_finite_field.py index ad509c9ad97..c8a44f4bbaf 100644 --- a/src/sage/rings/algebraic_closure_finite_field.py +++ b/src/sage/rings/algebraic_closure_finite_field.py @@ -1072,7 +1072,7 @@ def _get_im_gen(self, m, n): """ p = self.characteristic() if m == 1: - return self._subfield(n).one_element() + return self._subfield(n).one() return self._subfield(n).gen() ** ((p**n - 1)//(p**m - 1)) diff --git a/src/sage/rings/all.py b/src/sage/rings/all.py index 35aa1951026..a1eb4491eb0 100644 --- a/src/sage/rings/all.py +++ b/src/sage/rings/all.py @@ -135,9 +135,6 @@ from fraction_field import FractionField Frac = FractionField -# continued fractions -from contfrac import continued_fraction, CFF, ContinuedFractionField - # Arithmetic from arith import algdep, bernoulli, is_prime, is_prime_power, \ is_pseudoprime, is_pseudoprime_small_power, valuation, \ @@ -152,7 +149,6 @@ CRT_vectors, multinomial, multinomial_coefficients, \ kronecker_symbol, kronecker, legendre_symbol, \ primitive_root, nth_prime, quadratic_residues, moebius, \ - farey, continued_fraction_list, convergent, convergents, \ continuant, number_of_divisors, hilbert_symbol, hilbert_conductor, \ hilbert_conductor_inverse, falling_factorial, rising_factorial, \ integer_ceil, integer_floor, \ @@ -161,7 +157,7 @@ sort_complex_numbers_for_display, \ fundamental_discriminant, squarefree_divisors, \ Sigma, radical, Euler_Phi, binomial_coefficients, jacobi_symbol, \ - Moebius, Hirzebruch_Jung_continued_fraction_list, dedekind_sum, \ + Moebius, dedekind_sum, \ prime_factors @@ -183,3 +179,10 @@ from sage.misc.lazy_import import lazy_import lazy_import('sage.rings.invariant_theory', 'invariant_theory') + +# continued fractions +from sage.rings.continued_fraction import (farey, convergents, + continued_fraction, continued_fraction_list, + Hirzebruch_Jung_continued_fraction_list) +# and deprecated continued fractions +from sage.rings.contfrac import (CFF, ContinuedFractionField) diff --git a/src/sage/rings/arith.py b/src/sage/rings/arith.py index 4b46378e7a7..bb58f2c5ecd 100644 --- a/src/sage/rings/arith.py +++ b/src/sage/rings/arith.py @@ -23,7 +23,7 @@ import sage.rings.complex_number import sage.rings.real_mpfr from sage.structure.element import parent -from sage.misc.misc import prod, union +from sage.misc.all import prod, union from sage.rings.real_mpfi import RealIntervalField import fast_arith @@ -1848,32 +1848,28 @@ def xgcd(a, b): r""" Return a triple ``(g,s,t)`` such that `g = s\cdot a+t\cdot b = \gcd(a,b)`. - .. note:: + .. NOTE:: - One exception is if `a` and `b` are not in a PID, e.g., they are - both polynomials over the integers, then this function can't in - general return ``(g,s,t)`` as above, since they need not exist. - Instead, over the integers, we first multiply `g` by a divisor of - the resultant of `a/g` and `b/g`, up to sign. + One exception is if `a` and `b` are not in a principal ideal domain (see + :wikipedia:`Principal_ideal_domain`), e.g., they are both polynomials + over the integers. Then this function can't in general return ``(g,s,t)`` + as above, since they need not exist. Instead, over the integers, we + first multiply `g` by a divisor of the resultant of `a/g` and `b/g`, up + to sign. INPUT: - - - ``a, b`` - integers or univariate polynomials (or - any type with an xgcd method). - + - ``a, b`` - integers or more generally, element of a ring for which the + xgcd make sense (e.g. a field or univariate polynomials). OUTPUT: - ``g, s, t`` - such that `g = s\cdot a + t\cdot b` - - .. note:: + .. NOTE:: There is no guarantee that the returned cofactors (s and t) are - minimal. In the integer case, see - :meth:`sage.rings.integer.Integer._xgcd()` for minimal - cofactors. + minimal. EXAMPLES:: @@ -1881,14 +1877,20 @@ def xgcd(a, b): (4, 4, -5) sage: 4*56 + (-5)*44 4 + sage: g, a, b = xgcd(5/1, 7/1); g, a, b - (1, 1/5, 0) + (1, 3, -2) sage: a*(5/1) + b*(7/1) == g True + sage: x = polygen(QQ) sage: xgcd(x^3 - 1, x^2 - 1) (x - 1, 1, -x) + sage: K. = NumberField(x^2-3) + sage: g.xgcd(g+2) + (1, 1/3*g, 0) + sage: R. = K[] sage: S. = R.fraction_field()[] sage: xgcd(y^2, a*y+b) @@ -1896,8 +1898,8 @@ def xgcd(a, b): sage: xgcd((b+g)*y^2, (a+g)*y+b) (1, (a^2 + (2*g)*a + 3)/(b^3 + (g)*b^2), ((-a + (-g))/b^2)*y + 1/b) - We compute an xgcd over the integers, where the linear combination - is not the gcd but the resultant:: + Here is an example of a xgcd for two polynomials over the integers, where the linear + combination is not the gcd but the gcd multiplied by the resultant:: sage: R. = ZZ[] sage: gcd(2*x*(x-1), x^2) @@ -1911,9 +1913,7 @@ def xgcd(a, b): return a.xgcd(b) except AttributeError: pass - if not isinstance(a, sage.rings.integer.Integer): - a = ZZ(a) - return a.xgcd(ZZ(b)) + return ZZ(a).xgcd(ZZ(b)) XGCD = xgcd @@ -3079,7 +3079,7 @@ def CRT_vectors(X, moduli): if n != len(moduli): raise ValueError("number of moduli must equal length of X") a = CRT_basis(moduli) - modulus = misc.prod(moduli) + modulus = prod(moduli) return [sum([a[i]*X[i][j] for i in range(n)]) % modulus for j in range(len(X[0]))] def binomial(x, m, **kwds): @@ -3264,7 +3264,7 @@ def binomial(x, m, **kwds): P = type(x) if m < 0: return P(0) - return misc.prod([x-i for i in xrange(m)])/factorial(m) + return prod([x-i for i in xrange(m)])/factorial(m) def multinomial(*ks): r""" @@ -3927,428 +3927,9 @@ def range(self, start, stop=None, step=None): moebius = Moebius() -def farey(v, lim): - """ - Return the Farey sequence associated to the floating point number - v. - - INPUT: - - - - ``v`` - float (automatically converted to a float) - - - ``lim`` - maximum denominator. - - - OUTPUT: Results are (numerator, denominator); (1, 0) is "infinity". - - EXAMPLES:: - - sage: farey(2.0, 100) - (2, 1) - sage: farey(2.0, 1000) - (2, 1) - sage: farey(2.1, 1000) - (21, 10) - sage: farey(2.1, 100000) - (21, 10) - sage: farey(pi, 100000) - (312689, 99532) - - AUTHORS: - - - Scott David Daniels: Python Cookbook, 2nd Ed., Recipe 18.13 - """ - v = float(v) - if v < 0: - n, d = farey(-v, lim) - return -n, d - z = lim - lim # Get a "0 of the right type" for denominator - lower, upper = (z, z+1), (z+1, z) - while True: - mediant = (lower[0] + upper[0]), (lower[1] + upper[1]) - if v * mediant[1] > mediant[0]: - if lim < mediant[1]: - return upper - lower = mediant - elif v * mediant[1] == mediant[0]: - if lim >= mediant[1]: - return mediant - if lower[1] < upper[1]: - return lower - return upper - else: - if lim < mediant[1]: - return lower - upper = mediant - - -## def convergents_pnqn(x): -## """ -## Return the pairs (pn,qn) that are the numerators and denominators -## of the partial convergents of the continued fraction of x. We -## include (0,1) and (1,0) at the beginning of the list (these are -## the -2 and -1 th convergents). -## """ -## v = pari(x).contfrac() -## w = [(0,1), (1,0)] -## for n in range(len(v)): -## pn = w[n+1][0]*v[n] + w[n][0] -## qn = w[n+1][1]*v[n] + w[n][1] -## w.append(int(pn), int(qn)) -## return w - -def continued_fraction_list(x, partial_convergents=False, bits=None, nterms=None): - r""" - Returns the continued fraction of x as a list. - - The continued fraction expansion of `x` are the coefficients `a_i` in - - .. math:: - - x = a_1 + 1/(a_2+1/(...) ... ) - - with `a_1` integer and `a_2`, `...` positive integers. - - .. note:: - - This may be slow for real number input, since it's implemented in pure - Python. For rational number input the PARI C library is used. - - .. SEEALSO:: - - :func:`Hirzebruch_Jung_continued_fraction_list` for - Hirzebruch-Jung continued fractions. - - INPUT: - - - ``x`` -- exact rational or floating-point number. The number to - compute the continued fraction of. - - - ``partial_convergents`` -- boolean. Whether to return the partial convergents. - - - ``bits`` -- integer. the precision of the real interval field - that is used internally. - - - ``nterms`` -- integer. The upper bound on the number of terms in - the continued fraction expansion to return. - - OUTPUT: - - A lits of integers, the coefficients in the continued fraction - expansion of ``x``. If ``partial_convergents=True`` is passed, a - pair containing the coefficient list and the partial convergents - list is returned. - - EXAMPLES:: - - sage: continued_fraction_list(45/17) - [2, 1, 1, 1, 5] - sage: continued_fraction_list(e, bits=20) - [2, 1, 2, 1, 1, 4, 1, 1] - sage: continued_fraction_list(e, bits=30) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8] - sage: continued_fraction_list(sqrt(2)) - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] - sage: continued_fraction_list(sqrt(4/19)) - [0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1] - sage: continued_fraction_list(RR(pi), partial_convergents=True) - ([3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3], - [(3, 1), - (22, 7), - (333, 106), - (355, 113), - (103993, 33102), - (104348, 33215), - (208341, 66317), - (312689, 99532), - (833719, 265381), - (1146408, 364913), - (4272943, 1360120), - (5419351, 1725033), - (80143857, 25510582), - (245850922, 78256779)]) - sage: continued_fraction_list(e) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1] - sage: continued_fraction_list(RR(e)) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1] - sage: continued_fraction_list(RealField(200)(e)) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, - 14, 1, 1, 16, 1, 1, 18, 1, 1, 20, 1, 1, 22, 1, 1, 24, 1, 1, - 26, 1, 1, 28, 1, 1, 30, 1, 1, 32, 1, 1, 34, 1, 1, 36, 1, 1, 38, 1, 1] - - TESTS:: - - sage: continued_fraction_list(1 + 10^-10, nterms=3) - [1, 10000000000] - sage: continued_fraction_list(1 + 10^-20 - e^-100, bits=10, nterms=3) - [1, 100000000000000000000, 2688] - sage: continued_fraction_list(1 + 10^-20 - e^-100, bits=10, nterms=5) - [1, 100000000000000000000, 2688, 8, 1] - sage: continued_fraction_list(1 + 10^-20 - e^-100, bits=1000, nterms=5) - [1, 100000000000000000000, 2688, 8, 1] - - Check that :trac:`14858` is fixed:: - - sage: continued_fraction_list(3/4) == continued_fraction_list(SR(3/4)) - True - - """ - if isinstance(x, sage.symbolic.expression.Expression): - try: - x = x.pyobject() - except TypeError: - pass - - if isinstance(x, (integer.Integer, int, long)): - if partial_convergents: - return [x], [(x,1)] - else: - return [x] - - if isinstance(x, sage.rings.rational.Rational): - if bits is not None and nterms is None: - x = RealIntervalField(bits)(x) - else: - # PARI is faster than the pure Python below, but doesn't give us the convergents. - v = pari(x).contfrac().python() - if nterms is not None: - v = v[:nterms] - if partial_convergents: - w = [(0,1), (1,0)] - for a in v: - pn = a*w[-1][0] + w[-2][0] - qn = a*w[-1][1] + w[-2][1] - w.append((pn, qn)) - return v, w[2:] - else: - return v - - # Work in interval field, increasing precision as needed. - if bits is None: - try: - bits = x.prec() - except AttributeError: - bits = 53 - RIF = RealIntervalField(bits) - v = [] - w = [(0,1), (1,0)] - orig, x = x, RIF(x) - - while True: - try: - a = x.unique_floor() - except ValueError: - # Either we're done or we need more precision. - if nterms is None: - break - else: - RIF = RIF.to_prec(2*RIF.prec()) - x = RIF(orig) - for a in v: x = ~(x-a) - continue - if partial_convergents: - pn = a*w[-1][0] + w[-2][0] - qn = a*w[-1][1] + w[-2][1] - w.append((pn, qn)) - v.append(a) - if x == a or nterms is not None and len(v) >= nterms: - break - x = ~(x-a) - - if partial_convergents: - return v, w[2:] - else: - return v - - -def Hirzebruch_Jung_continued_fraction_list(x, bits=None, nterms=None): - r""" - Return the Hirzebruch-Jung continued fraction of ``x`` as a list. - - The Hirzebruch-Jung continued fraction of `x` is similar to the - ordinary continued fraction expansion, but with minus signs. That - is, the coefficients `a_i` in - - .. math:: - - x = a_1 - 1/(a_2-1/(...) ... ) - - with `a_1` integer and `a_2`, `...` positive integers. - - .. SEEALSO:: - - :func:`continued_fraction_list` for ordinary continued fractions. - - INPUT: - - - ``x`` -- exact rational or something that can be numerically - evaluated. The number to compute the continued fraction of. - - - ``bits`` -- integer (default: the precision of ``x``). the - precision of the real interval field that is used - internally. This is only used if ``x`` is not an exact fraction. - - - ``nterms`` -- integer (default: None). The upper bound on the - number of terms in the continued fraction expansion to return. - - OUTPUT: - - A lits of integers, the coefficients in the Hirzebruch-Jung continued - fraction expansion of ``x``. - - EXAMPLES:: - - sage: Hirzebruch_Jung_continued_fraction_list(17/11) - [2, 3, 2, 2, 2, 2] - sage: Hirzebruch_Jung_continued_fraction_list(45/17) - [3, 3, 6] - sage: Hirzebruch_Jung_continued_fraction_list(e, bits=20) - [3, 4, 3, 2, 2, 2, 3, 7] - sage: Hirzebruch_Jung_continued_fraction_list(e, bits=30) - [3, 4, 3, 2, 2, 2, 3, 8, 3, 2, 2, 2, 2, 2, 2, 2, 3] - sage: Hirzebruch_Jung_continued_fraction_list(sqrt(2), bits=100) - [2, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, - 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 2] - sage: Hirzebruch_Jung_continued_fraction_list(sqrt(4/19)) - [1, 2, 7, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 3, 7, - 2, 2, 2, 7, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] - sage: Hirzebruch_Jung_continued_fraction_list(pi) - [4, 2, 2, 2, 2, 2, 2, 17, 294, 3, 4, 5, 16, 2, 2] - sage: Hirzebruch_Jung_continued_fraction_list(e) - [3, 4, 3, 2, 2, 2, 3, 8, 3, 2, 2, 2, 2, 2, 2, 2, - 3, 12, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 10] - sage: Hirzebruch_Jung_continued_fraction_list(e, nterms=20) - [3, 4, 3, 2, 2, 2, 3, 8, 3, 2, 2, 2, 2, 2, 2, 2, 3, 12, 3, 2] - sage: len(_) == 20 - True - - TESTS:: - - sage: Hirzebruch_Jung_continued_fraction_list(1 - 10^-10, nterms=3) - [1, 10000000000] - sage: Hirzebruch_Jung_continued_fraction_list(1 - 10^-10 - e^-100, bits=100, nterms=5) - [1, 10000000000] - sage: Hirzebruch_Jung_continued_fraction_list(1 - 10^-20 - e^-100, bits=1000, nterms=5) - [1, 100000000000000000000, 2689, 2, 2] - """ - if not isinstance(x, sage.rings.rational.Rational): - try: - x = QQ(x) - except TypeError: - # Numerically evaluate x - if bits is None: - try: - bits = x.prec() - except AttributeError: - bits = 53 - x = QQ(x.n(bits)) - v = [] - while True: - div, mod = divmod(x.numerator(), x.denominator()) - if mod == 0: - v.append(div) - break - v.append(div+1) - if nterms is not None and len(v) >= nterms: - break - x = 1/(div+1-x) - return v - - -def convergent(v, n): - r""" - Return the n-th continued fraction convergent of the continued - fraction defined by the sequence of integers v. We assume - `n \geq 0`. - - INPUT: - - - - ``v`` - list of integers - - - ``n`` - integer - - - OUTPUT: a rational number - - If the continued fraction integers are - - .. math:: - - v = [a_0, a_1, a_2, \ldots, a_k] - - - then ``convergent(v,2)`` is the rational number - - .. math:: - - a_0 + 1/a_1 - - and ``convergent(v,k)`` is the rational number - - .. math:: - - a1 + 1/(a2+1/(...) ... ) - - represented by the continued fraction. - - EXAMPLES:: - - sage: convergent([2, 1, 2, 1, 1, 4, 1, 1], 7) - 193/71 - """ - if hasattr(v, 'convergent'): - return v.convergent(n) - i = int(n) - x = QQ(v[i]) - i -= 1 - while i >= 0: - x = QQ(v[i]) + 1/x - i -= 1 - return x - - -def convergents(v): - """ - Return all the partial convergents of a continued fraction defined - by the sequence of integers v. - - If v is not a list, compute the continued fraction of v and return - its convergents (this is potentially much faster than calling - continued_fraction first, since continued fractions are - implemented using PARI and there is overhead moving the answer back - from PARI). - - INPUT: - - - - ``v`` - list of integers or a rational number - - - OUTPUT: - - - - ``list`` - of partial convergents, as rational - numbers - - - EXAMPLES:: - - sage: convergents([2, 1, 2, 1, 1, 4, 1, 1]) - [2, 3, 8/3, 11/4, 19/7, 87/32, 106/39, 193/71] - """ - if hasattr(v, 'convergents'): - return v.convergents() - if not isinstance(v, list): - v = pari(v).contfrac() - w = [(0,1), (1,0)] - for n in range(len(v)): - pn = w[n+1][0]*v[n] + w[n][0] - qn = w[n+1][1]*v[n] + w[n][1] - w.append((pn, qn)) - return [QQ(x) for x in w[2:]] +## Note: farey, convergent, continued_fraction_list and convergents have been moved to +## sage.rings.continued_fraction ## def continuant(v, n=None): ## """ @@ -4395,7 +3976,7 @@ def continuant(v, n=None): sage: q = continuant([1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10]) sage: p/q 517656/190435 - sage: convergent([2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10],14) + sage: continued_fraction([2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10]).convergent(14) 517656/190435 sage: x = PolynomialRing(RationalField(),'x',5).gens() sage: continuant(x) @@ -4772,7 +4353,7 @@ def falling_factorial(x, a): if (isinstance(a, (integer.Integer, int, long)) or (isinstance(a, sage.symbolic.expression.Expression) and a.is_integer())) and a >= 0: - return misc.prod([(x - i) for i in range(a)], z=x.parent()(1)) + return prod([(x - i) for i in range(a)], z=x.parent()(1)) from sage.functions.all import gamma return gamma(x+1) / gamma(x-a+1) @@ -4860,7 +4441,7 @@ def rising_factorial(x, a): if (isinstance(a, (integer.Integer, int, long)) or (isinstance(a, sage.symbolic.expression.Expression) and a.is_integer())) and a >= 0: - return misc.prod([(x + i) for i in range(a)], z=x.parent()(1)) + return prod([(x + i) for i in range(a)], z=x.parent()(1)) from sage.functions.all import gamma return gamma(x+a) / gamma(x) diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 9d7a2bc3828..4b412061c51 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -232,7 +232,7 @@ cdef class ComplexDoubleField_class(sage.rings.ring.Field): cdef ComplexDoubleElement z cdef double imag = (ymax-ymin)*rstate.c_rand_double() + ymin cdef double real = (xmax-xmin)*rstate.c_rand_double() + xmin - z = PY_NEW(ComplexDoubleElement) + z = ComplexDoubleElement.__new__(ComplexDoubleElement) z._complex = gsl_complex_rect(real, imag) return z @@ -666,7 +666,7 @@ cdef ComplexDoubleElement new_ComplexDoubleElement(): Creates a new (empty) :class:`ComplexDoubleElement`. """ cdef ComplexDoubleElement z - z = PY_NEW(ComplexDoubleElement) + z = ComplexDoubleElement.__new__(ComplexDoubleElement) return z def is_ComplexDoubleElement(x): @@ -707,7 +707,7 @@ cdef inline ComplexDoubleElement pari_to_cdf(pari_gen g): ... PariError: incorrect type in gtofp (t_POL) """ - cdef ComplexDoubleElement z = PY_NEW(ComplexDoubleElement) + cdef ComplexDoubleElement z = ComplexDoubleElement.__new__(ComplexDoubleElement) pari_catch_sig_on() if typ(g.g) == t_COMPLEX: z._complex = gsl_complex_rect(gtodouble(gel(g.g, 1)), gtodouble(gel(g.g, 2))) @@ -768,7 +768,7 @@ cdef class ComplexDoubleElement(FieldElement): C-level code for creating a :class:`ComplexDoubleElement` from a ``gsl_complex``. """ - cdef ComplexDoubleElement z = PY_NEW(ComplexDoubleElement) + cdef ComplexDoubleElement z = ComplexDoubleElement.__new__(ComplexDoubleElement) z._complex = x return z @@ -1450,21 +1450,6 @@ cdef class ComplexDoubleElement(FieldElement): imag_part = imag - def parent(self): - """ - Return the complex double field, which is the parent of ``self``. - - EXAMPLES:: - - sage: a = CDF(2,3) - sage: a.parent() - Complex Double Field - sage: parent(a) - Complex Double Field - """ - return CDF - - ####################################################################### # Elementary Complex Functions ####################################################################### @@ -2485,7 +2470,7 @@ cdef class FloatToCDF(Morphism): sage: CDF(2+i) # indirect doctest 2.0 + 1.0*I """ - cdef ComplexDoubleElement z = PY_NEW(ComplexDoubleElement) + cdef ComplexDoubleElement z = ComplexDoubleElement.__new__(ComplexDoubleElement) z._complex = gsl_complex_rect(x, 0) return z @@ -2567,7 +2552,7 @@ cdef ComplexDoubleElement ComplexDoubleElement_from_doubles(double re, double im Create a new :class:`ComplexDoubleElement` with the specified real and imaginary parts. """ - cdef ComplexDoubleElement z = PY_NEW(ComplexDoubleElement) + cdef ComplexDoubleElement z = ComplexDoubleElement.__new__(ComplexDoubleElement) z._complex.dat[0] = re z._complex.dat[1] = im return z diff --git a/src/sage/rings/complex_field.py b/src/sage/rings/complex_field.py index 63237f13980..55d039d0ae9 100644 --- a/src/sage/rings/complex_field.py +++ b/src/sage/rings/complex_field.py @@ -344,7 +344,7 @@ def __call__(self, x=None, im=None): Complex Field with 53 bits of precision """ if x is None: - return self.zero_element() + return self.zero() # we leave this here to handle the imaginary parameter if im is not None: x = x, im diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index 7b07597df4d..6300ec729c4 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -86,7 +86,7 @@ cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): same parent as ``self``. """ cdef ComplexIntervalFieldElement x - x = PY_NEW(ComplexIntervalFieldElement) + x = ComplexIntervalFieldElement.__new__(ComplexIntervalFieldElement) x._parent = self._parent x._prec = self._prec mpfi_init2(x.__re, self._prec) diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 9a59b7adb25..3e913424941 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -321,7 +321,7 @@ cdef class MPComplexField_class(sage.rings.ring.Field): Return a new complex number with parent ``self`. """ cdef MPComplexNumber z - z = PY_NEW(MPComplexNumber) + z = MPComplexNumber.__new__(MPComplexNumber) z._parent = self mpc_init2(z.value, self.__prec) z.init = 1 @@ -371,7 +371,7 @@ cdef class MPComplexField_class(sage.rings.ring.Field): 2.00000000000000 + 3.00000000000000*I """ if x is None: - return self.zero_element() + return self.zero() # We implement __call__ to gracefully accept the second argument. if im is not None: x = x, im @@ -709,7 +709,7 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): Return a new complex number with same parent as ``self``. """ cdef MPComplexNumber z - z = PY_NEW(MPComplexNumber) + z = MPComplexNumber.__new__(MPComplexNumber) z._parent = self._parent mpc_init2(z.value, (self._parent).__prec) z.init = 1 @@ -1021,19 +1021,6 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): mpfr_set (y.value, self.value.im, (y._parent).rnd) return y - def parent(self): - """ - Return the complex field containing the number. - - EXAMPLES:: - - sage: C = MPComplexField() - sage: a = C(1.2456, 987.654) - sage: a.parent() - Complex Field with 53 bits of precision - """ - return self._parent - def str(self, int base=10, int truncate=True): """ Return a string of ``self``. diff --git a/src/sage/rings/complex_number.pyx b/src/sage/rings/complex_number.pyx index 597bed321a9..fb3d1f4805f 100644 --- a/src/sage/rings/complex_number.pyx +++ b/src/sage/rings/complex_number.pyx @@ -121,7 +121,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): parent as ``self``. """ cdef ComplexNumber x - x = PY_NEW(ComplexNumber) + x = ComplexNumber.__new__(ComplexNumber) x._parent = self._parent x._prec = self._prec x._multiplicative_order = None @@ -2598,7 +2598,7 @@ cdef class CCtoCDF(Map): sage: f(exp(pi*CC.0/4)) 0.7071067811865476 + 0.7071067811865475*I """ - cdef ComplexDoubleElement z = PY_NEW(ComplexDoubleElement) + cdef ComplexDoubleElement z = ComplexDoubleElement.__new__(ComplexDoubleElement) z._complex.dat[0] = mpfr_get_d((x).__re, GMP_RNDN) z._complex.dat[1] = mpfr_get_d((x).__im, GMP_RNDN) return z diff --git a/src/sage/rings/contfrac.py b/src/sage/rings/contfrac.py index cfd8a42a343..101e55c5a67 100644 --- a/src/sage/rings/contfrac.py +++ b/src/sage/rings/contfrac.py @@ -1,310 +1,214 @@ r""" -Continued Fractions +Continued fraction field Sage implements the field ``ContinuedFractionField`` (or ``CFF`` -for short) of finite simple continued fractions. This is really +for short) of finite simple continued fractions. This is really isomorphic to the field `\QQ` of rational numbers, but with different printing and semantics. It should be possible to use this field in -most cases where one could use `\QQ`, except arithmetic is slower. - -The ``continued_fraction(x)`` command returns an element of -``CFF`` that defines a continued fraction expansion to `x`. The -command ``continued_fraction(x,bits)`` computes the continued -fraction expansion of an approximation to `x` with given bits of -precision. Use ``show(c)`` to see a continued fraction nicely -typeset, and ``latex(c)`` to obtain the typeset version, e.g., for -inclusion in a paper. - -EXAMPLES: -We create some example elements of the continued fraction field:: - - sage: c = continued_fraction([1,2]); c - [1, 2] - sage: c = continued_fraction([3,7,15,1,292]); c - [3, 7, 15, 1, 292] - sage: c = continued_fraction(pi); c - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: c.value() - 80143857/25510582 - sage: QQ(c) - 80143857/25510582 - sage: RealField(200)(QQ(c) - pi) - -5.7908701643756732744264903067012149647564522968979302505514e-16 - -We can also create matrices, polynomials, vectors, etc., over the continued -fraction field. - -:: +most cases where one could use `\QQ`, except arithmetic is *much* slower. + +EXAMPLES:: + +We can create matrices, polynomials, vectors, etc., over the continued fraction +field:: sage: a = random_matrix(CFF, 4) sage: a - [ [-1, 2] [-1, 1, 94] [0, 2] [-12]] - [ [-1] [0, 2] [-1, 1, 3] [0, 1, 2]] - [ [-3, 2] [0] [0, 1, 2] [-1]] - [ [1] [-1] [0, 3] [1]] + [ [-1; 2] [-1; 1, 94] [0; 2] [-12]] + [ [-1] [0; 2] [-1; 1, 3] [0; 1, 2]] + [ [-3; 2] [0] [0; 1, 2] [-1]] + [ [1] [-1] [0; 3] [1]] sage: f = a.charpoly() sage: f - [1]*x^4 + ([-2, 3])*x^3 + [14, 1, 1, 1, 9, 1, 8]*x^2 + ([-13, 4, 1, 2, 1, 1, 1, 1, 1, 2, 2])*x + [-6, 1, 5, 9, 1, 5] + [1]*x^4 + ([-2; 3])*x^3 + [14; 1, 1, 1, 9, 1, 8]*x^2 + ([-13; 4, 1, 2, 1, 1, 1, 1, 1, 2, 2])*x + [-6; 1, 5, 9, 1, 5] sage: f(a) [[0] [0] [0] [0]] [[0] [0] [0] [0]] [[0] [0] [0] [0]] [[0] [0] [0] [0]] sage: vector(CFF, [1/2, 2/3, 3/4, 4/5]) - ([0, 2], [0, 1, 2], [0, 1, 3], [0, 1, 4]) + ([0; 2], [0; 1, 2], [0; 1, 3], [0; 1, 4]) AUTHORS: -- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``. - +- Niles Johnson (2010-08): ``random_element()`` should pass on ``*args`` and + ``**kwds`` (:trac:`3893`). """ -from sage.structure.element import FieldElement -from sage.structure.parent_gens import ParentWithGens -from sage.libs.pari.all import pari -from field import Field -from rational_field import QQ -from integer_ring import ZZ -from infinity import infinity -from real_mpfr import is_RealNumber, RealField -from real_double import RDF -from arith import (continued_fraction_list, - convergent, convergents) +from sage.structure.unique_representation import UniqueRepresentation +from sage.rings.ring import Field +from sage.structure.element import FieldElement +from continued_fraction import ContinuedFraction_periodic, ZZ_0 -class ContinuedFractionField_class(Field): +class ContinuedFractionField(UniqueRepresentation,Field): """ - The field of all finite continued fraction of real numbers. + The field of rational implemented as continued fraction. + + The code here is deprecated since in all situations it is better to use + ``QQ``. + + .. SEEALSO:: + + :func:`continued_fraction` EXAMPLES:: sage: CFF - Field of all continued fractions + QQ as continued fractions + sage: CFF([0,1,3,2]) + [0; 1, 3, 2] + sage: CFF(133/25) + [5; 3, 8] + + sage: CFF.category() + Category of fields The continued fraction field inherits from the base class - :class:`sage.rings.ring.Field`. However it was initialised - as such only since trac ticket #11900:: + :class:`sage.rings.ring.Field`. However it was initialised as such only + since trac ticket :trac:`11900`:: sage: CFF.category() Category of fields - """ - def __init__(self): - """ - EXAMPLES:: - - sage: ContinuedFractionField() - Field of all continued fractions - - TESTS:: - - sage: CFF._repr_option('element_is_atomic') - False - """ - Field.__init__(self, self) - self._assign_names(('x'),normalize=False) + class Element(ContinuedFraction_periodic,FieldElement): + r""" + A continued fraction of a rational number. - def __cmp__(self, right): - """ EXAMPLES:: - sage: CFF == ContinuedFractionField() - True - sage: CFF == CDF - False - sage: loads(dumps(CFF)) == CFF - True + sage: CFF(1/3) + [0; 3] + sage: CFF([1,2,3]) + [1; 2, 3] """ - return cmp(type(self), type(right)) + def __init__(self, x1, x2=None): + r""" + INPUT: - def __iter__(self): - """ - EXAMPLES:: + - ``parent`` - the parent - sage: i = 0 - sage: for a in CFF: - ... print a - ... i += 1 - ... if i > 5: break - ... - [0] - [1] - [-1] - [0, 2] - [-1, 2] - [2] - """ - for n in QQ: - yield self(n) + - ``x`` - the quotients of the continued fraction + TESTS:: - def _latex_(self): - r""" - EXAMPLES:: + sage: TestSuite(CFF.an_element()).run() + """ + ContinuedFraction_periodic.__init__(self, x1) + FieldElement.__init__(self, parent=CFF) - sage: latex(CFF) - \Bold{CFF} - """ - return "\\Bold{CFF}" + def _add_(self, other): + r""" + Add two continued fractions. - def _is_valid_homomorphism_(self, codomain, im_gens): - """ - Return whether or not the map to codomain by sending the - continued fraction [1] of self to im_gens[0] is a - homomorphism. + EXAMPLES:: - EXAMPLES:: + sage: CFF(1/3) + CFF([0,1,2,3]) + [1; 30] + """ + return self.parent()(self.value() + other.value()) - sage: CFF._is_valid_homomorphism_(ZZ,[ZZ(1)]) - False - sage: CFF._is_valid_homomorphism_(CFF,[CFF(1)]) - True - """ - try: - return im_gens[0] == codomain._coerce_(self(1)) - except TypeError: - return False + def _mul_(self, other): + r""" + Multiply two continued fractions. - def _repr_(self): - """ - EXAMPLES:: + EXAMPLES:: - sage: CFF - Field of all continued fractions - """ - return "Field of all continued fractions" + sage: CFF(1/3) * CFF([0,1,2,3]) + [0; 4, 3, 2] + """ + return self.parent()(self.value() * other.value()) - def _coerce_impl(self, x): - """ - Anything that implicitly coerces to the rationals or a real - field, implicitly coerces to the continued fraction field. - - EXAMPLES: - - The additions below call _coerce_impl implicitly:: - - sage: a = CFF(3/5); a - [0, 1, 1, 2] - sage: a + 2/5 - [1] - sage: 2/5 + a - [1] - sage: 1.5 + a - [2, 10] - sage: a + 1.5 - [2, 10] - """ - if is_RealNumber(x): - return self(x) - return self._coerce_try(x, [QQ, RDF]) + def _div_(self, other): + r""" + Divides two continued fractions. - def __call__(self, x, bits=None, nterms=None): - """ - INPUT: + EXAMPLES:: - - `x` -- a number + sage: CFF(1/3) / CFF(4/5) + [0; 2, 2, 2] + """ + return self.parent()(self.value() / other.value()) - - ``bits`` -- integer (optional) the number of bits of the - input number to use when computing the continued fraction. + def __reduce__(self): + r""" + Pickling helper. - EXAMPLES:: + EXAMPLES:: - sage: CFF(1.5) - [1, 2] - sage: CFF(e) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1] - sage: CFF(pi) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: CFF([1,2,3]) - [1, 2, 3] - sage: CFF(15/17) - [0, 1, 7, 2] - sage: c2 = loads(dumps(CFF)) - sage: c2(CFF(15/17)).parent() is c2 - True + sage: x = CFF(1/3) + sage: loads(dumps(x)) == x + True + """ + return (self.parent(), (self.value(),)) - We illustrate varying the bits parameter:: - - sage: CFF(pi) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: CFF(pi, bits=20) - [3, 7] - sage: CFF(pi, bits=80) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, 1] - sage: CFF(pi, bits=100) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, 1, 84, 2, 1, 1, 15, 3] - - And varying the nterms parameter:: - - sage: CFF(pi, nterms=3) - [3, 7, 15] - sage: CFF(pi, nterms=10) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1] - sage: CFF(pi, bits=10, nterms=10) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1] - """ - return ContinuedFraction(self, x, bits, nterms) + def __init__(self): + r""" + TESTS:: - def __len__(self): + sage: TestSuite(CFF(1/3)).run() + sage: TestSuite(CFF([1,2,3])).run() """ + Field.__init__(self, self) + + def _latex_(self): + r""" EXAMPLES:: - sage: len(CFF) - Traceback (most recent call last): - ... - TypeError: len() of unsized object + sage: latex(CFF) + \Bold{CFF} """ - raise TypeError('len() of unsized object') + return "\\Bold{CFF}" - def gens(self): + def _repr_(self): """ EXAMPLES:: - sage: CFF.gens() - ([1],) + sage: CFF + QQ as continued fractions """ - return (self(1), ) + return "QQ as continued fractions" + + def an_element(self): + r""" + Returns a continued fraction. - def gen(self, n=0): - """ EXAMPLES:: - sage: CFF.gen() - [1] - sage: CFF.0 - [1] + sage: CFF.an_element() + [-1; 2, 3] """ + return self([-1,2,3]) - if n == 0: - return self(1) - else: - raise IndexError("n must be 0") + def some_elements(self): + r""" + Return some continued fractions. - def degree(self): - """ EXAMPLES:: - sage: CFF.degree() - 1 + sage: CFF.some_elements() + ([0], [1], [1], [-1; 2], [3; 1, 2, 3]) """ - return 1 + return (self([0]), self([1]), self([0,1]), self([-1,2]), self([3,1,2,3])) - def ngens(self): + def is_field(self, proof=True): """ + Return True. + EXAMPLES:: - sage: CFF.ngens() - 1 + sage: CFF.is_field() + True """ - return 1 + return True - def is_field(self, proof = True): - """ - Return True, since the continued fraction field is a field. + def is_exact(self): + r""" + Return True. EXAMPLES:: - sage: CFF.is_field() + sage: CFF.is_exact() True """ return True @@ -331,7 +235,7 @@ def characteristic(self): sage: parent(c) Integer Ring """ - return ZZ(0) + return ZZ_0 def order(self): """ @@ -340,706 +244,74 @@ def order(self): sage: CFF.order() +Infinity """ - return infinity + from sage.rings.infinity import Infinity + return Infinity def random_element(self, *args, **kwds): """ - EXAMPLES:: - - sage: CFF.random_element(10,10) - [0, 4] - - Passes extra positional or keyword arguments through:: - - sage: [CFF.random_element(den_bound=10, num_bound=2) for x in range(4)] - [[-1, 1, 3], [0, 7], [0, 3], [0, 4]] - - - - """ - return self(QQ.random_element(*args, **kwds)) - - -class ContinuedFraction(FieldElement): - """ - A continued fraction object. - - EXAMPLES:: - - sage: continued_fraction(pi) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: CFF(pi) - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - """ - def __init__(self, parent, x, bits=None, nterms=None): - """ - EXAMPLES:: - - sage: sage.rings.contfrac.ContinuedFraction(CFF,[1,2,3,4,1,2]) - [1, 2, 3, 4, 1, 2] - sage: sage.rings.contfrac.ContinuedFraction(CFF,[1,2,3,4,-1,2]) - Traceback (most recent call last): - ... - ValueError: each entry except the first must be positive - """ - FieldElement.__init__(self, parent) - if isinstance(x, ContinuedFraction): - self._x = list(x._x) - elif isinstance(x, (list, tuple)): - x = [ZZ(a) for a in x] - for i in range(1,len(x)): - if x[i] <= 0: - raise ValueError("each entry except the first must be positive") - self._x = list(x) - else: - self._x = [ZZ(a) for a in continued_fraction_list(x, bits=bits, nterms=nterms)] - - def __getitem__(self, n): - """ - Returns `n`-th term of the continued fraction. - - OUTPUT: - - an integer or a a continued fraction - - EXAMPLES:: - - sage: a = continued_fraction(pi); a - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: a[4] - 292 - sage: a[-1] - 14 - sage: a[2:5] - [15, 1, 292] - sage: a[:3] - [3, 7, 15] - sage: a[4:] - [292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: a[4::2] - [292, 1, 2, 3, 14] - """ - if isinstance(n, slice): - start, stop, step = n.indices(len(self)) - return ContinuedFraction(self.parent(), self._x[start:stop:step]) - else: - return self._x[n] - - def _repr_(self): - """ - EXAMPLES:: - - sage: a = continued_fraction(pi); a - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: a.rename('continued fraction of pi') - sage: a - continued fraction of pi - """ - return str(self._x) - - def convergents(self): - """ - Return a list of rational numbers, which are the partial - convergents of this continued fraction. - - OUTPUT: - - - list of rational numbers - - EXAMPLES:: - - sage: a = CFF(pi, bits=34); a - [3, 7, 15, 1, 292] - sage: a.convergents() - [3, 22/7, 333/106, 355/113, 103993/33102] - sage: a.value() - 103993/33102 - sage: a[:-1].value() - 355/113 - """ - return convergents(self._x) - - def convergent(self, n): - """ - Return the `n`-th partial convergent to self. - - OUTPUT: - - rational number - - EXAMPLES:: - - sage: a = CFF(pi, bits=34); a - [3, 7, 15, 1, 292] - sage: a.convergents() - [3, 22/7, 333/106, 355/113, 103993/33102] - sage: a.convergent(0) - 3 - sage: a.convergent(1) - 22/7 - sage: a.convergent(4) - 103993/33102 - """ - return convergent(self._x, n) - - def __len__(self): - """ - Return the number of terms in this continued fraction. - - EXAMPLES:: - - sage: len(continued_fraction([1,2,3,4,5]) ) - 5 - """ - return len(self._x) - - def pn(self, n): - """ - Return the numerator of the `n`-th partial convergent, computed - using the recurrence. - - EXAMPLES:: - - sage: c = continued_fraction(pi); c - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: c.pn(0), c.qn(0) - (3, 1) - sage: len(c) - 13 - sage: c.pn(12), c.qn(12) - (80143857, 25510582) - """ - if n < -2: - raise ValueError("n must be at least -2") - if n > len(self._x): - raise ValueError("n must be at most %s"%len(self._x)) - try: - return self.__pn[n+2] - except AttributeError: - self.__pn = [0, 1, self._x[0]] - self.__qn = [1, 0, 1] - except IndexError: - pass - for k in range(len(self.__pn), n+3): - self.__pn.append(self._x[k-2]*self.__pn[k-1] + self.__pn[k-2]) - self.__qn.append(self._x[k-2]*self.__qn[k-1] + self.__qn[k-2]) - return self.__pn[n+2] - - def qn(self, n): - """ - Return the denominator of the `n`-th partial convergent, computed - using the recurrence. - - EXAMPLES:: - - sage: c = continued_fraction(pi); c - [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] - sage: c.qn(0), c.pn(0) - (1, 3) - sage: len(c) - 13 - sage: c.pn(12), c.qn(12) - (80143857, 25510582) - """ - if n < -2: - raise ValueError("n must be at least -2") - if n > len(self._x): - raise ValueError("n must be at most %s"%len(self._x)) - try: - return self.__qn[n+2] - except (AttributeError, IndexError): - pass - self.pn(n) - return self.__qn[n+2] - - def _rational_(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: a._rational_() - -17/389 - sage: QQ(a) - -17/389 - """ - try: - return self.__rational - except AttributeError: - r = convergents(self._x)[-1] - self.__rational =r - return r - - def value(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: a.value() - -17/389 - sage: QQ(a) - -17/389 - """ - return self._rational_() - - def numerator(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: a.numerator() - -17 - """ - return self._rational_().numerator() - - def denominator(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: a.denominator() - 389 - """ - return self._rational_().denominator() - - def __int__(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: int(a) - -1 - """ - return int(self._rational_()) - - def __long__(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: long(a) - -1L - """ - return long(self._rational_()) - - def __float__(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: float(a) - -0.043701799485861184 - """ - return float(self._rational_()) - - def _add_(self, right): - """ - EXAMPLES:: - - sage: a = CFF(-17/389) - sage: b = CFF(1/389) - sage: c = a+b; c - [-1, 1, 23, 3, 5] - sage: c.value() - -16/389 - """ - return ContinuedFraction(self.parent(), - self._rational_() + right._rational_()) - - def _sub_(self, right): - """ - EXAMPLES:: - - sage: a = CFF(-17/389) - sage: b = CFF(1/389) - sage: c = a - b; c - [-1, 1, 20, 1, 1, 1, 1, 3] - sage: c.value() - -18/389 - """ - return ContinuedFraction(self.parent(), - self._rational_() - right._rational_()) - - def _mul_(self, right): - """ - EXAMPLES:: - - sage: a = CFF(-17/389) - sage: b = CFF(1/389) - sage: c = a * b; c - [-1, 1, 8900, 4, 4] - sage: c.value(), (-1/389)*(17/389) - (-17/151321, -17/151321) - """ - return ContinuedFraction(self.parent(), - self._rational_() * right._rational_()) - - def _div_(self, right): - """ - EXAMPLES:: - - sage: a = CFF(-17/389) - sage: b = CFF(1/389) - sage: c = a / b; c - [-17] - sage: c.value(), (17/389) / (-1/389) - (-17, -17) - """ - return ContinuedFraction(self.parent(), - self._rational_() / right._rational_()) - - def __cmp__(self, right): - """ - EXAMPLES:: - - sage: a = CFF(-17/389) - sage: b = CFF(1/389) - sage: a < b - True - sage: QQ(a) < QQ(b) - True - sage: QQ(a) - -17/389 - sage: QQ(b) - 1/389 - """ - return cmp(self._rational_(), right._rational_()) - - def _latex_(self): - """ - EXAMPLES:: - - sage: a = CFF(-17/389) - sage: latex(a) - -1+ \frac{\displaystyle 1}{\displaystyle 1+ \frac{\displaystyle 1}{\displaystyle 21+ \frac{\displaystyle 1}{\displaystyle 1+ \frac{\displaystyle 1}{\displaystyle 7+ \frac{\displaystyle 1}{\displaystyle 2}}}}} - """ - v = self._x - if len(v) == 0: - return '0' - s = str(v[0]) - for i in range(1,len(v)): - s += '+ \\frac{\\displaystyle 1}{\\displaystyle %s'%v[i] - s += '}'*(len(v)-1) - return s - - def sqrt(self, prec=53, all=False): - """ - Return continued fraction approximation to square root of the - value of this continued fraction. + Return a somewhat random continued fraction (the result is either + finite or ultimately periodic). INPUT: - - `prec` -- integer (default: 53) precision of square root - that is approximated - - - `all` -- bool (default: False); if True, return all square - roots of self, instead of just one. - - EXAMPLES:: - - sage: a = CFF(4/19); a - [0, 4, 1, 3] - sage: b = a.sqrt(); b - [0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1] - sage: b.value() - 4508361/9825745 - sage: float(b.value()^2 - a) - -5.451492525672688e-16 - sage: b = a.sqrt(prec=100); b - [0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5] - sage: b^2 - [0, 4, 1, 3, 7849253184229368265220252099, 1, 3] - sage: a.sqrt(all=True) - [[0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1], - [-1, 1, 1, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1]] - sage: a = CFF(4/25).sqrt(); a - [0, 2, 2] - sage: a.value() - 2/5 - """ - r = self._rational_() - if r < 0: - raise ValueError("self must be positive") - X = r.sqrt(all=all, prec=prec) - if not all: - return ContinuedFraction(self.parent(), X) - else: - return [ContinuedFraction(self.parent(), x) for x in X] - - def list(self): - """ - Return copy of the underlying list of this continued fraction. - - EXAMPLES:: - - sage: a = CFF(e); v = a.list(); v - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1] - sage: v[0] = 5 - sage: a - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1] - """ - return list(self._x) - - def __hash__(self): - """ - Return hash of self, which is the same as the hash of the value - of self, as a rational number. - - EXAMPLES:: - - sage: a = CFF(e) - sage: hash(a) - 19952398 - sage: hash(QQ(a)) - 19952398 - """ - return hash(self._rational_()) - - def __invert__(self): - """ - Return the multiplicative inverse of self. + - ``args``, ``kwds`` - arguments passed to ``QQ.random_element`` EXAMPLES:: - sage: a = CFF(e) - sage: b = ~a; b - [0, 2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 2] - sage: b*a - [1] + sage: CFF.random_element() # random + [0; 4, 7] """ - return ContinuedFraction(self.parent(), - self._rational_().__invert__()) + from sage.rings.rational_field import QQ + return self(QQ.random_element()) - def __pow__(self, n): - """ - Return self to the power of `n`. - - EXAMPLES:: - - sage: a = CFF([1,2,3]); a - [1, 2, 3] - sage: a^3 - [2, 1, 10, 1, 4, 1, 4] - sage: QQ(a)^3 == QQ(a^3) - True - sage: a^(-3) - [0, 2, 1, 10, 1, 4, 1, 4] - sage: QQ(a)^(-3) == QQ(a^(-3)) - True - """ - return ContinuedFraction(self.parent(), - self._rational_()**n) - - def __neg__(self): - """ - Return additive inverse of self. - - EXAMPLES:: - - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: -a - [0, 22, 1, 7, 2] - sage: QQ(-a) - 17/389 - """ - return ContinuedFraction(self.parent(), - self._rational_().__neg__()) - - def __abs__(self): - """ - Return absolute value of self. + def _element_constructor_(self, data, *extra_args): + r""" + Build an element of that field. - EXAMPLES:: + TESTS:: - sage: a = CFF(-17/389); a - [-1, 1, 21, 1, 7, 2] - sage: abs(a) - [0, 22, 1, 7, 2] - sage: QQ(abs(a)) - 17/389 - """ - return ContinuedFraction(self.parent(), - self._rational_().__abs__()) + sage: CFF(1/3) + [0; 3] + sage: CFF([1,3,2]) + [1; 3, 2] + sage: CFF(CFF(1/3)) + [0; 3] + """ + if isinstance(data, FieldElement) and data.parent() is self: + data = list(data) + if extra_args: + print "data",data,type(data) + print "extra_args",extra_args, type(extra_args[0]) + data = list(extra_args[0]) + if not isinstance(data, (tuple,list)): + from sage.rings.rational_field import QQ + data = QQ(data).continued_fraction_list() + else: + from continued_fraction import check_and_reduce_pair + data,_ = check_and_reduce_pair(data, []) + return self.element_class(data) - def is_one(self): - """ - Return True if self is one. + def _coerce_map_from_(self, R): + r""" + Return True for ZZ and QQ. EXAMPLES:: - sage: continued_fraction(1).is_one() + sage: CFF.has_coerce_map_from(ZZ) # indirect doctest True - sage: continued_fraction(2).is_one() - False - """ - return self._rational_().is_one() - - def __nonzero__(self): - """ - Return False if self is zero. - - EXAMPLES:: - - sage: continued_fraction(0).is_zero() + sage: CFF.has_coerce_map_from(QQ) True - sage: continued_fraction(1).is_zero() + sage: CFF.has_coerce_map_from(RR) False """ - return not self._rational_().is_zero() - - def _pari_(self): - """ - Return PARI list corresponding to this continued fraction. - - EXAMPLES:: - - sage: c = continued_fraction(0.12345); c - [0, 8, 9, 1, 21, 1, 1] - sage: pari(c) - [0, 8, 9, 1, 21, 1, 1] - """ - return pari(self._x) - - def _interface_init_(self, I=None): - """ - Return list representation for other systems corresponding to - this continued fraction. - - EXAMPLES:: - - sage: c = continued_fraction(0.12345); c - [0, 8, 9, 1, 21, 1, 1] - sage: gp(c) - [0, 8, 9, 1, 21, 1, 1] - sage: gap(c) - [ 0, 8, 9, 1, 21, 1, 1 ] - sage: maxima(c) - [0,8,9,1,21,1,1] - """ - return str(self._x) - - def additive_order(self): - """ - Return the additive order of this continued fraction, - which we defined to be the additive order of its value. - - EXAMPLES:: - - sage: CFF(-1).additive_order() - +Infinity - sage: CFF(0).additive_order() - 1 - """ - return self.value().additive_order() - - def multiplicative_order(self): - """ - Return the multiplicative order of this continued fraction, - which we defined to be the multiplicative order of its value. - - EXAMPLES:: - - sage: CFF(-1).multiplicative_order() - 2 - sage: CFF(1).multiplicative_order() - 1 - sage: CFF(pi).multiplicative_order() - +Infinity - """ - return self.value().multiplicative_order() - - -CFF = ContinuedFractionField_class() - -def ContinuedFractionField(): - """ - Return the (unique) field of all continued fractions. - - EXAMPLES:: - - sage: ContinuedFractionField() - Field of all continued fractions - """ - return CFF - -def continued_fraction(x, bits=None, nterms=None): - """ - Return the truncated continued fraction expansion of the real number - `x`, computed with an interval floating point approximation of `x` - to the given number of bits of precision. The returned continued - fraction is a list-like object, with a value method and partial - convergents method. - - If bits is not given, then use the number of valid bits of - precision of `x`, if `x` is a floating point number, or 53 bits - otherwise. If nterms is given, the precision is increased until - the specified number of terms can be computed, if possible. - - INPUT: - - - `x` -- number - - - ``bits`` -- None (default) or a positive integer - - - ``nterms`` -- None (default) or a positive integer - - OUTPUT: - - - a continued fraction - - EXAMPLES:: - - sage: v = continued_fraction(sqrt(2)); v - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] - sage: v = continued_fraction(sqrt(2), nterms=22); v - [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] - sage: type(v) - - sage: parent(v) - Field of all continued fractions - sage: v.value() - 131836323/93222358 - sage: RR(v.value()) == RR(sqrt(2)) - True - sage: v.convergents() - [1, 3/2, 7/5, 17/12, 41/29, 99/70, 239/169,...131836323/93222358] - sage: [RR(x) for x in v.convergents()] - [1.00000000000000, 1.50000000000000, 1.40000000000000, 1.41666666666667, ...1.41421356237310] - sage: continued_fraction(sqrt(2), 10) - [1, 2, 2] - sage: v.numerator() - 131836323 - sage: v.denominator() - 93222358 - sage: [v.pn(i) for i in range(10)] - [1, 3, 7, 17, 41, 99, 239, 577, 1393, 3363] - sage: [v.qn(i) for i in range(10)] - [1, 2, 5, 12, 29, 70, 169, 408, 985, 2378] - - Here are some more examples:: - - sage: continued_fraction(e, bits=20) - [2, 1, 2, 1, 1, 4, 1, 1] - sage: continued_fraction(e, bits=30) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8] - sage: continued_fraction(RealField(200)(e)) - [2, 1, 2, 1, 1, 4, 1, 1, 6, ...36, 1, 1, 38, 1, 1] - - Initial rounding can result in incorrect trailing digits:: - - sage: continued_fraction(RealField(39)(e)) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 2] - sage: continued_fraction(RealIntervalField(39)(e)) - [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10] - """ - return CFF(x, bits=bits, nterms=nterms) - + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ + return R is ZZ or R is QQ +CFF = ContinuedFractionField() +# Unpickling support is needed as the class ContinuedFractionField_class has +# been renamed into ContinuedFractionField in the ticket 14567 +from sage.structure.sage_object import register_unpickle_override +register_unpickle_override('sage.rings.contfrac', 'ContinuedFractionField_class',ContinuedFractionField) diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py new file mode 100644 index 00000000000..b6ae0990553 --- /dev/null +++ b/src/sage/rings/continued_fraction.py @@ -0,0 +1,2381 @@ +r""" +Continued fractions + +A continued fraction is a representation of a real number in terms of a sequence +of integers denoted `[a_0; a_1, a_2, \ldots]`. The well known decimal expansion +is another way of representing a real number by a sequence of integers. The +value of a continued fraction is defined recursively as: + +.. MATH:: + + [a_0; a_1, a_2, \ldots] = a_0 + \frac{1}{[a_1; a_2, \ldots]} = a_0 + + \frac{\displaystyle 1} + {\displaystyle a_1 + \frac{\displaystyle 1} + {\displaystyle a_2 + \frac{\displaystyle 1} + {\ldots}}} + +In this expansion, all coefficients `a_n` are integers and only the value `a_0` +may be non positive. Note that `a_0` is nothing else but the floor (this remark +provides a way to build the continued fraction expansion from a given real +number). As examples + +.. MATH:: + + \frac{45}{38} = 1 + \frac{\displaystyle 1} + {\displaystyle 5 + \frac{\displaystyle 1} + {\displaystyle 2 + \frac{\displaystyle 1} + {\displaystyle 3}}} + +.. MATH:: + + \pi = 3 + \frac{\displaystyle 1} + {\displaystyle 7 + \frac{\displaystyle 1} + {\displaystyle 15 + \frac{\displaystyle 1} + {\displaystyle 1 + \frac{\displaystyle 1} + {\displaystyle 292 + \frac{\displaystyle 1} + {\ldots}}}}} + +It is quite remarkable that + +- any real number admits a unique continued fraction expansion +- finite expansions correspond to rationals +- ultimately periodic expansions correspond to quadratic numbers (ie numbers of + the form `a + b \sqrt{D}` with `a` and `b` rationals and `D` square free + positive integer) +- two real numbers `x` and `y` have the same tail (up to a shift) in their + continued fraction expansion if and only if there are integers `a,b,c,d` with + `|ad - bc| = 1` and such that `y = (ax + b) / (cx + d)`. + +Moreover, the rational numbers obtained by truncation of the expansion of a real +number gives its so-called best approximations. For more informations on +continued fractions, you may have a look at :wikipedia:`Continued_fraction`. + +EXAMPLES: + +If you want to create the continued fraction of some real number you may either +use its method continued_fraction (if it exists) or call +:func:`continued_fraction`:: + + sage: (13/27).continued_fraction() + [0; 2, 13] + sage: 0 + 1/(2 + 1/13) + 13/27 + + sage: continued_fraction(22/45) + [0; 2, 22] + sage: 0 + 1/(2 + 1/22) + 22/45 + + sage: continued_fraction(pi) + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: continued_fraction_list(pi, nterms=5) + [3, 7, 15, 1, 292] + + sage: K. = NumberField(x^3 - 5, embedding=1.709) + sage: continued_fraction(cbrt5) + [1; 1, 2, 2, 4, 3, 3, 1, 5, 1, 1, 4, 10, 17, 1, 14, 1, 1, 3052, 1, ...] + +It is also possible to create a continued fraction from a list of partial +quotients:: + + sage: continued_fraction([-3,1,2,3,4,1,2]) + [-3; 1, 2, 3, 4, 1, 2] + +Even infinite:: + + sage: w = words.ThueMorseWord([1,2]) + sage: w + word: 1221211221121221211212211221211221121221... + sage: continued_fraction(w) + [1; 2, 2, 1, 2, 1, 1, 2, 2, 1...] + +To go back and forth between the value (as a real number) and the partial +quotients (seen as a finite or infinite list) you can use the methods +``quotients`` and ``value``:: + + sage: cf = (13/27).continued_fraction() + sage: cf.quotients() + [0, 2, 13] + sage: cf.value() + 13/27 + + sage: cf = continued_fraction(pi) + sage: cf.quotients() + lazy list [3, 7, 15, ...] + sage: cf.value() + pi + +The method ``value`` is currently not supported for continued fractions built +from an infinite sequence:: + + sage: w = words.FibonacciWord([1,2]) + sage: cf = continued_fraction(w) + sage: cf.quotients() + word: 1211212112112121121211211212112112121121... + sage: cf.value() + Traceback (most recent call last): + ... + NotImplementedError: Real numbers built from continued fractions are not yet implemented + +Recall that quadratic numbers correspond to ultimately periodic continued +fractions. For them special methods give access to preperiod and period:: + + sage: K. = QuadraticField(2) + sage: cf = continued_fraction(sqrt2); cf + [1; (2)*] + sage: cf.value() + sqrt2 + sage: cf.preperiod() + (1,) + sage: cf.period() + (2,) + + sage: cf = (3*sqrt2 + 1/2).continued_fraction(); cf + [4; (1, 2, 1, 7)*] + + sage: cf = continued_fraction([(1,2,3),(1,4)]); cf + [1; 2, 3, (1, 4)*] + sage: cf.value() + -2/23*sqrt2 + 36/23 + +On the following we can remark how the tail may change even in the same +quadratic field:: + + sage: for i in xrange(20): print continued_fraction(i*sqrt2) + [0] + [1; (2)*] + [2; (1, 4)*] + [4; (4, 8)*] + [5; (1, 1, 1, 10)*] + [7; (14)*] + ... + [24; (24, 48)*] + [25; (2, 5, 6, 5, 2, 50)*] + [26; (1, 6, 1, 2, 3, 2, 26, 2, 3, 2, 1, 6, 1, 52)*] + +Nevertheless, the tail is preserved under invertible integer homographies:: + + sage: apply_homography = lambda m,z: (m[0,0]*z + m[0,1]) / (m[1,0]*z + m[1,1]) + sage: m1 = SL2Z([60,13,83,18]) + sage: m2 = SL2Z([27,80,28,83]) + sage: a = sqrt2/3 + sage: a.continued_fraction() + [0; 2, (8, 4)*] + sage: b = apply_homography(m1, a) + sage: b.continued_fraction() + [0; 1, 2, 1, 1, 1, 1, 6, (8, 4)*] + sage: c = apply_homography(m2, a) + sage: c.continued_fraction() + [0; 1, 26, 1, 2, 2, (8, 4)*] + sage: d = apply_homography(m1**2*m2**3, a) + sage: d.continued_fraction() + [0; 1, 2, 1, 1, 1, 1, 5, 2, 1, 1, 1, 1, 5, 26, 1, 2, 1, 26, 1, 2, 1, 26, 1, 2, 2, (8, 4)*] + +.. TODO:: + + - Interactions with integer/rational and reals. + + - Gosper's algorithm to compute the continued fraction of (ax + b)/(cx + d) + knowing the one of x (see Gosper (1972, + http://www.inwap.com/pdp10/hbaker/hakmem/cf.html), Knuth (1998, TAOCP vol + 2, Exercise 4.5.3.15), Fowler (1999). See also Liardet, P. and Stambul, P. + "Algebraic Computation with Continued Fractions." J. Number Th. 73, + 92-121, 1998. + + - Improve numerical approximation (the method + :meth:`~ContinuedFraction_base._mpfr_` is quite slow compared to the + same method for an element of a number field) + + - Make a class for generalized continued fractions of the form `a_0 + + b_0/(a_1 + b_1/(...))` (the standard continued fractions are when all + `b_n= 1` while the Hirzebruch-Jung continued fractions are the one for + which `b_n = -1` for all `n`). See + :wikipedia:`Generalized_continued_fraction`. + + - look at the function ContinuedFractionApproximationOfRoot in GAP + +AUTHORS: + +- Vincent Delecroix (2014): cleaning, refactorisation, documentation from the + old implementation in ``contfrac`` (:trac:`14567`). +""" +from sage.structure.sage_object import SageObject +from integer import Integer +from infinity import Infinity + +ZZ_0 = Integer(0) +ZZ_1 = Integer(1) +ZZ_m1 = Integer(-1) +ZZ_2 = Integer(2) + +def last_two_convergents(x): + """ + Given the list ``x`` that consists of numbers, return the two last + convergents `p_{n-1}, q_{n-1}, p_n, q_n`. + + This function is principally used to compute the value of a ultimately + periodic continued fraction. + + EXAMPLES:: + + sage: from sage.rings.continued_fraction import last_two_convergents + sage: last_two_convergents([]) + (0, 1, 1, 0) + sage: last_two_convergents([0]) + (1, 0, 0, 1) + sage: last_two_convergents([-1,1,3,2]) + (-1, 4, -2, 9) + """ + p0, p1 = 0, 1 + q0, q1 = 1, 0 + for a in x: + p0, p1 = p1, a*p1+p0 + q0, q1 = q1, a*q1+q0 + return p0, q0, p1, q1 + +def rat_interval_cf_list(r1, r2): + r""" + Return the common prefix of r1 and r2 seen as continued fractions. + + EXAMPLES:: + + sage: from sage.rings.continued_fraction import rat_interval_cf_list + sage: for prec in xrange(10,54): + ....: R = RealIntervalField(20) + ....: for _ in xrange(100): + ....: x = R.random_element() * R.random_element() + R.random_element() / 100 + ....: l = x.lower().exact_rational() + ....: u = x.upper().exact_rational() + ....: cf = rat_interval_cf_list(l,u) + ....: a = continued_fraction(cf).value() + ....: b = continued_fraction(cf+[1]).value() + ....: if a > b: + ....: a,b = b,a + ....: assert a <= l + ....: assert b >= u + """ + l = [] + c1 = r1.floor() + c2 = r2.floor() + while c1 == c2: + l.append(c1) + r1 -= c1 + if r1 == 0: + break + r2 -= c2 + if r2 == 0: + break + + r1 = ~r1 + r2 = ~r2 + + c1 = r1.floor() + c2 = r2.floor() + return l + + +class ContinuedFraction_base(SageObject): + r""" + Base class for (standard) continued fractions. + + If you want to implement your own continued fraction, simply derived from + this class and implement the following methods: + + - ``def quotient(self, n)``: return the ``n``-th quotient of ``self`` as a + Sage integer + + - ``def length(self)``: the number of partial quotients of ``self`` as a + Sage integer or ``Infinity``. + + and optionally: + + - ``def value(self)``: return the value of ``self`` (an exact real number) + + This base class will provide: + + - computation of convergents in :meth:`convergent`, :meth:`numerator` and + :meth:`denominator` + + - comparison with other continued fractions (see :meth:`__cmp__`) + + - elementary arithmetic function :meth:`floor`, :meth:`ceil`, :meth:`sign` + + - accurate numerical approximations :meth:`_mpfr_` + + All other methods, in particular the ones involving binary operations like + sum or product, rely on the optional method :meth:`value` (and not on + convergents) and may fail at execution if it is not implemented. + """ + def __init__(self): + r""" + INPUT: + + - ``parent`` -- the parent of ``self`` + + TESTS:: + + sage: TestSuite(continued_fraction(3)).run() + """ + self._pn = [ZZ_0, ZZ_1] + self._qn = [ZZ_1, ZZ_0] + + def __abs__(self): + """ + Return absolute value of self. + + EXAMPLES:: + + sage: a = continued_fraction(-17/389); a + [-1; 1, 21, 1, 7, 2] + sage: abs(a) + [0; 22, 1, 7, 2] + sage: QQ(abs(a)) + 17/389 + """ + if self.quotient(0) >= 0: + return self + return self.__neg__() + + def __cmp__(self, other): + """ + EXAMPLES:: + + sage: a = continued_fraction(-17/389) + sage: b = continued_fraction(1/389) + sage: c = continued_fraction([(),(1,)]) # the golden ratio + sage: d = continued_fraction([(-1,),(1,)]) + sage: d < a and a < b and b < c + True + sage: d >= a + False + sage: d == d + True + """ + i = 0 + + while True: + a = self.quotient(i) + b = other.quotient(i) + test = cmp(a,b) + if test == 1: # a > b + return -1 if i % 2 else 1 + if test == -1: # b > a + return 1 if i % 2 else -1 + if a == ZZ_0 and b == ZZ_0 and i: # rational case + return 0 + i += 1 + + def _mpfr_(self, R): + r""" + Return a numerical approximation of ``self`` in the real mpfr ring ``R``. + + The output result is accurate: when the rounding mode of + ``R`` is 'RNDN' then the result is the nearest binary number of ``R`` to + ``self``. The other rounding mode are 'RNDD' (toward +infinity), 'RNDU' + (toward -infinity) and 'RNDZ' (toward zero). + + EXAMPLES:: + + sage: continued_fraction(1/2).n() + 0.500000000000000 + sage: continued_fraction([0,4]).n() + 0.250000000000000 + sage: continued_fraction([12,1,3,4,2,2,3,1,2]).n(digits=4) + 12.76 + + sage: continued_fraction(12/7).n(digits=13) == (12/7).n(digits=13) + True + sage: continued_fraction(-14/333).n(digits=21) == (-14/333).n(digits=21) + True + + sage: a = (106*pi - 333) / (355 - 113*pi) - 292 + sage: cf = continued_fraction(a); cf + [0; 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, 1, 84, 2, 1, ...] + sage: cf.n(digits=3) + 0.635 + sage: cf.n(digits=4) + 0.6346 + sage: cf.n(digits=5) + 0.63459 + sage: cf.n(digits=6) + 0.634591 + sage: cf.n(digits=7) + 0.6345910 + sage: cf.n(digits=8) + 0.63459101 + + sage: K. = NumberField(x^3-2, 'a', embedding=1.25) + sage: b = 504/253*a^2 + 635/253*a + 661/253 + sage: cf = continued_fraction(b); cf + [8; 1, 14, 1, 10, 2, 1, 4, 12, 2, 3, 2, 1, 3, 4, 1, 1, 2, 14, 3, ...] + sage: cf.n(digits=3) + 8.94 + sage: cf.n(digits=6) + 8.93715 + sage: cf.n(digits=7) + 8.937154 + sage: cf.n(digits=8) + 8.9371541 + sage: cf.n(digits=9) + 8.93715414 + sage: cf.n(digits=10) + 8.937154138 + sage: cf.n(digits=11) + 8.9371541378 + + TESTS:: + + We check that the rounding works as expected, at least in the rational + case:: + + sage: for _ in xrange(100): + ....: a = QQ.random_element(num_bound=1<<64) + ....: cf = continued_fraction(a) + ....: for prec in 17,24,53,128,256: + ....: for rnd in 'RNDN','RNDD','RNDU','RNDZ': + ....: R = RealField(prec=prec, rnd=rnd) + ....: assert R(cf) == R(a) + """ + # 1. integer case + if self.quotient(1) is Infinity: + return R(self.quotient(0)) + + # 2. negative numbers + # TODO: it is possible to deal with negative values. The only problem is + # that we need to find the good value for N (which involves + # self.quotient(k) for k=0,1,2) + if self.quotient(0) < 0: + rnd = R.rounding_mode() + if rnd == 'RNDN' or rnd == 'RNDZ': + return -R(-self) + elif rnd == 'RNDD': + r = R(-self) + s,m,e = r.sign_mantissa_exponent() + if e < 0: + return -(R(m+1) >> (-e)) + return -(R(m+1) << e) + else: + r = R(-self) + s,m,e = r.sign_mantissa_exponent() + if e < 0: + return -(R(m-1) >> (-e)) + return -(R(m-1) << e) + + # 3. positive non integer + if self.quotient(0) == 0: # 0 <= self < 1 + N = R.prec() + self.quotient(1).nbits() - 1 + if self.quotient(2) is Infinity and self.quotient(1) % (1 << (self.quotient(1).nbits()-1)) == 0: + # if self is of the form [0; 2^N] then we need the following + N -= 1 + else: # self > 1 + N = R.prec() - self.quotient(0).nbits() + + # even/odd convergents are respectively below/above + k = 0 + p_even = self.numerator(2*k) + p_odd = self.numerator(2*k+1) + q_even = self.denominator(2*k) + q_odd = self.denominator(2*k+1) + m_even = (p_even << N) // q_even # floor((2^N p_even) / q_even) + m_odd = (p_odd << N + q_odd - 1) // q_odd # ceil((2^N p_odd) / q_odd) + while (m_odd - m_even) > 1: + k += 1 + p_even = self.numerator(2*k) + p_odd = self.numerator(2*k+1) + q_even = self.denominator(2*k) + q_odd = self.denominator(2*k+1) + m_even = (p_even << N) // q_even + m_odd = ((p_odd << N) + q_odd - 1) // q_odd + + assert m_odd.nbits() == R.prec() or m_even.nbits() == R.prec() + + if m_even == m_odd: # no need to worry (we have a decimal number) + return R(m_even) >> N + + # check ordering + # m_even/2^N <= p_even/q_even <= self <= p_odd/q_odd <= m_odd/2^N + assert m_odd == m_even + 1 + assert m_even / (ZZ_1 << N) <= p_even/q_even + assert p_even / q_even <= p_odd / q_odd + assert p_odd / q_odd <= m_odd / (ZZ_1 << N) + + rnd = R.rounding_mode() + if rnd == 'RNDN': # round to the nearest + # in order to find the nearest approximation we possibly need to + # augment our precision on convergents. + while True: + assert not(p_odd << (N+1) <= (2*m_odd-1) * q_odd) or not(p_even << (N+1) >= (2*m_even+1) * q_even) + if p_odd << (N+1) <= (2*m_odd-1) * q_odd: + return R(m_even) >> N + if p_even << (N+1) >= (2*m_even+1) * q_even: + return R(m_odd) >> N + k += 1 + p_even = self.numerator(2*k) + p_odd = self.numerator(2*k+1) + q_even = self.denominator(2*k) + q_odd = self.denominator(2*k+1) + elif rnd == 'RNDU': # round up (toward +infinity) + return R(m_odd) >> N + elif rnd == 'RNDD': # round down (toward -infinity) + return R(m_even) >> N + elif rnd == 'RNDZ': # round toward zero + if m_even.sign() == 1: + return R(m_even) >> N + else: + return R(m_odd) >> N + else: + raise ValueError("%s unknown rounding mode" % rnd) + + def __float__(self): + """ + EXAMPLES:: + + sage: a = continued_fraction(-17/389); a + [-1; 1, 21, 1, 7, 2] + sage: float(a) + -0.043701799485861184 + sage: float(-17/389) + -0.043701799485861184 + """ + from sage.rings.real_mpfr import RR + return float(self._mpfr_(RR)) + + def numerator(self, n): + """ + Return the numerator of the `n`-th partial convergent of ``self``. + + EXAMPLES:: + + sage: c = continued_fraction(pi); c + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: c.numerator(0) + 3 + sage: c.numerator(12) + 80143857 + sage: c.numerator(152) + 3943771611212266962743738812600748213157266596588744951727393497446921245353005283 + """ + n = Integer(n) + + p = self._pn + q = self._qn + + if n < -2: + raise ValueError("n must be at least -2") + + for k in xrange(len(p), n+3): + x = self.quotient(k-2) + if x is Infinity and k != 2: + return p[-1] + p.append(x*p[k-1] + p[k-2]) + q.append(x*q[k-1] + q[k-2]) + + return p[n+2] + + p = numerator + + def pn(self, n): + r""" + Return the numerator of the `n`-th partial convergent of ``self``. + + This method is deprecated since :trac:`14567` and :meth:`numerator` + should be used instead. + + EXAMPLES:: + + sage: continued_fraction([1,2,3,5,4]).pn(3) + doctest:...: DeprecationWarning: pn is deprecated. Use the methods p or numerator instead. + See http://trac.sagemath.org/14567 for details. + 53 + """ + from sage.misc.superseded import deprecation + deprecation(14567, 'pn is deprecated. Use the methods p or numerator instead.') + return self.numerator(n) + + def denominator(self, n): + """ + Return the denominator of the ``n``-th partial convergent of ``self``. + + EXAMPLES:: + + sage: c = continued_fraction(pi); c + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: c.denominator(0) + 1 + sage: c.denominator(12) + 25510582 + sage: c.denominator(152) + 1255341492699841451528811722575401081588363886480089431843026103930863337221076748 + """ + self.numerator(n) # ! silent computation of qn + if len(self._qn) < n+3: + return self._qn[-1] + return self._qn[n+2] + + q = denominator + + def qn(self, n): + r""" + Return the denominator of the ``n``-th partial convergent of ``self``. + + This method is deprecated since :trac:`14567`. Use :meth:`denominator` + instead. + + EXAMPLES:: + + sage: continued_fraction([1,2,3,12,1]).qn(3) + doctest:...: DeprecationWarning: qn is deprecated. Use the methods q or denominator instead. + See http://trac.sagemath.org/14567 for details. + 93 + """ + from sage.misc.superseded import deprecation + deprecation(14567, 'qn is deprecated. Use the methods q or denominator instead.') + return self.denominator(n) + + def convergent(self, n): + """ + Return the ``n``-th partial convergent to self. + + EXAMPLES:: + + sage: a = continued_fraction(pi); a + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: a.convergent(3) + 355/113 + sage: a.convergent(15) + 411557987/131002976 + """ + return self.numerator(n) / self.denominator(n) + + def convergents(self): + """ + Return the list of partial convergents of ``self``. + + If ``self`` is an infinite continued fraction, then the object returned + is a :class:`~sage.misc.lazy_list.lazy_list` which behave like an + infinite list. + + EXAMPLES:: + + sage: a = continued_fraction(23/157); a + [0; 6, 1, 4, 1, 3] + sage: a.convergents() + [0, 1/6, 1/7, 5/34, 6/41, 23/157] + + sage: #TODO: example with infinite list + """ + if self.length() == Infinity: + from sage.misc.lazy_list import lazy_list + from itertools import count + return lazy_list(self.numerator(n) / self.denominator(n) for n in count()) + return [self.numerator(n) / self.denominator(n) for n in xrange(len(self))] + + def quotients(self): + r""" + Return the list of partial quotients of ``self``. + + If ``self`` is an infinite continued fraction, the the object returned + is a :class:``~sage.misc.lazy_list.lazy_list`` which behave like an + infinite list. + + EXAMPLES:: + + sage: a = continued_fraction(23/157); a + [0; 6, 1, 4, 1, 3] + sage: a.quotients() + [0, 6, 1, 4, 1, 3] + + sage: #TODO: example with infinite list + """ + if self.length() == Infinity: + from sage.misc.lazy_list import lazy_list + from itertools import count + return lazy_list(self.quotient(n) for n in count()) + return [self.quotient(n) for n in xrange(len(self))] + + def __getitem__(self, n): + r""" + Return the ``n``-th partial quotient of ``self`` or a continued fraction + associated to a sublist of the partial quotients of ``self``. + + TESTS:: + + sage: cf1 = continued_fraction(pi); cf1 + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: cf2 = continued_fraction(QuadraticField(2).gen()); cf2 + [1; (2)*] + sage: cf3 = continued_fraction(4/17); cf3 + [0; 4, 4] + sage: cf1[3:17] + [1; 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2] + sage: cf2[:10] + [1; 2, 2, 2, 2, 2, 2, 2, 2, 2] + sage: cf3[1:16] + [4; 4] + + Be careful that the truncation of an infinite continued fraction might + be shorter by one:: + + sage: len(continued_fraction(golden_ratio)[:8]) + 7 + """ + if isinstance(n, slice): + quots = self.quotients().__getitem__(n) + if n.stop is not None: + quots = list(quots) + return continued_fraction(quots) + + try: + n = n.__index__() + except (AttributeError, ValueError): + raise ValueError("n (=%s) should be an integer" % n) + if n < 0: + raise ValueError("n (=%s) should be positive" % n) + q = self.quotient(n) + if q is Infinity: + raise IndexError("index out of range") + + return q + + def __iter__(self): + r""" + Iterate over the partial quotient of self. + + EXAMPLES:: + + sage: cf = continued_fraction(pi) + sage: i = iter(cf) + sage: [next(i) for _ in xrange(10)] + [3, 7, 15, 1, 292, 1, 1, 1, 2, 1] + sage: [next(i) for _ in xrange(10)] + [3, 1, 14, 2, 1, 1, 2, 2, 2, 2] + sage: [next(i) for _ in xrange(10)] + [1, 84, 2, 1, 1, 15, 3, 13, 1, 4] + """ + yield self.quotient(0) + i = 1 + while True: + q = self.quotient(i) + if q is Infinity: + break + yield q + i += 1 + + def __int__(self): + """ + EXAMPLES:: + + sage: a = continued_fraction(-17/389); a + [-1; 1, 21, 1, 7, 2] + sage: int(a) + -1 + """ + return int(self.quotient(0)) + + def __long__(self): + """ + EXAMPLES:: + + sage: a = continued_fraction(-17/389); a + [-1; 1, 21, 1, 7, 2] + sage: long(a) + -1L + """ + return long(self.quotient(0)) + + def sign(self): + r""" + Returns the sign of self as an Integer. + + The sign is defined to be ``0`` if ``self`` is ``0``, ``1`` if ``self`` + is positive and ``-1`` if ``self`` is negative. + + EXAMPLES:: + + sage: continued_fraction(tan(pi/7)).sign() + 1 + sage: continued_fraction(-34/2115).sign() + -1 + sage: continued_fraction([0]).sign() + 0 + """ + if self.quotient(0) == 0: + if self.quotient(1) is Infinity: + return ZZ_0 + return ZZ_1 + return self.quotient(0).sign() + + def floor(self): + r""" + Return the floor of ``self``. + + EXAMPLES:: + + sage: cf = continued_fraction([2,1,2,3]) + sage: cf.floor() + 2 + """ + return self.quotient(0) + + def ceil(self): + r""" + Return the ceil of ``self``. + + EXAMPLES:: + + sage: cf = continued_fraction([2,1,3,4]) + sage: cf.ceil() + 3 + """ + if self.length() == 1: + return self.quotient(0) + return self.quotient(0)+1 + + def __nonzero__(self): + """ + Return False if self is zero. + + EXAMPLES:: + + sage: continued_fraction(0).is_zero() # indirect doctest + True + sage: continued_fraction(1).is_zero() # indirect doctest + False + sage: continued_fraction([(),(1,)]).is_zero() # indirect doctest + False + sage: continued_fraction([(0,),(1,2)]).is_zero() # indirect doctest + False + """ + return bool(self.quotient(0)) or self.quotient(1) is not Infinity + + def is_zero(self): + r""" + Test whether ``self`` is zero. + + EXAMPLES:: + + sage: continued_fraction(0).is_zero() + True + sage: continued_fraction((0,1)).is_zero() + False + sage: continued_fraction(-1/2).is_zero() + False + sage: continued_fraction(pi).is_zero() + False + """ + return self.quotient(0) == ZZ_0 and self.quotient(1) is Infinity + + def is_one(self): + r""" + Test whether ``self`` is one. + + EXAMPLES:: + + sage: continued_fraction(1).is_one() + True + sage: continued_fraction(5/4).is_one() + False + sage: continued_fraction(0).is_one() + False + sage: continued_fraction(pi).is_one() + False + """ + return self.quotient(0) == ZZ_1 and self.quotient(1) is Infinity + + def is_minus_one(self): + r""" + Test whether ``self`` is minus one. + + EXAMPLES:: + + sage: continued_fraction(-1).is_minus_one() + True + sage: continued_fraction(1).is_minus_one() + False + sage: continued_fraction(0).is_minus_one() + False + sage: continued_fraction(-2).is_minus_one() + False + sage: continued_fraction([-1,1]).is_minus_one() + False + """ + return self.quotient(0) == ZZ_m1 and self.quotient(1) is Infinity + + def additive_order(self): + """ + Return the additive order of this continued fraction, + which we defined to be the additive order of its value. + + EXAMPLES:: + + sage: continued_fraction(-1).additive_order() + +Infinity + sage: continued_fraction(0).additive_order() + 1 + """ + return Infinity if self else ZZ_1 + + def multiplicative_order(self): + """ + Return the multiplicative order of this continued fraction, + which we defined to be the multiplicative order of its value. + + EXAMPLES:: + + sage: continued_fraction(-1).multiplicative_order() + 2 + sage: continued_fraction(1).multiplicative_order() + 1 + sage: continued_fraction(pi).multiplicative_order() + +Infinity + """ + if self.is_zero(): + return Infinity + if self.is_one(): + return ZZ_1 + if self.is_minus_one(): + return ZZ_2 + return Infinity + + def numerical_approx(self, prec=None, digits=None, algorithm=None): + """ + Return a numerical approximation of this continued fraction. + + INPUT: + + - ``prec`` - the precision + + - ``digits`` - the number of digits + + - ``algorithm`` - the algorithm to use + + See :func:`sage.misc.functional.numerical_approx` for more information + on the input. + + EXAMPLES:: + + sage: w = words.FibonacciWord([1,3]) + sage: cf = continued_fraction(w) + sage: cf + [1; 3, 1, 1, 3, 1, 3, 1, 1, 3, 1, 1, 3, 1, 3, 1, 1, 3, 1, 3...] + sage: cf.numerical_approx(prec=53) + 1.28102513329557 + + The method `n` is a shortcut to this one:: + + sage: cf.n(digits=25) + 1.281025133295569815552930 + sage: cf.n(digits=33) + 1.28102513329556981555293038097590 + """ + import sage.misc.functional + return sage.misc.functional.numerical_approx(self, prec=prec, + digits=digits, + algorithm=algorithm) + n = numerical_approx + + +class ContinuedFraction_periodic(ContinuedFraction_base): + r""" + Continued fraction associated with rational or quadratic number. + + A rational number has a finite continued fraction expansion (or ultimately + 0). The one of a quadratic number, ie a number of the form `a + b \sqrt{D}` + with `a` and `b` rational, is ultimately periodic. + + .. NOTE:: + + This class stores a tuple ``_x1`` for the preperiod and a tuple ``_x2`` + for the period. In the purely periodic case ``_x1`` is empty while in + the rational case ``_x2`` is the tuple ``(0,)``. + """ + def __init__(self, x1, x2=None, check=True): + r""" + INPUT: + + - ``x1`` - a tuple of integers + + - ``x2`` - a tuple of integers + + TESTS:: + + sage: cf = continued_fraction((1,1,2,3,4)) # indirect doctest + sage: loads(dumps(cf)) == cf + True + sage: cf = continued_fraction((1,5),(3,2)) # indirect doctest + sage: loads(dumps(cf)) == cf + True + """ + ContinuedFraction_base.__init__(self) + self._x1 = tuple(x1) + if not x2: + self._x2 = (Infinity,) + else: + self._x2 = tuple(x2) + + def period(self): + r""" + Return the periodic part of ``self``. + + EXAMPLES:: + + sage: K. = QuadraticField(3) + sage: cf = continued_fraction(sqrt3); cf + [1; (1, 2)*] + sage: cf.period() + (1, 2) + + sage: for k in xsrange(2,40): + ....: if not k.is_square(): + ....: s = QuadraticField(k).gen() + ....: cf = continued_fraction(s) + ....: print '%2d %d %s'%(k, len(cf.period()), cf) + 2 1 [1; (2)*] + 3 2 [1; (1, 2)*] + 5 1 [2; (4)*] + 6 2 [2; (2, 4)*] + 7 4 [2; (1, 1, 1, 4)*] + 8 2 [2; (1, 4)*] + 10 1 [3; (6)*] + 11 2 [3; (3, 6)*] + 12 2 [3; (2, 6)*] + 13 5 [3; (1, 1, 1, 1, 6)*] + 14 4 [3; (1, 2, 1, 6)*] + ... + 35 2 [5; (1, 10)*] + 37 1 [6; (12)*] + 38 2 [6; (6, 12)*] + 39 2 [6; (4, 12)*] + """ + if self._x2[0] is Infinity: + return () + return self._x2 + + def preperiod(self): + r""" + Return the preperiodic part of ``self``. + + EXAMPLES:: + + sage: K. = QuadraticField(3) + sage: cf = continued_fraction(sqrt3); cf + [1; (1, 2)*] + sage: cf.preperiod() + (1,) + + sage: cf = continued_fraction(sqrt3/7); cf + [0; 4, (24, 8)*] + sage: cf.preperiod() + (0, 4) + """ + return self._x1 + + def quotient(self, n): + r""" + Return the ``n``-th partial quotient of ``self``. + + EXAMPLES:: + + sage: cf = continued_fraction([(12,5),(1,3)]) + sage: [cf.quotient(i) for i in xrange(10)] + [12, 5, 1, 3, 1, 3, 1, 3, 1, 3] + """ + n = int(n) + if n < 0: + raise ValueError("n (=%d) should be positive" % n) + if n < len(self._x1): + return self._x1[n] + return self._x2[(n-len(self._x1)) % len(self._x2)] + + def length(self): + r""" + Returns the number of partial quotients of ``self``. + + EXAMPLES:: + + sage: continued_fraction(2/5).length() + 3 + sage: cf = continued_fraction([(0,1),(2,)]); cf + [0; 1, (2)*] + sage: cf.length() + +Infinity + """ + if len(self._x2) > 1 or self._x2[0] is not Infinity: + return Infinity + return Integer(len(self._x1)) + + def __cmp__(self, other): + r""" + EXAMPLES:: + + sage: a = continued_fraction([(0,),(1,2,3,1,2,3,1)]); a.n() + 0.694249167819459 + sage: b = continued_fraction([(0,),(1,2,3)]); b.n() + 0.694254176766073 + sage: c = continued_fraction([(0,1),(2,3)]); c.n() + 0.696140478029631 + sage: d = continued_fraction([(0,1,2),(3,)]); d.n() + 0.697224362268005 + sage: a < b and a < c and a < d + True + sage: b < c and b < d and c < d + True + sage: b == c + False + sage: c > c + False + sage: b >= d + False + """ + if isinstance(other, ContinuedFraction_periodic): + n = max(len(self._x1) + 2*len(self._x2), + len(other._x1) + 2*len(other._x2)) + for i in xrange(n): + a = self.quotient(i) + b = other.quotient(i) + test = cmp(a,b) + if test == 1: + return -1 if i % 2 else 1 + if test == -1: + return 1 if i % 2 else -1 + return 0 + + return ContinuedFraction_base.__cmp__(self, other) + + def value(self): + r""" + Return the value of ``self`` as a quadratic number (with square free + discriminant). + + EXAMPLES: + + Some purely periodic examples:: + + sage: cf = continued_fraction([(),(2,)]); cf + [(2)*] + sage: v = cf.value(); v + sqrt2 + 1 + sage: v.continued_fraction() + [(2)*] + + sage: cf = continued_fraction([(),(1,2)]); cf + [(1, 2)*] + sage: v = cf.value(); v + 1/2*sqrt3 + 1/2 + sage: v.continued_fraction() + [(1, 2)*] + + The number ``sqrt3`` that appear above is actually internal to the + continued fraction. In order to be access it from the console:: + + sage: cf.value().parent().inject_variables() + Defining sqrt3 + sage: sqrt3 + sqrt3 + sage: ((sqrt3+1)/2).continued_fraction() + [(1, 2)*] + + Some ultimately periodic but non periodic examples:: + + sage: cf = continued_fraction([(1,),(2,)]); cf + [1; (2)*] + sage: v = cf.value(); v + sqrt2 + sage: v.continued_fraction() + [1; (2)*] + + sage: cf = continued_fraction([(1,3),(1,2)]); cf + [1; 3, (1, 2)*] + sage: v = cf.value(); v + -sqrt3 + 3 + sage: v.continued_fraction() + [1; 3, (1, 2)*] + + sage: cf = continued_fraction([(-5,18), (1,3,1,5)]) + sage: cf.value().continued_fraction() == cf + True + sage: cf = continued_fraction([(-1,),(1,)]) + sage: cf.value().continued_fraction() == cf + True + + TESTS:: + + sage: a1 = ((0,1),(2,3)) + sage: a2 = ((-12,1,1),(2,3,2,4)) + sage: a3 = ((1,),(1,2)) + sage: a4 = ((-2,2),(1,124,13)) + sage: a5 = ((0,),(1,)) + sage: for a in a1,a2,a3,a4,a5: + ....: cf = continued_fraction(a) + ....: assert cf.value().continued_fraction() == cf + """ + if self._x1 and self._x1[0] < 0: + return -(-self).value() + + if self._x2[0] is Infinity: + return self._rational_() + + # determine the equation for the purely periodic cont. frac. determined + # by self._x2 + p0,q0,p1,q1 = last_two_convergents(self._x2) + + # now x is one of the root of the equation + # q1 x^2 + (q0 - p1) x - p0 = 0 + from sage.rings.number_field.number_field import QuadraticField + from sage.misc.functional import squarefree_part + D = (q0-p1)**2 + 4*q1*p0 + DD = squarefree_part(D) + Q = QuadraticField(DD, 'sqrt%d' % DD) + x = ((p1 - q0) + (D/DD).sqrt() * Q.gen()) / (2*q1) + + # we add the preperiod + p0,q0,p1,q1 = last_two_convergents(self._x1) + return (p1*x + p0) / (q1*x + q0) + + def _repr_(self): + r""" + TESTS:: + + sage: a = continued_fraction(pi.n()); a + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] + sage: a.rename('continued fraction of pi') + sage: a + continued fraction of pi + + sage: continued_fraction([(0,1),(2,)]) + [0; 1, (2)*] + sage: continued_fraction([(),(1,3)]) + [(1, 3)*] + """ + if self._x2[0] is Infinity: # rational case + if len(self._x1) == 1: + return '[%d]' % self._x1[0] + return '[%d; ' % self._x1[0] + ', '.join(str(a) for a in self._x1[1:]) + ']' + + period = '(' + ', '.join(str(a) for a in self._x2) + ')*' + if not self._x1: # purely periodic case + return '[' + period + ']' + + if len(self._x1) == 1: + return '[%d; ' % self._x1[0] + period + ']' + return '[%d; ' % self._x1[0] + ', '.join(str(a) for a in self._x1[1:]) + ', ' + period + ']' + +# def __reduce__(self): +# r""" +# Pickling support. +# +# EXAMPLES:: +# +# sage: a = CFF([1,2,3]) +# sage: loads(dumps(a)) == a +# True +# +# sage: a = CFF([(-1,2),(3,1,4)]) +# sage: loads(dumps(a)) == a +# True +# """ +# return self.parent(),((self._x1,self._x2),) + + def __len__(self): + """ + Return the number of terms in this continued fraction. + + EXAMPLES:: + + sage: len(continued_fraction([1,2,3,4,5]) ) + 5 + """ + if self._x2[0] is Infinity: # rational case + return len(self._x1) + raise ValueError("the length is infinite") + + def _rational_(self): + """ + EXAMPLES:: + + sage: a = continued_fraction(-17/389); a + [-1; 1, 21, 1, 7, 2] + sage: a._rational_() + -17/389 + sage: QQ(a) + -17/389 + """ + if self._x2[0] is not Infinity: + raise ValueError("this is not a rational!") + n = len(self) + return self.numerator(n-1) / self.denominator(n-1) + + def _latex_(self): + """ + EXAMPLES:: + + sage: a = continued_fraction(-17/389) + sage: latex(a) + -1+ \frac{\displaystyle 1}{\displaystyle 1+ \frac{\displaystyle 1}{\displaystyle 21+ \frac{\displaystyle 1}{\displaystyle 1+ \frac{\displaystyle 1}{\displaystyle 7+ \frac{\displaystyle 1}{\displaystyle 2}}}}} + """ + if self._x2[0] is not Infinity: + raise NotImplementedError("latex not implemented for non rational continued fractions") + v = self._x1 + if len(v) == 0: + return '0' + s = str(v[0]) + for i in range(1,len(v)): + s += '+ \\frac{\\displaystyle 1}{\\displaystyle %s' % v[i] + s += '}'*(len(v)-1) + return s + + def __invert__(self): + """ + Return the multiplicative inverse of self. + + EXAMPLES:: + + sage: a = continued_fraction(13/25) + sage: ~a == continued_fraction(25/13) + True + sage: a.value() * (~a).value() + 1 + + sage: a = continued_fraction(-17/253) + sage: ~a == continued_fraction(-253/17) + True + sage: a.value() * (~a).value() + 1 + + sage: K. = QuadraticField(5) + sage: a1 = (sqrt5+1)/2 + sage: c1 = a1.continued_fraction(); c1 + [(1)*] + sage: ~c1 + [0; (1)*] + sage: c1.value() * (~c1).value() + 1 + + sage: c2 = (sqrt5/3 + 1/7).continued_fraction(); c2 + [0; 1, (7, 1, 17, ..., 1, 2)*] + sage: c2.value() * (~c2).value() + 1 + """ + if not self: + raise ZeroDivisionError("Rational division by 0") + if self._x1: + if self._x1[0] < 0: + return -(-self).__invert__() + if self._x1[0] == 0: + return self.__class__(self._x1[1:], self._x2) + return self.__class__((0,) + self._x1, self._x2) + + def __neg__(self): + """ + Return additive inverse of self. + + TESTS:: + + sage: quots1 = [(0,),(1,),(2,),(0,1),(1,1),(2,1),(1,2),(0,1,1),(1,1,1),(1,1,1,1),(1,2)] + sage: for q in quots1: + ....: cf = continued_fraction(q) + ....: ncf = -cf + ....: nncf = -ncf + ....: assert cf == nncf + ....: assert ncf.value() == -cf.value() + ....: assert cf.length() < 2 or cf.quotients()[-1] != 1 + ....: assert ncf.length() < 2 or ncf.quotients()[-1] != 1 + ....: assert nncf.length() < 2 or nncf.quotients()[-1] != 1 + + sage: quots2 = [((),(1,)), ((), (1,2)), ((0,),(1,)), ((),(2,1)), ((3,),(2,1))] + sage: for q in quots2: + ....: cf = continued_fraction(q) + ....: ncf = -cf + ....: nncf = -ncf + ....: assert cf == nncf + ....: assert ncf.value() == -cf.value() + """ + x1 = self._x1 + x2 = self._x2 + + if x2[0] is Infinity: + if len(x1) == 1: + xx1 =(-x1[0],) + + elif x1[1] == 1: + xx1 = (-x1[0]-1, x1[2]+1) + x1[3:] + + elif len(x1) == 2 and x1[1] == 2: + xx1 = (-x1[0] -1, ZZ_2) + + else: + xx1 = (-x1[0]-1, ZZ_1, x1[1]-1) + x1[2:] + + return self.__class__(xx1, x2) + + # to make the quadratic case work, we need 3 elements in x1 + if len(x1) < 3: + x1 += x2 + if len(x1) < 3: + x1 += x2 + if len(x1) < 3: + x1 += x2 + + if x1[1] == 1: + xx1 = (-x1[0]-1, x1[2]+1) + x1[3:] + else: + xx1 = (-x1[0]-1, ZZ_1, x1[1]-1) + x1[2:] + xx1,xx2 = check_and_reduce_pair(xx1,x2) + return self.__class__(xx1,xx2) + +class ContinuedFraction_real(ContinuedFraction_base): + r""" + Continued fraction of a real (exact) number. + + This class simply wraps a real number into an attribute (that can be + accessed through the method :meth:`value`). The number is assumed to be + irrational. + + EXAMPLES:: + + sage: cf = continued_fraction(pi) + sage: cf + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: cf.value() + pi + + sage: cf = continued_fraction(e) + sage: cf + [2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, ...] + sage: cf.value() + e + """ + def __init__(self, x): + r""" + INPUT: + + - ``x`` -- the real number from which we want the continued fraction + + TESTS:: + + sage: TestSuite(continued_fraction(pi)).run() + """ + ContinuedFraction_base.__init__(self) + self._x0 = x + + + from real_mpfi import RealIntervalField + self._xa = RealIntervalField(53)(self._x0) # an approximation of the + # last element of the orbit + # under the Gauss map + self._quotients = [] + + def length(self): + r""" + Return infinity + + EXAMPLES:: + + sage: continued_fraction(pi).length() + +Infinity + """ + return Infinity + + def __len__(self): + r""" + TESTS:: + + sage: len(continued_fraction(pi)) + Traceback (most recent call last): + ... + ValueError: the length is infinite! + """ + raise ValueError("the length is infinite!") + +# def __reduce__(self): +# r""" +# Pickling support. +# +# TESTS:: +# +# sage: cf = continued_fraction(pi) +# sage: loads(dumps(cf)) == cf +# True +# """ +# return self.parent(),(self.value(),) + + def __cmp__(self, other): + r""" + Comparison. + + EXAMPLES:: + + sage: continued_fraction(pi) > continued_fraction(e) + True + sage: continued_fraction(pi) > continued_fraction(e+4) + False + """ + try: + # The following is crazy and prevent us from using cmp(self.value(), + # other.value()). On sage-5.10.beta2: + # sage: cmp(pi, 4) + # -1 + # sage: cmp(pi, pi+4) + # 1 + if self.value() == other.value(): + return 0 + if self.value() - other.value() > 0: + return 1 + return -1 + except StandardError: + return ContinuedFraction_base.__cmp__(self, other) + + def _repr_(self): + r""" + String representation. + + EXAMPLES:: + + sage: continued_fraction(pi) # indirect doctest + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + """ + return '[%d; ' % self.quotient(0) + ', '.join(str(self.quotient(i)) for i in xrange(1,20)) + ", ...]" + + def quotient(self, n): + r""" + Returns the ``n``-th quotient of ``self``. + + EXAMPLES:: + + sage: cf = continued_fraction(pi) + sage: cf.quotient(27) + 13 + sage: cf.quotient(2552) + 152 + sage: cf.quotient(10000) # long time + 5 + + The algorithm is not efficient with element of the symbolic ring and, + if possible, one can always prefer number fields elements. The reason is + that, given a symbolic element ``x``, there is no automatic way to + evaluate in ``RIF`` an expression of the form ``(a*x+b)/(c*x+d)`` where + both the numerator and the denominator are extremely small:: + + sage: a1 = pi + sage: c1 = continued_fraction(a1) + sage: p0 = c1.numerator(12); q0 = c1.denominator(12) + sage: p1 = c1.numerator(13); q1 = c1.denominator(13) + sage: num = (q0*a1 - p0); num.n() + 1.49011611938477e-8 + sage: den = (q1*a1 - p1); den.n() + -2.98023223876953e-8 + sage: a1 = -num/den + sage: RIF(a1) + [-infinity .. +infinity] + + The same computation with an element of a number field instead of + ``pi`` gives a very satisfactory answer:: + + sage: K. = NumberField(x^3 - 2, embedding=1.25) + sage: c2 = continued_fraction(a2) + sage: p0 = c2.numerator(111); q0 = c2.denominator(111) + sage: p1 = c2.numerator(112); q1 = c2.denominator(112) + sage: num = (q0*a2 - p0); num.n() + -4.56719261665907e46 + sage: den = (q1*a2 - p1); den.n() + -3.65375409332726e47 + sage: a2 = -num/den + sage: b2 = RIF(a2); b2 + 1.002685823312715? + sage: b2.absolute_diameter() + 8.88178419700125e-16 + + The consequence is that the precision needed with ``c1`` grows when we + compute larger and larger partial quotients:: + + sage: c1.quotient(100) + 2 + sage: c1._xa.parent() + Real Interval Field with 353 bits of precision + sage: c1.quotient(200) + 3 + sage: c1._xa.parent() + Real Interval Field with 753 bits of precision + sage: c1.quotient(300) + 5 + sage: c1._xa.parent() + Real Interval Field with 1053 bits of precision + + sage: c2.quotient(200) + 6 + sage: c2._xa.parent() + Real Interval Field with 53 bits of precision + sage: c2.quotient(500) + 1 + sage: c2._xa.parent() + Real Interval Field with 53 bits of precision + sage: c2.quotient(1000) + 1 + sage: c2._xa.parent() + Real Interval Field with 53 bits of precision + """ + x = self._xa + + if len(self._quotients) > 1 and n >= len(self._quotients) and self._quotients[-1] == 0: + return ZZ_0 + + for k in xrange(len(self._quotients), n+1): + if x.lower().is_infinity() or x.upper().is_infinity() or x.lower().floor() != x.upper().floor(): + orbit = lambda z: -(self.denominator(k-2)*z-self.numerator(k-2))/(self.denominator(k-1)*z-self.numerator(k-1)) + x = x.parent()(orbit(self._x0)) + + # It may happen that the above line fails to give an + # approximation with the expected number of digits (see the + # examples). In that case, we augment the precision. + while x.lower().is_infinity() or x.upper().is_infinity() or x.lower().floor() != x.upper().floor(): + from real_mpfi import RealIntervalField + self._prec = x.parent().prec() + 100 + x = RealIntervalField(self._prec)(orbit(self._x0)) + + self._quotients.append(x.unique_floor()) + x = (x-x.unique_floor()) + if not x: + self._quotients.append(ZZ_0) + return ZZ_0 + x = ~x + + self._xa = x + return self._quotients[n] + + def value(self): + r""" + Return the value of ``self`` (the number from which it was built). + + EXAMPLES:: + + sage: cf = continued_fraction(e) + sage: cf.value() + e + """ + return self._x0 + + +class ContinuedFraction_infinite(ContinuedFraction_base): + r""" + A continued fraction defined by an infinite sequence of partial quotients. + + EXAMPLES:: + + sage: t = continued_fraction(words.ThueMorseWord([1,2])); t + [1; 2, 2, 1, 2, 1, 1, 2, 2, 1...] + sage: t.n(digits=100) + 1.422388736882785488341547116024565825306879108991711829311892452916456747272565883312455412962072042 + + We check that comparisons work well:: + + sage: t > continued_fraction(1) and t < continued_fraction(3/2) + True + sage: t < continued_fraction(1) or t > continued_fraction(2) + False + + Can also be called with a ``value`` option:: + + sage: def f(n): + ....: if n % 3 == 2: return 2*(n+1)//3 + ....: return 1 + sage: w = Word(f, alphabet=NN) + sage: w + word: 1,1,2,1,1,4,1,1,6,1,1,8,1,1,10,1,1,12,1,1,14,1,1,16,1,1,18,1,1,20,1,1,22,1,1,24,1,1,26,1,... + sage: cf = continued_fraction(w, value=e-1) + sage: cf + [1; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1...] + + In that case a small check is done on the input:: + + sage: cf = continued_fraction(w, value=pi) + Traceback (most recent call last): + ... + ValueError: value evaluates to 3.141592653589794? while the continued fraction evaluates to 1.718281828459046? in Real Interval Field with 53 bits of precision. + + """ + def __init__(self, w, value=None, check=True): + r""" + INPUT: + + - ``parent`` - a parent + + - ``w`` - an infinite list + + - ``value`` - an optional known value + + - ``check`` - whether the constructor checks the input (default is + ``True``) + + TESTS:: + + sage: w = words.FibonacciWord(['a','b']) + sage: continued_fraction(w) + Traceback (most recent call last): + ... + ValueError: the sequence must consist of integers + + sage: from itertools import count + sage: w = Word(count()) + sage: continued_fraction(w) + [0; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19...] + + sage: continued_fraction(words.FibonacciWord([0,1])) + Traceback (most recent call last): + ... + ValueError: only the first partial quotient can be null + + sage: w = words.ThueMorseWord([int(1), int(2)]) + sage: t = continued_fraction(w) + sage: type(t.quotient(1)) + + """ + ContinuedFraction_base.__init__(self) + self._w = w + + if check: + for i in xrange(10): + k = w[i] + if not isinstance(k, Integer): + try: + k = Integer(w[i]) + except (TypeError,ValueError): + raise ValueError("the sequence must consist of integers") + self.quotient = self._Integer_quotient + + if not k and i: + raise ValueError("only the first partial quotient can be null") + + if check and value is not None: + from sage.rings.real_mpfi import RealIntervalField + R = RealIntervalField(53) + x = R(value) + y = R(self) + if x.lower() > y.lower() or x.upper() < y.upper(): + raise ValueError("value evaluates to %s while the continued fraction evaluates to %s in %s."%(x,y,R)) + + self._value = value + + def _repr_(self): + r""" + String representation. + + EXAMPLES:: + + sage: # TODO + """ + return "[" + str(self._w[0]) + "; " + ", ".join(map(str,self._w[1:20])) + "...]" + + def length(self): + r""" + Returns infinity. + + EXAMPLES:: + + sage: w = words.FibonacciWord([3,13]) + sage: cf = continued_fraction(w) + sage: cf.length() + +Infinity + """ + return Infinity + + def quotient(self, n): + r""" + The ``n``-th partial quotient of ``self``. + + EXAMPLES:: + + sage: w = words.FibonacciWord([1,3]) + sage: cf = continued_fraction(w) + sage: cf.quotient(0) + 1 + sage: cf.quotient(1) + 3 + sage: cf.quotient(2) + 1 + """ + return self._w[n] + + def quotients(self): + r""" + Return the infinite list from which this continued fraction was built. + + EXAMPLES:: + + sage: w = words.FibonacciWord([1,5]) + sage: cf = continued_fraction(w) + sage: cf.quotients() + word: 1511515115115151151511511515115115151151... + """ + return self._w + + def _Integer_quotient(self, n): + r""" + The ``n``-th partial quotient of ``self``. + + EXAMPLES:: + + sage: w = words.ThueMorseWord([int(1), int(2)]) + sage: t = continued_fraction(w) + sage: t.quotient(0) + 1 + sage: t.quotient(1) + 2 + sage: type(t.quotient(1)) # indirect doctest + + """ + return Integer(self._w[n]) + + def value(self): + r""" + The value of ``self``. + + The method only works if a value was provided in the constructor. + + EXAMPLES:: + + sage: def f(n): + ....: if n % 3 == 2: return 2*(n+1)//3 + ....: return 1 + sage: w = Word(f, alphabet=NN) + sage: w + word: 1,1,2,1,1,4,1,1,6,1,1,8,1,1,10,1,1,12,1,1,14,1,1,16,1,1,18,1,1,20,1,1,22,1,1,24,1,1,26,1,... + sage: cf = continued_fraction(w, value=e-1) + sage: cf + [1; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1...] + sage: cf.value() + e - 1 + """ + if self._value is not None: + return self._value + raise NotImplementedError("Real numbers built from continued fractions are not yet implemented") + +def check_and_reduce_pair(x1,x2=None): + r""" + There are often two ways to represent a given continued fraction. This + function makes it canonical. + + In the very special case of the number `0` we return the pair + ``((0,),(0,))``. + + TESTS:: + + sage: from sage.rings.continued_fraction import check_and_reduce_pair + sage: check_and_reduce_pair([]) + ((0,), (+Infinity,)) + sage: check_and_reduce_pair([-1,1]) + ((0,), (+Infinity,)) + sage: check_and_reduce_pair([1,1,1]) + ((1, 2), (+Infinity,)) + sage: check_and_reduce_pair([1,3],[2,3]) + ((1,), (3, 2)) + sage: check_and_reduce_pair([1,2,3],[2,3,2,3,2,3]) + ((1,), (2, 3)) + sage: check_and_reduce_pair([1,2],[]) + ((1, 2), (+Infinity,)) + """ + y1 = map(Integer,x1) + + if x2 is None or not x2 or x2[0] is Infinity: + y2 = [Infinity] + if not y1: + y1 = [ZZ_0] + elif len(y1) > 1 and y1[-1] == 1: + y1.pop(-1) + y1[-1] += 1 + + else: + y2 = map(Integer,x2) + if any(b <= ZZ_0 for b in y2): + raise ValueError("the elements of the period can not be negative") + + # add possibly some element of x1 into the period + while y1 and y1[-1] == y2[-1]: + y1.pop(-1) + y2.insert(0,y2.pop(-1)) + + # some special cases to treat + if len(y2) == 1 and y2[0] == 0: + if not y1: + y1 = [ZZ_0] + elif len(y1) > 1 and y1[-1] == 1: + y1.pop(-1) + y1[-1] += 1 + + # check that y2 is not a pure power (in a very naive way!!) + n2 = len(y2) + for i in xrange(1,(n2+2)/2): + if n2 % i == 0 and y2[:-i] == y2[i:]: + y2 = y2[:i] + break + + # check that at then end y1 has no zeros in it + for i in xrange(1,len(y1)): + if y1[i] <= 0: + raise ValueError("all quotient except the first must be positive") + + return tuple(y1),tuple(y2) + + +def continued_fraction_list(x, type="std", partial_convergents=False, bits=None, nterms=None): + r""" + Returns the (finite) continued fraction of ``x`` as a list. + + The continued fraction expansion of ``x`` are the coefficients `a_i` in + + .. MATH:: + + x = a_0 + 1/(a_1 + 1/(...)) + + with `a_0` integer and `a_1`, `...` positive integers. The Hirzebruch-Jung + continued fraction is the one for which the `+` signs are replaced with `-` + signs + + .. MATH:: + + x = a_0 - 1/(a_1 - 1/(...)) + + .. SEEALSO:: + + :func:`continued_fraction` + + INPUT: + + - ``x`` -- exact rational or floating-point number. The number to + compute the continued fraction of. + + - ``type`` -- either "std" (default) for standard continued fractions or + "hj" for Hirzebruch-Jung ones. + + - ``partial_convergents`` -- boolean. Whether to return the partial convergents. + + - ``bits`` -- an optional integer that specify a precision for the real + interval field that is used internally. + + - ``nterms`` -- integer. The upper bound on the number of terms in + the continued fraction expansion to return. + + OUTPUT: + + A lits of integers, the coefficients in the continued fraction expansion of + ``x``. If ``partial_convergents`` is set to ``True``, then return a pair + containing the coefficient list and the partial convergents list is + returned. + + EXAMPLES:: + + sage: continued_fraction_list(45/19) + [2, 2, 1, 2, 2] + sage: 2 + 1/(2 + 1/(1 + 1/(2 + 1/2))) + 45/19 + + sage: continued_fraction_list(45/19,type="hj") + [3, 2, 3, 2, 3] + sage: 3 - 1/(2 - 1/(3 - 1/(2 - 1/3))) + 45/19 + + Specifying ``bits`` or ``nterms`` modify the length of the output:: + + sage: continued_fraction_list(e, bits=20) + [2, 1, 2, 1, 1, 4, 2] + sage: continued_fraction_list(sqrt(2)+sqrt(3), bits=30) + [3, 6, 1, 5, 7, 2] + sage: continued_fraction_list(pi, bits=53) + [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] + + sage: continued_fraction_list(log(3/2), nterms=15) + [0, 2, 2, 6, 1, 11, 2, 1, 2, 2, 1, 4, 3, 1, 1] + sage: continued_fraction_list(tan(sqrt(pi)), nterms=20) + [-5, 9, 4, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 2, 4, 3, 1, 63] + + When the continued fraction is infinite (ie ``x`` is an irrational number) + and the parameters ``bits`` and ``nterms`` are not specified then a warning + is raised:: + + sage: continued_fraction_list(sqrt(2)) + doctest:...: UserWarning: the continued fraction of sqrt(2) seems infinite, return only the first 20 terms + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] + sage: continued_fraction_list(sqrt(4/19)) + doctest:...: UserWarning: the continued fraction of 2*sqrt(1/19) seems infinite, return only the first 20 terms + [0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 16] + + An examples with the list of partial convergents:: + + sage: continued_fraction_list(RR(pi), partial_convergents=True) + ([3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3], + [(3, 1), + (22, 7), + (333, 106), + (355, 113), + (103993, 33102), + (104348, 33215), + (208341, 66317), + (312689, 99532), + (833719, 265381), + (1146408, 364913), + (4272943, 1360120), + (5419351, 1725033), + (80143857, 25510582), + (245850922, 78256779)]) + + TESTS:: + + sage: continued_fraction_list(1 + 10^-10, nterms=3) + [1, 10000000000] + sage: continued_fraction_list(1 + 10^-20 - e^-100, nterms=3) + [1, 100000000000000000000, 2688] + sage: continued_fraction_list(1 + 10^-20 - e^-100, nterms=5) + [1, 100000000000000000000, 2688, 8, 1] + sage: continued_fraction_list(1 + 10^-20 - e^-100, nterms=5) + [1, 100000000000000000000, 2688, 8, 1] + """ + from rational_field import QQ + + try: + return x.continued_fraction_list(type=type) + except AttributeError: + pass + + if bits is not None: + from real_mpfi import RealIntervalField + x = RealIntervalField(bits)(x) + + if type == "hj": + l = QQ(x).continued_fraction_list("hj") + ## The C-code in sage.rings.rational is much more faster than the pure + ## Python below + ## v = [] + ## while True: + ## div, mod = divmod(x.numerator(), x.denominator()) + ## if mod == 0: + ## v.append(div) + ## break + ## v.append(div+1) + ## if nterms is not None and len(v) >= nterms: + ## break + ## x = 1/(div+1-x) + ## return v + if nterms is None: + return l + return l[:nterms] + + if type != "std": + raise ValueError("type must be either \"std\" or \"hj\"") + + cf = None + + from sage.rings.real_mpfi import is_RealIntervalField + if is_RealIntervalField(x.parent()): + cf = continued_fraction(rat_interval_cf_list( + x.lower().exact_rational(), + x.upper().exact_rational())) + + if cf is None: + try: + cf = continued_fraction(x) + except ValueError: + pass + + if cf is None: + raise ValueError("does not know how to compute the continued fraction of %s"%x) + + if nterms: + limit = min(cf.length(), nterms) + elif cf.length() != Infinity: + limit = cf.length() + else: + import warnings + warnings.warn("the continued fraction of %s seems infinite, return only the first 20 terms" % x) + limit = 20 + if partial_convergents: + return [cf.quotient(i) for i in xrange(limit)], [(cf.numerator(i),cf.denominator(i)) for i in xrange(limit)] + return [cf.quotient(i) for i in xrange(limit)] + + + + +def continued_fraction(x, value=None): + r""" + Return the continued fraction of ``x``. + + INPUT: + + - `x` -- a number or a list of partial quotients (for finite + development) or two list of partial quotients (preperiod and period + for ultimately periodic development) + + EXAMPLES: + + A finite continued fraction may be initialized by a number or by its list of + partial quotients:: + + sage: continued_fraction(12/571) + [0; 47, 1, 1, 2, 2] + sage: continued_fraction([3,2,1,4]) + [3; 2, 1, 4] + + It can be called with elements defined from symbolic values, in which case + the partial quotients are evaluated in a lazy way:: + + sage: c = continued_fraction(golden_ratio); c + [1; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...] + sage: c.convergent(12) + 377/233 + sage: fibonacci(14)/fibonacci(13) + 377/233 + + sage: continued_fraction(pi) + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: c = continued_fraction(pi); c + [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] + sage: a = c.convergent(3); a + 355/113 + sage: a.n() + 3.14159292035398 + sage: pi.n() + 3.14159265358979 + + sage: continued_fraction(sqrt(2)) + [1; 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...] + sage: continued_fraction(tan(1)) + [1; 1, 1, 3, 1, 5, 1, 7, 1, 9, 1, 11, 1, 13, 1, 15, 1, 17, 1, 19, ...] + sage: continued_fraction(tanh(1)) + [0; 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, ...] + sage: continued_fraction(e) + [2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, ...] + + If you want to play with quadratic numbers (such as ``golden_ratio`` and + ``sqrt(2)`` above), it is much more convenient to use number fields as + follows since preperiods and periods are computed:: + + sage: K. = NumberField(x^2-5, embedding=2.23) + sage: my_golden_ratio = (1 + sqrt5)/2 + sage: cf = continued_fraction((1+sqrt5)/2); cf + [(1)*] + sage: cf.convergent(12) + 377/233 + sage: cf.period() + (1,) + sage: cf = continued_fraction(2/3+sqrt5/5); cf + [1; 8, (1, 3, 1, 1, 3, 9)*] + sage: cf.preperiod() + (1, 8) + sage: cf.period() + (1, 3, 1, 1, 3, 9) + + sage: L. = NumberField(x^2-2, embedding=1.41) + sage: cf = continued_fraction(sqrt2); cf + [1; (2)*] + sage: cf.period() + (2,) + sage: cf = continued_fraction(sqrt2/3); cf + [0; 2, (8, 4)*] + sage: cf.period() + (8, 4) + + It is also possible to go the other way around, build a ultimately periodic + continued fraction from its preperiod and its period and get its value + back:: + + sage: cf = continued_fraction([(1,1),(2,8)]); cf + [1; 1, (2, 8)*] + sage: cf.value() + 2/11*sqrt5 + 14/11 + + It is possible to deal with higher degree number fields but in that case the + continued fraction expansion is known to be aperiodic:: + + sage: K. = NumberField(x^3-2, embedding=1.25) + sage: cf = continued_fraction(a); cf + [1; 3, 1, 5, 1, 1, 4, 1, 1, 8, 1, 14, 1, 10, 2, 1, 4, 12, 2, 3, ...] + + Note that initial rounding can result in incorrect trailing partial + quotients:: + + sage: continued_fraction(RealField(39)(e)) + [2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 2] + + Note the value returned for floating point number is the continued fraction + associated to the rational number you obtain with a conversion:: + + sage: for _ in xrange(10): + ....: x = RR.random_element() + ....: cff = continued_fraction(x) + ....: cfe = QQ(x).continued_fraction() + ....: assert cff == cfe, "%s %s %s"%(x,cff,cfe) + """ + + if isinstance(x, ContinuedFraction_base): + return x + + try: + return x.continued_fraction() + except AttributeError: + pass + + # input for finite or ultimately periodic partial quotient expansion + from sage.combinat.words.finite_word import FiniteWord_class + if isinstance(x, FiniteWord_class): + x = list(x) + + if isinstance(x, (list, tuple)): + if len(x) == 2 and isinstance(x[0], (list,tuple)) and isinstance(x[1], (list,tuple)): + x1 = tuple(Integer(a) for a in x[0]) + x2 = tuple(Integer(a) for a in x[1]) + x1, x2 = check_and_reduce_pair(x1, x2) + else: + x1, x2 = check_and_reduce_pair(x) + return ContinuedFraction_periodic(x1, x2) + + # input for infinite partial quotient expansion + from sage.misc.lazy_list import lazy_list + from sage.combinat.words.infinite_word import InfiniteWord_class + if isinstance(x, (lazy_list, InfiniteWord_class)): + return ContinuedFraction_infinite(x, value) + + # input for numbers + #TODO: the approach used below might be not what the user expects as we + # have currently in sage (version 6.2) + # sage: RR.random_element() in QQ + # True + from rational_field import QQ + if x in QQ: + return QQ(x).continued_fraction() + + is_real = False + try: + is_real = x.is_real() + except AttributeError: + pass + + if is_real is False: + # we can not rely on the answer of .is_real() for elements of the + # symbolic ring. The thing below is a dirty temporary hack. + from real_mpfi import RealIntervalField + RIF = RealIntervalField(53) + try: + RIF(x) + is_real = True + except (AttributeError,ValueError): + pass + + if is_real is False: + raise ValueError("the number %s does not seem to be a real number"%x) + + if x.parent().is_exact(): + return ContinuedFraction_real(x) + + # we treat separatly the symbolic ring that holds all constants and + # which is not exact + from sage.symbolic.ring import SR + if x.parent() == SR: + return ContinuedFraction_real(x) + + raise ValueError("does not know how to compute the continued fraction of %s, try the function continued_fraction_list instead"%x) + +def Hirzebruch_Jung_continued_fraction_list(x, bits=None, nterms=None): + r""" + Return the Hirzebruch-Jung continued fraction of ``x`` as a list. + + This function is deprecated since :trac:`14567`. See + :func:`continued_fraction_list` and the documentation therein. + + INPUT: + + - ``x`` -- exact rational or something that can be numerically + evaluated. The number to compute the continued fraction of. + + - ``bits`` -- integer (default: the precision of ``x``). the + precision of the real interval field that is used + internally. This is only used if ``x`` is not an exact fraction. + + - ``nterms`` -- integer (default: None). The upper bound on the + number of terms in the continued fraction expansion to return. + A lits of integers, the coefficients in the Hirzebruch-Jung continued + fraction expansion of ``x``. + + EXAMPLES:: + + sage: Hirzebruch_Jung_continued_fraction_list(17/11) + doctest:...: DeprecationWarning: Hirzebruch_Jung_continued_fraction_list(x) is replaced by + continued_fraction_list(x,type="hj") + or for rationals + x.continued_fraction_list(type="hj") + See http://trac.sagemath.org/14567 for details. + [2, 3, 2, 2, 2, 2] + """ + from sage.misc.superseded import deprecation + deprecation(14567, 'Hirzebruch_Jung_continued_fraction_list(x) is replaced by\n\tcontinued_fraction_list(x,type="hj")\nor for rationals\n\tx.continued_fraction_list(type="hj")') + return continued_fraction_list(x, type="hj", bits=bits, nterms=nterms) + +def convergents(x): + r""" + Return the (partial) convergents of the number ``x``. + + EXAMPLES:: + + sage: convergents(143/255) + [0, 1, 1/2, 4/7, 5/9, 9/16, 14/25, 23/41, 60/107, 143/255] + """ + return continued_fraction(x).convergents() + +def farey(v, lim): + """ + Return the Farey sequence associated to the floating point number + v. + + INPUT: + + + - ``v`` - float (automatically converted to a float) + + - ``lim`` - maximum denominator. + + + OUTPUT: Results are (numerator, denominator); (1, 0) is "infinity". + + EXAMPLES:: + + sage: farey(2.0, 100) + doctest:...: DeprecationWarning: farey is deprecated. + See http://trac.sagemath.org/14567 for details. + (2, 1) + sage: farey(2.0, 1000) + (2, 1) + sage: farey(2.1, 1000) + (21, 10) + sage: farey(2.1, 100000) + (21, 10) + sage: farey(pi, 100000) + (312689, 99532) + + AUTHORS: + + - Scott David Daniels: Python Cookbook, 2nd Ed., Recipe 18.13 + """ + from sage.misc.superseded import deprecation + deprecation(14567, 'farey is deprecated.') + + v = float(v) + if v < 0: + n, d = farey(-v, lim) + return -n, d + z = lim - lim # Get a "0 of the right type" for denominator + lower, upper = (z, z+1), (z+1, z) + while True: + mediant = (lower[0] + upper[0]), (lower[1] + upper[1]) + if v * mediant[1] > mediant[0]: + if lim < mediant[1]: + return upper + lower = mediant + elif v * mediant[1] == mediant[0]: + if lim >= mediant[1]: + return mediant + if lower[1] < upper[1]: + return lower + return upper + else: + if lim < mediant[1]: + return lower + upper = mediant + + diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index d9ad7c017a1..3e4e2434803 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -1839,7 +1839,7 @@ cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givar if cache._has_array: return cache._array[x] else: - y = PY_NEW(FiniteField_givaroElement) + y = FiniteField_givaroElement.__new__(FiniteField_givaroElement) y._parent = cache.parent y._cache = cache y.element = x diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 0b855299923..5b5d176a37a 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -226,7 +226,7 @@ cdef class Cache_ntl_gf2e(SageObject): """ cdef FiniteField_ntl_gf2eElement y self.F.restore() - y = PY_NEW(FiniteField_ntl_gf2eElement) + y = FiniteField_ntl_gf2eElement.__new__(FiniteField_ntl_gf2eElement) y._parent = self._parent y._cache = self return y @@ -527,7 +527,7 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): cdef FiniteField_ntl_gf2eElement _new(FiniteField_ntl_gf2eElement self): cdef FiniteField_ntl_gf2eElement y (self._parent._cache).F.restore() - y = PY_NEW(FiniteField_ntl_gf2eElement) + y = FiniteField_ntl_gf2eElement.__new__(FiniteField_ntl_gf2eElement) y._parent = self._parent y._cache = self._cache return y diff --git a/src/sage/rings/finite_rings/element_pari_ffelt.pyx b/src/sage/rings/finite_rings/element_pari_ffelt.pyx index baefde1b346..4adbfedca2b 100644 --- a/src/sage/rings/finite_rings/element_pari_ffelt.pyx +++ b/src/sage/rings/finite_rings/element_pari_ffelt.pyx @@ -639,7 +639,7 @@ cdef class FiniteFieldElement_pari_ffelt(FinitePolyExtElement): """ if exp == 0: - return self._parent.one_element() + return self._parent.one() if exp < 0 and FF_equal0(self.val): raise ZeroDivisionError exp = Integer(exp)._pari_() diff --git a/src/sage/rings/finite_rings/finite_field_base.pyx b/src/sage/rings/finite_rings/finite_field_base.pyx index 3b2a89e6d8b..90924756205 100644 --- a/src/sage/rings/finite_rings/finite_field_base.pyx +++ b/src/sage/rings/finite_rings/finite_field_base.pyx @@ -1062,7 +1062,7 @@ cdef class FiniteField(Field): if R is int or R is long or R is ZZ: return True if is_IntegerModRing(R) and self.characteristic().divides(R.characteristic()): - return R.hom((self.one_element(),), check=False) + return R.hom((self.one(),), check=False) if is_FiniteField(R): if R is self: return True @@ -1071,7 +1071,7 @@ cdef class FiniteField(Field): return False if R.characteristic() == self.characteristic(): if R.degree() == 1: - return R.hom((self.one_element(),), check=False) + return R.hom((self.one(),), check=False) elif (R.degree().divides(self.degree()) and hasattr(self, '_prefix') and hasattr(R, '_prefix')): return R.hom((self.gen() ** ((self.order() - 1)//(R.order() - 1)),)) diff --git a/src/sage/rings/finite_rings/finite_field_prime_modn.py b/src/sage/rings/finite_rings/finite_field_prime_modn.py index 235a767ab43..1dcee12e521 100644 --- a/src/sage/rings/finite_rings/finite_field_prime_modn.py +++ b/src/sage/rings/finite_rings/finite_field_prime_modn.py @@ -254,7 +254,7 @@ def gen(self, n=0): try: self.__gen = -(self._modulus[0]) except AttributeError: - self.__gen = self.one_element() + self.__gen = self.one() return self.__gen def __iter__(self): @@ -271,11 +271,11 @@ def __iter__(self): sage: K = GF(next_prime(2^256)) sage: all = iter(K) - sage: all.next() + sage: next(all) 0 - sage: all.next() + sage: next(all) 1 - sage: all.next() + sage: next(all) 2 """ yield self(0) diff --git a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx index 36120165a40..cd76fdfbc7e 100644 --- a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx +++ b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx @@ -259,7 +259,7 @@ cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givar if cache._has_array: return cache._array[x] else: - y = PY_NEW(FiniteField_givaroElement) + y = FiniteField_givaroElement.__new__(FiniteField_givaroElement) y._parent = cache.parent y._cache = cache y.element = x diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index bff871f3cd6..6fd4d810929 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -307,8 +307,8 @@ cdef class IntegerMod_abstract(FiniteRingElement): cdef _new_c_from_long(self, long value): - cdef IntegerMod_abstract x - x = PY_NEW(PY_TYPE(self)) + cdef type t = type(self) + cdef IntegerMod_abstract x = t.__new__(t) if PY_TYPE_CHECK(x, IntegerMod_gmp): mpz_init((x).value) # should be done by the new method x._parent = self._parent @@ -1722,7 +1722,7 @@ cdef class IntegerMod_gmp(IntegerMod_abstract): cdef IntegerMod_gmp _new_c(self): cdef IntegerMod_gmp x - x = PY_NEW(IntegerMod_gmp) + x = IntegerMod_gmp.__new__(IntegerMod_gmp) mpz_init(x.value) x.__modulus = self.__modulus x._parent = self._parent @@ -2228,7 +2228,7 @@ cdef class IntegerMod_int(IntegerMod_abstract): self.set_from_mpz(z.value) def _make_new_with_parent_c(self, parent): #ParentWithBase parent): - cdef IntegerMod_int x = PY_NEW(IntegerMod_int) + cdef IntegerMod_int x = IntegerMod_int.__new__(IntegerMod_int) x._parent = parent x.__modulus = parent._pyx_order x.ivalue = self.ivalue @@ -2237,7 +2237,7 @@ cdef class IntegerMod_int(IntegerMod_abstract): cdef IntegerMod_int _new_c(self, int_fast32_t value): if self.__modulus.table is not None: return self.__modulus.lookup(value) - cdef IntegerMod_int x = PY_NEW(IntegerMod_int) + cdef IntegerMod_int x = IntegerMod_int.__new__(IntegerMod_int) x._parent = self._parent x.__modulus = self.__modulus x.ivalue = value @@ -2367,7 +2367,7 @@ cdef class IntegerMod_int(IntegerMod_abstract): def __copy__(IntegerMod_int self): - cdef IntegerMod_int x = PY_NEW(IntegerMod_int) + cdef IntegerMod_int x = IntegerMod_int.__new__(IntegerMod_int) x._parent = self._parent x.__modulus = self.__modulus x.ivalue = self.ivalue @@ -2637,7 +2637,7 @@ cdef class IntegerMod_int(IntegerMod_abstract): cdef mpz_t res_mpz if PyInt_CheckExact(exp) and -100000 < PyInt_AS_LONG(exp) < 100000: long_exp = PyInt_AS_LONG(exp) - elif PY_TYPE_CHECK_EXACT(exp, Integer) and mpz_cmpabs_ui((exp).value, 100000) == -1: + elif type(exp) is Integer and mpz_cmpabs_ui((exp).value, 100000) == -1: long_exp = mpz_get_si((exp).value) else: sig_on() @@ -3110,7 +3110,7 @@ cdef class IntegerMod_int64(IntegerMod_abstract): cdef IntegerMod_int64 _new_c(self, int_fast64_t value): cdef IntegerMod_int64 x - x = PY_NEW(IntegerMod_int64) + x = IntegerMod_int64.__new__(IntegerMod_int64) x.__modulus = self.__modulus x._parent = self._parent x.ivalue = value @@ -3510,7 +3510,7 @@ cdef class IntegerMod_int64(IntegerMod_abstract): cdef mpz_t res_mpz if PyInt_CheckExact(exp) and -100000 < PyInt_AS_LONG(exp) < 100000: long_exp = PyInt_AS_LONG(exp) - elif PY_TYPE_CHECK_EXACT(exp, Integer) and mpz_cmpabs_ui((exp).value, 100000) == -1: + elif type(exp) is Integer and mpz_cmpabs_ui((exp).value, 100000) == -1: long_exp = mpz_get_si((exp).value) else: sig_on() @@ -3646,7 +3646,7 @@ cdef mpz_pow_helper(mpz_t res, mpz_t base, object exp, mpz_t modulus): invert = True mpz_powm_ui(res, base, long_exp, modulus) else: - if not PY_TYPE_CHECK_EXACT(exp, Integer): + if type(exp) is not Integer: exp = Integer(exp) if mpz_sgn((exp).value) < 0: exp = -exp diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index 1fe168ae3ae..8fd36848fa7 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -631,7 +631,7 @@ def gen(self, i=0): z3 """ x = self._R.gen(i) - one = self._R.one_element() + one = self._R.one() r = self._element_class(self, x, one, coerce=False, reduce=False) return r diff --git a/src/sage/rings/fraction_field_FpT.pyx b/src/sage/rings/fraction_field_FpT.pyx index 0289fe782da..032ba0e9b64 100644 --- a/src/sage/rings/fraction_field_FpT.pyx +++ b/src/sage/rings/fraction_field_FpT.pyx @@ -148,7 +148,7 @@ cdef class FpTElement(RingElement): """ Creates a new FpTElement in the same field, leaving the value to be initialized. """ - cdef FpTElement x = PY_NEW(FpTElement) + cdef FpTElement x = FpTElement.__new__(FpTElement) x._parent = self._parent x.p = self.p nmod_poly_init_preinv(x._numer, x.p, self._numer.mod.ninv) @@ -160,7 +160,7 @@ cdef class FpTElement(RingElement): """ Creates a new FpTElement in the same field, with the same value as self. """ - cdef FpTElement x = PY_NEW(FpTElement) + cdef FpTElement x = FpTElement.__new__(FpTElement) x._parent = self._parent x.p = self.p nmod_poly_init2_preinv(x._numer, x.p, self._numer.mod.ninv, self._numer.length) @@ -194,7 +194,7 @@ cdef class FpTElement(RingElement): sage: a.numerator() t^6 + 3*t^4 + 10*t^3 + 3*t^2 + 1 """ - cdef Polynomial_zmod_flint res = PY_NEW(Polynomial_zmod_flint) + cdef Polynomial_zmod_flint res = Polynomial_zmod_flint.__new__(Polynomial_zmod_flint) nmod_poly_init2_preinv(&res.x, self.p, self._numer.mod.ninv, self._numer.length) nmod_poly_set(&res.x, self._numer) res._parent = self._parent.poly_ring @@ -225,7 +225,7 @@ cdef class FpTElement(RingElement): sage: a.denominator() t^3 """ - cdef Polynomial_zmod_flint res = PY_NEW(Polynomial_zmod_flint) + cdef Polynomial_zmod_flint res = Polynomial_zmod_flint.__new__(Polynomial_zmod_flint) nmod_poly_init2_preinv(&res.x, self.p, self._denom.mod.ninv, self._denom.length) nmod_poly_set(&res.x, self._denom) res._parent = self._parent.poly_ring @@ -1076,7 +1076,7 @@ cdef class Polyring_FpT_coerce(RingHomomorphism_coercion): t^2 + 1 """ cdef Polynomial_zmod_flint x = _x - cdef FpTElement ans = PY_NEW(FpTElement) + cdef FpTElement ans = FpTElement.__new__(FpTElement) ans._parent = self.codomain() ans.p = self.p nmod_poly_init(ans._numer, ans.p) @@ -1132,7 +1132,7 @@ cdef class Polyring_FpT_coerce(RingHomomorphism_coercion): x = _x except TypeError: raise NotImplementedError('Fraction fields not implemented for this type.') - cdef FpTElement ans = PY_NEW(FpTElement) + cdef FpTElement ans = FpTElement.__new__(FpTElement) ans._parent = self.codomain() ans.p = self.p nmod_poly_init(ans._numer, ans.p) @@ -1287,7 +1287,7 @@ cdef class FpT_Polyring_section(Section): normalize(x._numer, x._denom, self.p) if nmod_poly_degree(x._denom) != 0: raise ValueError, "not integral" - ans = PY_NEW(Polynomial_zmod_flint) + ans = Polynomial_zmod_flint.__new__(Polynomial_zmod_flint) if nmod_poly_get_coeff_ui(x._denom, 0) != 1: normalize(x._numer, x._denom, self.p) nmod_poly_init(&ans.x, self.p) @@ -1376,7 +1376,7 @@ cdef class Fp_FpT_coerce(RingHomomorphism_coercion): 3 """ cdef IntegerMod_int x = _x - cdef FpTElement ans = PY_NEW(FpTElement) + cdef FpTElement ans = FpTElement.__new__(FpTElement) ans._parent = self.codomain() ans.p = self.p nmod_poly_init(ans._numer, ans.p) @@ -1405,7 +1405,7 @@ cdef class Fp_FpT_coerce(RingHomomorphism_coercion): 2/2*t """ cdef IntegerMod_int x = _x - cdef FpTElement ans = PY_NEW(FpTElement) + cdef FpTElement ans = FpTElement.__new__(FpTElement) ans._parent = self.codomain() ans.p = self.p nmod_poly_init(ans._numer, ans.p) @@ -1585,7 +1585,7 @@ cdef class FpT_Fp_section(Section): raise ValueError, "not integral" if nmod_poly_degree(x._numer) > 0: raise ValueError, "not constant" - ans = PY_NEW(IntegerMod_int) + ans = IntegerMod_int.__new__(IntegerMod_int) ans._parent = self.codomain() ans.__modulus = ans._parent._pyx_order if nmod_poly_get_coeff_ui(x._denom, 0) != 1: @@ -1677,7 +1677,7 @@ cdef class ZZ_FpT_coerce(RingHomomorphism_coercion): 3 """ cdef Integer x = _x - cdef FpTElement ans = PY_NEW(FpTElement) + cdef FpTElement ans = FpTElement.__new__(FpTElement) ans._parent = self.codomain() ans.p = self.p nmod_poly_init(ans._numer, ans.p) @@ -1708,7 +1708,7 @@ cdef class ZZ_FpT_coerce(RingHomomorphism_coercion): 2/2*t """ cdef Integer x = _x - cdef FpTElement ans = PY_NEW(FpTElement) + cdef FpTElement ans = FpTElement.__new__(FpTElement) ans._parent = self.codomain() ans.p = self.p nmod_poly_init(ans._numer, ans.p) diff --git a/src/sage/rings/fraction_field_element.pyx b/src/sage/rings/fraction_field_element.pyx index 21255278950..b55bf42dc07 100644 --- a/src/sage/rings/fraction_field_element.pyx +++ b/src/sage/rings/fraction_field_element.pyx @@ -90,9 +90,9 @@ cdef class FractionFieldElement(FieldElement): sage: P. = QQ[] sage: F = P.fraction_field() - sage: P.one_element()//F.one_element() + sage: P.one()//F.one() 1 - sage: F.one_element().quo_rem(F.one_element()) + sage: F.one().quo_rem(F.one()) (1, 0) """ cdef object __numerator @@ -190,7 +190,7 @@ cdef class FractionFieldElement(FieldElement): if not den.is_one() and den.is_unit(): try: num *= den.inverse_of_unit() - den = den.parent().one_element() + den = den.parent().one() except Exception: pass self.__numerator = num @@ -529,7 +529,7 @@ cdef class FractionFieldElement(FieldElement): tnum = rnum * sden + rden * snum if tnum.is_zero(): return self.__class__(self._parent, tnum, - self._parent.ring().one_element(), coerce=False, + self._parent.ring().one(), coerce=False, reduce=False) else: tden = self.__denominator * sden @@ -540,7 +540,7 @@ cdef class FractionFieldElement(FieldElement): if not tden.is_one() and tden.is_unit(): try: tnum = tnum * tden.inverse_of_unit() - tden = self._parent.ring().one_element() + tden = self._parent.ring().one() except AttributeError: pass except NotImplementedError: @@ -608,7 +608,7 @@ cdef class FractionFieldElement(FieldElement): sden = ( right).__denominator if (rnum.is_zero() or snum.is_zero()): - return self._parent.zero_element() + return self._parent.zero() if self._parent.is_exact(): try: @@ -625,7 +625,7 @@ cdef class FractionFieldElement(FieldElement): if not tden.is_one() and tden.is_unit(): try: tnum = tnum * tden.inverse_of_unit() - tden = self._parent.ring().one_element() + tden = self._parent.ring().one() except AttributeError: pass except NotImplementedError: @@ -780,7 +780,7 @@ cdef class FractionFieldElement(FieldElement): if right == 0: R = self.parent().ring() return self.__class__(self.parent(), - R.one_element(), R.one_element(), + R.one(), R.one(), coerce=False, reduce=False) elif right > 0: return self.__class__(self.parent(), diff --git a/src/sage/rings/function_field/function_field_element.pyx b/src/sage/rings/function_field/function_field_element.pyx index 6b623ee2c31..48ded72a3f0 100644 --- a/src/sage/rings/function_field/function_field_element.pyx +++ b/src/sage/rings/function_field/function_field_element.pyx @@ -83,7 +83,8 @@ cdef class FunctionFieldElement(FieldElement): (self._parent, type(self), self._x)) cdef FunctionFieldElement _new_c(self): - cdef FunctionFieldElement x = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef FunctionFieldElement x = t.__new__(t) x._parent = self._parent return x diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index 3bfbeb038ee..ea505a7ac85 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -261,7 +261,7 @@ def __init__(self, ring, gens, coerce=True): gens = [ring(x) for x in gens] gens = tuple(gens) - if len(gens)==0: gens=(ring.zero_element(),) + if len(gens)==0: gens=(ring.zero(),) self.__gens = gens MonoidElement.__init__(self, ring.ideal_monoid()) diff --git a/src/sage/rings/infinity.py b/src/sage/rings/infinity.py index 44c3f460934..3a9577c53be 100644 --- a/src/sage/rings/infinity.py +++ b/src/sage/rings/infinity.py @@ -264,6 +264,22 @@ def _maxima_init_(self): else: return 'inf' + def _fricas_init_(self): + """ + TESTS:: + + sage: fricas(-oo) # optional - fricas + %minusInfinity + sage: [x._fricas_init_() for x in [unsigned_infinity, oo, -oo]] # optional - fricas + ['%infinity', '%plusInfinity', '%minusInfinity'] + """ + if self._sign_char == '': + return r"%infinity" + elif self._sign > 0: + return r"%plusInfinity" + else: + return r"%minusInfinity" + def _pari_(self): """ Convert ``self`` to a Pari object. diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 625fde72cf9..b41b629b2b5 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -147,9 +147,8 @@ from cpython.number cimport * from cpython.int cimport * from libc.stdint cimport uint64_t cimport sage.structure.element -from sage.structure.element cimport Element +from sage.structure.element cimport Element, EuclideanDomainElement, parent_c include "sage/ext/python_debug.pxi" -include "../structure/coerce.pxi" # for parent_c include "sage/libs/pari/decl.pxi" from sage.rings.rational cimport Rational from sage.libs.gmp.rational_reconstruction cimport mpq_rational_reconstruction @@ -1825,7 +1824,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): """ cdef Integer z = PY_NEW(Integer) cdef long yy, res - if PY_TYPE(x) is PY_TYPE(y): + if type(x) is type(y): if not mpz_sgn((y).value): raise ZeroDivisionError, "Integer division by zero" if mpz_size((x).value) > 100000: @@ -2915,7 +2914,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): cdef long yy, res # first case: Integer % Integer - if PY_TYPE(x) is PY_TYPE(y): + if type(x) is type(y): if not mpz_sgn((y).value): raise ZeroDivisionError, "Integer modulo by zero" if mpz_size((x).value) > 100000: @@ -3016,7 +3015,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): mpz_sub_ui(q.value, q.value, 1) mpz_sub_ui(r.value, r.value, -d) - elif PY_TYPE_CHECK_EXACT(other, Integer): + elif type(other) is Integer: if mpz_sgn((other).value) == 0: raise ZeroDivisionError, "Integer division by zero" if mpz_size(self.value) > 100000: @@ -3104,7 +3103,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): ZeroDivisionError: rational reconstruction with zero modulus """ cdef Integer a - cdef Rational x = PY_NEW(Rational) + cdef Rational x = Rational.__new__(Rational) try: mpq_rational_reconstruction(x.value, self.value, m.value) except ValueError: @@ -4294,7 +4293,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): else: R = RealField(prec) if self.is_zero(): - return R.zero_element() + return R.zero() return R(self).abs().log() cdef bint _is_power_of(Integer self, Integer n): diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index 63c2e074d31..4efaa231af3 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -32,24 +32,15 @@ other types will also coerce to the integers, when it makes sense. """ #***************************************************************************** -# -# Sage -# # Copyright (C) 2005 William Stein # -# Distributed under the terms of the GNU General Public License (GPL) -# -# This code is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# The full text of the GPL is available at: -# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -########################################################################### include "sage/ext/cdefs.pxi" include "sage/ext/stdsage.pxi" @@ -70,8 +61,8 @@ from sage.categories.basic import EuclideanDomains from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.structure.parent_gens import ParentWithGens from sage.structure.parent cimport Parent - from sage.structure.sequence import Sequence +from sage.misc.misc_c import prod cimport integer cimport rational @@ -439,7 +430,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): ... ZeroDivisionError: Rational division by zero """ - cdef rational.Rational x = PY_NEW(rational.Rational) + cdef rational.Rational x = rational.Rational.__new__(rational.Rational) if mpz_sgn(right.value) == 0: raise ZeroDivisionError('Rational division by zero') mpz_set(mpq_numref(x.value), left.value) @@ -1328,7 +1319,6 @@ def IntegerRing(): """ return ZZ -import sage.misc.misc def crt_basis(X, xgcd=None): r""" Compute and return a Chinese Remainder Theorem basis for the list ``X`` @@ -1391,16 +1381,16 @@ def crt_basis(X, xgcd=None): if len(X) == 0: return [] - P = sage.misc.misc.prod(X) + P = prod(X) Y = [] # 2. Compute extended GCD's ONE=X[0].parent()(1) for i in range(len(X)): p = X[i] - prod = P//p - g,s,t = p.xgcd(prod) + others = P//p + g,s,t = p.xgcd(others) if g != ONE: - raise ArithmeticError, "The elements of the list X must be coprime in pairs." - Y.append(t*prod) + raise ArithmeticError("the elements of the list X must be coprime in pairs") + Y.append(t*others) return Y diff --git a/src/sage/rings/laurent_series_ring_element.pyx b/src/sage/rings/laurent_series_ring_element.pyx index 71fe1e71ccb..32d0011dc3d 100644 --- a/src/sage/rings/laurent_series_ring_element.pyx +++ b/src/sage/rings/laurent_series_ring_element.pyx @@ -448,7 +448,7 @@ cdef class LaurentSeries(AlgebraElement): sage: f.coefficients() [-5, 1, 1, -10/3] """ - zero = self.parent().base_ring().zero_element() + zero = self.parent().base_ring().zero() return [c for c in self.list() if c != zero] def residue(self): @@ -491,7 +491,7 @@ cdef class LaurentSeries(AlgebraElement): sage: f.exponents() [-2, 1, 2, 3] """ - zero = self.parent().base_ring().zero_element() + zero = self.parent().base_ring().zero() l = self.list() v = self.valuation() return [i+v for i in range(len(l)) if l[i] != zero] @@ -1278,6 +1278,20 @@ cdef class LaurentSeries(AlgebraElement): t = u.parent().gen() return t**(self.__n) * u + def inverse(self): + """ + Return the inverse of self, i.e., self^(-1). + + EXAMPLES:: + + sage: R. = LaurentSeriesRing(ZZ) + sage: t.inverse() + t^-1 + sage: (1-t).inverse() + 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + t^7 + t^8 + ... + """ + return self.__invert__() + def __call__(self, *x, **kwds): """ Compute value of this Laurent series at x. diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 5c7c592f826..50dd8c5e6c6 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -625,7 +625,7 @@ cdef class RingHomomorphism(RingMap): sage: bool(ZZ.hom(R1, [1])) False """ - return bool(self.codomain().one_element()) + return bool(self.codomain().one()) def _repr_type(self): """ @@ -1556,6 +1556,21 @@ cdef class RingHomomorphism_from_base(RingHomomorphism): except Exception: raise TypeError, "invalid argument %s"%repr(x) + def is_identity(self): + """ + Return ``True`` if this morphism is the identity morphism. + + EXAMPLES:: + + sage: K. = GF(4) + sage: phi = End(K)([z^2]) + sage: R. = K[] + sage: psi = End(R)(phi) + sage: psi.is_identity() + False + """ + return self.__underlying.is_identity() and RingHomomorphism.is_identity(self) + cdef class RingHomomorphism_cover(RingHomomorphism): r""" A homomorphism induced by quotienting a ring out by an ideal. diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index f904413fd41..e50b5eb18da 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -3182,7 +3182,7 @@ def primes_of_degree_one_iter(self, num_integer_primes=10000, max_iterations=100 sage: K. = CyclotomicField(10) sage: it = K.primes_of_degree_one_iter() - sage: Ps = [ it.next() for i in range(3) ] + sage: Ps = [ next(it) for i in range(3) ] sage: Ps # random [Fractional ideal (z^3 + z + 1), Fractional ideal (3*z^3 - z^2 + z - 1), Fractional ideal (2*z^3 - 3*z^2 + z - 2)] sage: [ P.norm() for P in Ps ] # random @@ -3233,7 +3233,7 @@ def primes_of_degree_one_list(self, n, num_integer_primes=10000, max_iterations= [1, 1, 1] """ it = self.primes_of_degree_one_iter() - return [ it.next() for i in range(n) ] + return [ next(it) for i in range(n) ] def _is_valid_homomorphism_(self, codomain, im_gens): """ @@ -4073,7 +4073,7 @@ def selmer_group_iterator(self, S, m, proof=True): [1, -1, 13, -13, 11, -11, 143, -143] """ KSgens, ords = self.selmer_group(S=S, m=m, proof=proof, orders=True) - one = self.one_element() + one = self.one() from sage.misc.all import cartesian_product_iterator for ev in cartesian_product_iterator([range(o) for o in ords]): yield prod([p**e for p,e in zip(KSgens, ev)], one) @@ -8441,11 +8441,11 @@ def __init__(self, n, names, embedding=None, assume_disc_small=False, maximize_a TESTS:: sage: TestSuite(k).run() - sage: type(CyclotomicField(4).zero_element()) + sage: type(CyclotomicField(4).zero()) - sage: type(CyclotomicField(6).one_element()) + sage: type(CyclotomicField(6).one()) - sage: type(CyclotomicField(15).zero_element()) + sage: type(CyclotomicField(15).zero()) """ f = QQ['x'].cyclotomic_polynomial(n) @@ -9638,9 +9638,9 @@ def __init__(self, polynomial, name=None, latex_name=None, check=True, embedding TESTS:: sage: k. = QuadraticField(7) - sage: type(k.zero_element()) + sage: type(k.zero()) - sage: type(k.one_element()) + sage: type(k.one()) sage: TestSuite(k).run() diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index 20f7e4a2d64..9f5daf9402f 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -177,8 +177,8 @@ cdef class NumberFieldElement(FieldElement): Quickly creates a new initialized NumberFieldElement with the same parent as self. """ - cdef NumberFieldElement x - x = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef NumberFieldElement x = t.__new__(t) x._parent = self._parent x.__fld_numerator = self.__fld_numerator x.__fld_denominator = self.__fld_denominator @@ -303,7 +303,7 @@ cdef class NumberFieldElement(FieldElement): return elif isinstance(f, NumberFieldElement): - if PY_TYPE(self) is PY_TYPE(f): + if type(self) is type(f): self.__numerator = (f).__numerator self.__denominator = (f).__denominator return @@ -446,7 +446,8 @@ cdef class NumberFieldElement(FieldElement): else: return self.polynomial()(new_parent.gen()**rel) - cdef NumberFieldElement x = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef NumberFieldElement x = t.__new__(t) x._parent = new_parent x.__fld_numerator, x.__fld_denominator = new_parent.polynomial_ntl() x.__denominator = self.__denominator @@ -1006,7 +1007,7 @@ cdef class NumberFieldElement(FieldElement): R = RealField(prec) if self.is_zero(): - return R.zero_element() + return R.zero() val = self.valuation(P) nP = P.residue_class_degree()*P.absolute_ramification_index() return R(P.absolute_norm()) ** (-R(val) / R(nP)) @@ -1729,7 +1730,7 @@ cdef class NumberFieldElement(FieldElement): TypeError: An embedding into RR or CC must be specified. """ if (PY_TYPE_CHECK(base, NumberFieldElement) and - (PY_TYPE_CHECK(exp, Integer) or PY_TYPE_CHECK_EXACT(exp, int) or exp in ZZ)): + (PY_TYPE_CHECK(exp, Integer) or type(exp) is int or exp in ZZ)): return generic_power_c(base, exp, None) else: cbase, cexp = canonical_coercion(base, exp) @@ -2510,7 +2511,7 @@ cdef class NumberFieldElement(FieldElement): if self.__multiplicative_order is not None: return self.__multiplicative_order - one = self.number_field().one_element() + one = self.number_field().one() infinity = sage.rings.infinity.infinity if self == one: @@ -3037,9 +3038,9 @@ cdef class NumberFieldElement(FieldElement): if self.valuation(P) >= 0: ## includes the case self=0 from sage.rings.real_mpfr import RealField if prec is None: - return RealField().zero_element() + return RealField().zero() else: - return RealField(prec).zero_element() + return RealField(prec).zero() ht = self.abs_non_arch(P,prec).log() if not weighted: return ht @@ -3100,8 +3101,8 @@ cdef class NumberFieldElement(FieldElement): emb = K.places(prec=prec)[i] a = emb(self).abs() Kv = emb.codomain() - if a <= Kv.one_element(): - return Kv.zero_element() + if a <= Kv.one(): + return Kv.zero() ht = a.log() from sage.rings.real_mpfr import is_RealField if weighted and not is_RealField(Kv): @@ -3159,7 +3160,7 @@ cdef class NumberFieldElement(FieldElement): else: R = RealField(prec) if self.is_zero(): - return R.zero_element() + return R.zero() return R(self.denominator_ideal().absolute_norm()).log() def global_height_arch(self, prec=None): @@ -3187,7 +3188,7 @@ cdef class NumberFieldElement(FieldElement): """ r,s = self.number_field().signature() hts = [self.local_height_arch(i, prec, weighted=True) for i in range(r+s)] - return sum(hts, hts[0].parent().zero_element()) + return sum(hts, hts[0].parent().zero()) def global_height(self, prec=None): """ @@ -4252,8 +4253,8 @@ cdef class OrderElement_absolute(NumberFieldElement_absolute): sage: O.1 * O.1 * O.1 -18 """ - cdef OrderElement_absolute x - x = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef OrderElement_absolute x = t.__new__(t) x._parent = self._parent x._number_field = self._parent.number_field() x.__fld_numerator = self.__fld_numerator @@ -4392,8 +4393,8 @@ cdef class OrderElement_relative(NumberFieldElement_relative): sage: parent(c) == O True """ - cdef OrderElement_relative x - x = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef OrderElement_relative x = t.__new__(t) x._parent = self._parent x._number_field = self._parent.number_field() x.__fld_numerator = self.__fld_numerator diff --git a/src/sage/rings/number_field/number_field_element_quadratic.pyx b/src/sage/rings/number_field/number_field_element_quadratic.pyx index f78efa3a5b8..c5127cfcb0d 100644 --- a/src/sage/rings/number_field/number_field_element_quadratic.pyx +++ b/src/sage/rings/number_field/number_field_element_quadratic.pyx @@ -172,7 +172,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): mpz_set(self.b, (f).b) mpz_set(self.denom, (f).denom) - elif PY_TYPE_CHECK_EXACT(f, tuple) and len(f) == 2: + elif type(f) is tuple and len(f) == 2: NumberFieldElement_absolute.__init__(self, parent, None) ad, bd = f mpz_lcm(self.denom, mpq_denref(ad.value), mpq_denref(bd.value)) @@ -181,7 +181,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): mpz_divexact(self.b, self.denom, mpq_denref(bd.value)) mpz_mul(self.b, self.b, mpq_numref(bd.value)) - elif PY_TYPE_CHECK_EXACT(f, tuple) and len(f) == 3: + elif type(f) is tuple and len(f) == 3: NumberFieldElement_absolute.__init__(self, parent, None) a, b, denom = f mpz_set(self.a, a.value) @@ -234,8 +234,8 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): sage: b + b # indirect doctest 2*b """ - cdef NumberFieldElement_quadratic x - x = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef NumberFieldElement_quadratic x = t.__new__(t) x._parent = self._parent x.standard_embedding = self.standard_embedding x.D = self.D @@ -463,7 +463,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): cdef mpz_t tmp_mpz cdef long tmp_const - x = PY_NEW(NumberFieldElement_absolute) + x = NumberFieldElement_absolute.__new__(NumberFieldElement_absolute) mpz_to_ZZ(&elt_den, self.denom) @@ -552,7 +552,8 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): sage: a._coefficients() [0, 1] """ - cdef Rational ad = PY_NEW(Rational), bd = PY_NEW(Rational) + cdef Rational ad = Rational.__new__(Rational) + cdef Rational bd = Rational.__new__(Rational) if mpz_cmp_ui(self.a, 0) == 0: mpq_set_ui(ad.value, 0, 1) else: @@ -898,6 +899,68 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): return 1 return -1 + def continued_fraction_list(self): + r""" + Return the preperiod and the period of the continued fraction expansion + of ``self``. + + EXAMPLES:: + + sage: K. = QuadraticField(2) + sage: sqrt2.continued_fraction_list() + ((1,), (2,)) + sage: (1/2+sqrt2/3).continued_fraction_list() + ((0, 1, 33), (1, 32)) + + For rational entries a pair of tuples is also returned but the second + one is empty:: + + sage: K(123/567).continued_fraction_list() + ((0, 4, 1, 1, 1, 1, 3, 2), ()) + """ + cdef NumberFieldElement_quadratic x + + if mpz_sgn(self.b) == 0: + return tuple(Rational(self).continued_fraction_list()),() + + if mpz_sgn(self.D.value) < 0: + raise ValueError("the method is only available for positive discriminant") + + x = self + orbit = [] + quots = [] + while x not in orbit: + quots.append(x.floor()) + orbit.append(x) + x = ~(x - quots[-1]) + + i = orbit.index(x) + + return tuple(quots[:i]), tuple(quots[i:]) + + def continued_fraction(self): + r""" + Return the (finite or ultimately periodic) continued fraction of ``self``. + + EXAMPLES:: + + sage: K. = QuadraticField(2) + sage: cf = sqrt2.continued_fraction(); cf + [1; (2)*] + sage: cf.n() + 1.41421356237310 + sage: sqrt2.n() + 1.41421356237310 + sage: cf.value() + sqrt2 + + sage: (sqrt2/3 + 1/4).continued_fraction() + [0; 1, (2, 1, 1, 2, 3, 2, 1, 1, 2, 5, 1, 1, 14, 1, 1, 5)*] + """ + t1,t2 = self.continued_fraction_list() + from sage.rings.continued_fraction import ContinuedFraction_periodic + return ContinuedFraction_periodic(t1,t2) + ######################################################### # Arithmetic ######################################################### @@ -1296,7 +1359,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): if mpz_cmp_ui(self.b, 0)!=0: raise TypeError("Unable to coerce %s to a rational" % self) else: - res = PY_NEW(Rational) + res = Rational.__new__(Rational) mpz_set(mpq_numref(res.value), self.a) mpz_set(mpq_denref(res.value), self.denom) mpq_canonicalize(res.value) @@ -1330,7 +1393,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): if mpz_sgn(self.D.value) > 0: return self # totally real else: - res = PY_NEW(Rational) + res = Rational.__new__(Rational) mpz_set(mpq_numref(res.value), self.a) mpz_set(mpq_denref(res.value), self.denom) mpq_canonicalize(res.value) @@ -1374,7 +1437,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): """ if mpz_sgn(self.D.value) > 0: - return PY_NEW(Rational) # = 0 + return Rational.__new__(Rational) # = 0 embedding = self._parent.coerce_embedding() cdef Integer negD = -self.D cdef NumberFieldElement_quadratic q = self._new() @@ -1386,7 +1449,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): # D = -1 is the most common case we'll see here if embedding is None: raise ValueError("Embedding must be specified.") - res = PY_NEW(Rational) + res = Rational.__new__(Rational) if mpz_cmp_ui(negD.value, 1) == 0: mpz_set(mpq_numref(res.value), self.b) else: @@ -1429,7 +1492,8 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): """ # In terms of the generator... cdef NumberFieldElement_quadratic gen = self.number_field().gen() # should this be cached? - cdef Rational const = PY_NEW(Rational), lin = PY_NEW(Rational) + cdef Rational const = Rational.__new__(Rational) + cdef Rational lin = Rational.__new__(Rational) ad, bd = self.parts() if not self: return [] @@ -1535,7 +1599,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): 2 """ # trace = 2*self.a / self.denom - cdef Rational res = PY_NEW(Rational) + cdef Rational res = Rational.__new__(Rational) if mpz_odd_p(self.denom): mpz_mul_2exp(mpq_numref(res.value), self.a, 1) mpz_set(mpq_denref(res.value), self.denom) @@ -1586,7 +1650,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): ValueError: no way to embed L into parent's base ring K """ - cdef Rational res = PY_NEW(Rational) + cdef Rational res = Rational.__new__(Rational) if K is None or K == QQ: # norm = (a^2 - d b^2) / self.denom^2 @@ -2065,7 +2129,7 @@ cdef class Z_to_quadratic_field_element(Morphism): """ import sage.categories.homset Morphism.__init__(self, sage.categories.homset.Hom(ZZ, K)) - self.zero_element = K.zero_element() + self.zero_element = K.zero() cdef dict _extra_slots(self, dict _slots): """ @@ -2186,7 +2250,7 @@ cdef class Q_to_quadratic_field_element(Morphism): """ import sage.categories.homset Morphism.__init__(self, sage.categories.homset.Hom(QQ, K)) - self.zero_element = K.zero_element() + self.zero_element = K.zero() cdef dict _extra_slots(self, dict _slots): """ diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index 4b3eb9f5b02..d03cbad2e5a 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -52,7 +52,7 @@ import number_field from sage.rings.ideal import (Ideal_generic, Ideal_fractional) -from sage.misc.misc import prod +from sage.misc.all import prod from sage.misc.mrange import xmrange_iter from sage.misc.cachefunc import cached_method from sage.structure.element import generic_power diff --git a/src/sage/rings/number_field/small_primes_of_degree_one.py b/src/sage/rings/number_field/small_primes_of_degree_one.py index 67d84435a0f..d5555e7e902 100644 --- a/src/sage/rings/number_field/small_primes_of_degree_one.py +++ b/src/sage/rings/number_field/small_primes_of_degree_one.py @@ -185,7 +185,7 @@ def _lengthen_queue(self): """ count = 0 while count < self._max_iterations: - n = self._integer_iter.next() + n = next(self._integer_iter) g = self._prod_of_small_primes.gcd(self._poly(n)) self._prod_of_small_primes //= g self._queue = self._queue + [ (p, n) for p in g.prime_divisors() ] @@ -203,7 +203,7 @@ def next(self): sage: x = QQ['x'].gen() sage: K. = NumberField(x^2 - 3) sage: it = K.primes_of_degree_one_iter() - sage: [ it.next() for i in range(3) ] # random + sage: [ next(it) for i in range(3) ] # random [Fractional ideal (2*a + 1), Fractional ideal (-a + 4), Fractional ideal (3*a + 2)] We test that #6396 is fixed. Note that the doctest is flagged as random diff --git a/src/sage/rings/number_field/totallyreal_data.pxd b/src/sage/rings/number_field/totallyreal_data.pxd index 6f650cafdcd..4ca330785ed 100644 --- a/src/sage/rings/number_field/totallyreal_data.pxd +++ b/src/sage/rings/number_field/totallyreal_data.pxd @@ -20,7 +20,8 @@ cdef class tr_data: cdef double B cdef double b_lower, b_upper, gamma - cdef int *a, *amax + cdef int *a + cdef int *amax cdef double *beta cdef int *gnk diff --git a/src/sage/rings/number_field/totallyreal_data.pyx b/src/sage/rings/number_field/totallyreal_data.pyx index 0804309e7bb..02c4a729853 100644 --- a/src/sage/rings/number_field/totallyreal_data.pyx +++ b/src/sage/rings/number_field/totallyreal_data.pyx @@ -654,8 +654,10 @@ cdef class tr_data: """ cdef int n, np1, k, i, j, nk, kz - cdef int *gnkm, *gnkm1 - cdef double *betak, bl, br, akmin, akmax, tmp_dbl + cdef int *gnkm + cdef int *gnkm1 + cdef double *betak + cdef double bl, br, akmin, akmax, tmp_dbl cdef bint maxoutflag n = self.n diff --git a/src/sage/rings/number_field/unit_group.py b/src/sage/rings/number_field/unit_group.py index 4b5c64fa0b9..c907e7671eb 100644 --- a/src/sage/rings/number_field/unit_group.py +++ b/src/sage/rings/number_field/unit_group.py @@ -141,7 +141,7 @@ from sage.structure.sequence import Sequence from sage.structure.proof.proof import get_flag from sage.libs.pari.all import pari -from sage.misc.misc import prod +from sage.misc.all import prod from sage.rings.integer_ring import ZZ class UnitGroup(AbelianGroupWithValues_class): @@ -643,6 +643,6 @@ def exp(self, exponents): sage: SUK.log(u) == v True """ - return prod([u**e for u,e in zip(self.gens_values(),exponents)], self.number_field().one_element()) + return prod((u**e for u,e in zip(self.gens_values(),exponents)), self.number_field().one()) diff --git a/src/sage/rings/padics/CA_template.pxi b/src/sage/rings/padics/CA_template.pxi index 0e874a30ea4..5571e376524 100644 --- a/src/sage/rings/padics/CA_template.pxi +++ b/src/sage/rings/padics/CA_template.pxi @@ -95,7 +95,8 @@ cdef class CAElement(pAdicTemplateElement): sage: R = ZpCA(5); R(6,5) * R(7,8) #indirect doctest 2 + 3*5 + 5^2 + O(5^5) """ - cdef CAElement ans = PY_NEW(self.__class__) + cdef type t = self.__class__ + cdef CAElement ans = t.__new__(t) ans._parent = self._parent ans.prime_pow = self.prime_pow cconstruct(ans.value, ans.prime_pow) @@ -1361,7 +1362,7 @@ def unpickle_cae_v2(cls, parent, value, absprec): sage: a.parent() is R True """ - cdef CAElement ans = PY_NEW(cls) + cdef CAElement ans = cls.__new__(cls) ans._parent = parent ans.prime_pow = parent.prime_pow cconstruct(ans.value, ans.prime_pow) diff --git a/src/sage/rings/padics/CR_template.pxi b/src/sage/rings/padics/CR_template.pxi index eb652bf03d0..45cb10848e3 100644 --- a/src/sage/rings/padics/CR_template.pxi +++ b/src/sage/rings/padics/CR_template.pxi @@ -181,7 +181,8 @@ cdef class CRElement(pAdicTemplateElement): sage: R(6,5) * R(7,8) #indirect doctest 2 + 3*5 + 5^2 + O(5^5) """ - cdef CRElement ans = PY_NEW(self.__class__) + cdef type t = self.__class__ + cdef CRElement ans = t.__new__(t) ans._parent = self._parent ans.prime_pow = self.prime_pow cconstruct(ans.unit, ans.prime_pow) @@ -1958,7 +1959,7 @@ cdef class pAdicConvert_CR_QQ(RingMap): sage: f(Qp(5)(1/5)) 1/5 """ - cdef Rational ans = PY_NEW(Rational) + cdef Rational ans = Rational.__new__(Rational) cdef CRElement x = _x if x.relprec == 0: mpq_set_ui(ans.value, 0, 1) @@ -2129,7 +2130,7 @@ def unpickle_cre_v2(cls, parent, unit, ordp, relprec): sage: a.precision_relative() == b.precision_relative() True """ - cdef CRElement ans = PY_NEW(cls) + cdef CRElement ans = cls.__new__(cls) ans._parent = parent ans.prime_pow = parent.prime_pow cconstruct(ans.unit, ans.prime_pow) diff --git a/src/sage/rings/padics/FM_template.pxi b/src/sage/rings/padics/FM_template.pxi index c7bf5778130..6d7a503ec85 100644 --- a/src/sage/rings/padics/FM_template.pxi +++ b/src/sage/rings/padics/FM_template.pxi @@ -94,7 +94,8 @@ cdef class FMElement(pAdicTemplateElement): sage: R = ZpFM(5); R(6) * R(7) #indirect doctest 2 + 3*5 + 5^2 + O(5^20) """ - cdef FMElement ans = PY_NEW(self.__class__) + cdef type t = self.__class__ + cdef FMElement ans = t.__new__(t) ans._parent = self._parent ans.prime_pow = self.prime_pow cconstruct(ans.value, ans.prime_pow) @@ -1151,7 +1152,7 @@ def unpickle_fme_v2(cls, parent, value): sage: a.parent() is R True """ - cdef FMElement ans = PY_NEW(cls) + cdef FMElement ans = cls.__new__(cls) ans._parent = parent ans.prime_pow = parent.prime_pow cconstruct(ans.value, ans.prime_pow) diff --git a/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx index 4d0f98ec68b..984a1cc007b 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx @@ -866,7 +866,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): sage: w^5 + 1 # indirect doctest 1 + w^5 + O(w^25) """ - cdef pAdicZZpXCAElement ans = PY_NEW(pAdicZZpXCAElement) + cdef pAdicZZpXCAElement ans = pAdicZZpXCAElement.__new__(pAdicZZpXCAElement) ans._parent = self._parent ans.prime_pow = self.prime_pow ans.absprec = absprec @@ -897,7 +897,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): if self.absprec == 0: return make_ZZpXCAElement, (self.parent(), None, absprec, 0) self.prime_pow.restore_context_capdiv(self.absprec) - cdef ntl_ZZ_pX holder = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX holder = ntl_ZZ_pX.__new__(ntl_ZZ_pX) holder.c = self.prime_pow.get_context_capdiv(self.absprec) holder.x = self.value return make_ZZpXCAElement, (self.parent(), holder, absprec, 0) @@ -989,7 +989,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): sage: y.parent() Eisenstein Extension of 5-adic Field with capped relative precision 5 in w defined by (1 + O(5^5))*x^5 + (O(5^6))*x^4 + (3*5^2 + O(5^6))*x^3 + (2*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))*x^2 + (5^3 + O(5^6))*x + (4*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6)) """ - cdef pAdicZZpXCRElement ans = PY_NEW(pAdicZZpXCRElement) + cdef pAdicZZpXCRElement ans = pAdicZZpXCRElement.__new__(pAdicZZpXCRElement) ans._parent = self._parent.fraction_field() ans.prime_pow = ans._parent.prime_pow ans.ordp = 0 @@ -1384,7 +1384,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): mpz_clear(tmp) if ans_ordp >= self.prime_pow.ram_prec_cap: return self._new_c(self.prime_pow.ram_prec_cap) - cdef ntl_ZZ rZZ = PY_NEW(ntl_ZZ) + cdef ntl_ZZ rZZ = ntl_ZZ.__new__(ntl_ZZ) mpz_to_ZZ(&rZZ.x, right.value) if ans_ordp + ans_relprec <= self.prime_pow.ram_prec_cap: ans = self._new_c(ans_ordp + ans_relprec) # restores context @@ -1698,7 +1698,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): if self.absprec == 0: raise ValueError, "self has 0 absolute precision" self.prime_pow.restore_context_capdiv(self.absprec) - cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX) ans.c = self.prime_pow.get_context_capdiv(self.absprec) ans.x = self.value return ans diff --git a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx index b7356b847a9..42318bce6ed 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx @@ -1419,7 +1419,8 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): 3 + O(w^6) """ cdef ZZ_pX_c high_shifter, high_shifter2 - cdef ZZ_pX_Modulus_c *modulus, modulus_up + cdef ZZ_pX_Modulus_c *modulus + cdef ZZ_pX_Modulus_c modulus_up cdef ntl_ZZ_pContext_class c cdef PowComputer_ZZ_pX_small_Eis sm cdef PowComputer_ZZ_pX_big_Eis big @@ -1509,7 +1510,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): sage: w^5 + 1 # indirect doctest 1 + w^5 + O(w^25) """ - cdef pAdicZZpXCRElement ans = PY_NEW(pAdicZZpXCRElement) + cdef pAdicZZpXCRElement ans = pAdicZZpXCRElement.__new__(pAdicZZpXCRElement) ans._parent = self._parent ans.prime_pow = self.prime_pow if relprec > 0: @@ -1546,7 +1547,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): if self.relprec == 0: return make_ZZpXCRElement, (self.parent(), None, ordp, relprec, 0) self.prime_pow.restore_context_capdiv(self.relprec) - cdef ntl_ZZ_pX holder = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX holder = ntl_ZZ_pX.__new__(ntl_ZZ_pX) holder.c = self.prime_pow.get_context_capdiv(self.relprec) holder.x = self.unit return make_ZZpXCRElement, (self.parent(), holder, ordp, relprec, 0) @@ -2075,7 +2076,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): raise ValueError, "valuation overflow" ans.ordp = mpz_get_si(tmp) mpz_clear(tmp) - cdef ntl_ZZ rZZ = PY_NEW(ntl_ZZ) + cdef ntl_ZZ rZZ = ntl_ZZ.__new__(ntl_ZZ) mpz_to_ZZ(&rZZ.x, right.value) sig_on() if mpz_sgn(right.value) < 0: @@ -2457,7 +2458,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): if self.relprec == 0: raise ValueError, "self == 0" self.prime_pow.restore_context_capdiv(self.relprec) - cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX) ans.c = self.prime_pow.get_context_capdiv(self.relprec) ans.x = self.unit return ans @@ -2523,8 +2524,8 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): little_shift = self.prime_pow.e - little_shift ctx = self.prime_pow.get_context_capdiv(self.relprec + little_shift) ctx.restore_c() - cdef pAdicZZpXCRElement dummy = PY_NEW(pAdicZZpXCRElement) - cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX) + cdef pAdicZZpXCRElement dummy = pAdicZZpXCRElement.__new__(pAdicZZpXCRElement) + cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX) cdef Integer ans_k = PY_NEW(Integer) dummy.unit = self.unit dummy.prime_pow = self.prime_pow diff --git a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx index 1f949698eab..9b2e77e22f2 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx @@ -405,7 +405,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): True """ self.prime_pow.restore_top_context() - cdef ntl_ZZ_pX holder = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX holder = ntl_ZZ_pX.__new__(ntl_ZZ_pX) holder.c = self.prime_pow.get_top_context() holder.x = self.value return make_ZZpXFMElement, (self.parent(), holder) @@ -439,7 +439,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): 1 + w^5 + O(w^25) """ self.prime_pow.restore_top_context() - cdef pAdicZZpXFMElement ans = PY_NEW(pAdicZZpXFMElement) + cdef pAdicZZpXFMElement ans = pAdicZZpXFMElement.__new__(pAdicZZpXFMElement) ans._parent = self._parent ZZ_pX_construct(&ans.value) ans.prime_pow = self.prime_pow @@ -776,7 +776,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): if right == 0 and self == 0: return self.parent(1) cdef pAdicZZpXFMElement ans = self._new_c() - cdef ntl_ZZ rZZ = PY_NEW(ntl_ZZ) + cdef ntl_ZZ rZZ = ntl_ZZ.__new__(ntl_ZZ) mpz_to_ZZ(&rZZ.x, (right).value) if mpz_sgn((right).value) < 0: if self.valuation_c() > 0: @@ -1189,7 +1189,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): [89 9 4 1] """ self.prime_pow.restore_top_context() - cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX) ans.c = self.prime_pow.get_top_context() ans.x = self.value return ans diff --git a/src/sage/rings/padics/padic_ZZ_pX_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_element.pyx index 43fa3b47ca7..821cac929c9 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_element.pyx @@ -620,17 +620,17 @@ cdef preprocess_list(pAdicZZpXElement elt, L): raise ValueError, "negative valuation" if total_type == one: # rationals and integers - py_tmp = PY_NEW(ntl_ZZ) + py_tmp = ntl_ZZ.__new__(ntl_ZZ) py_tmp.x = elt.prime_pow.pow_ZZ_top()[0] ctx = ntl_ZZ_pContext(py_tmp) else: # integers, rationals and things with finite precision # note that min_val will be non-positive since things with finite precision return non-positive valuation from get_val_prec - py_tmp = PY_NEW(ntl_ZZ) + py_tmp = ntl_ZZ.__new__(ntl_ZZ) py_tmp.x = elt.prime_pow.pow_ZZ_tmp(mpz_get_ui(((min_aprec - min_val)).value))[0] ctx = ntl_ZZ_pContext(py_tmp) if min_val < 0: - pshift_z = PY_NEW(ntl_ZZ) + pshift_z = ntl_ZZ.__new__(ntl_ZZ) pshift_z.x = elt.prime_pow.pow_ZZ_tmp(-mpz_get_si((min_val).value))[0] pshift_m = elt.prime_pow.pow_Integer(-mpz_get_si((min_val).value)) for i from 0 <= i < len(L): @@ -645,13 +645,13 @@ cdef preprocess_list(pAdicZZpXElement elt, L): elif (L[i].modulus_context() is not ctx) or min_val != zero: L[i] = ntl_ZZ_p(L[i].lift()*pshift_z, ctx) elif elt.parent().is_capped_relative() and min_val > 0: - pshift_z = PY_NEW(ntl_ZZ) + pshift_z = ntl_ZZ.__new__(ntl_ZZ) pshift_z.x = elt.prime_pow.pow_ZZ_tmp(mpz_get_ui((min_val).value))[0] pshift_m = elt.prime_pow.pow_Integer(mpz_get_ui((min_val).value)) for i from 0 <= i < len(L): if PY_TYPE_CHECK(L[i], ntl_ZZ): ZZ_div(tmp, (L[i]).x, pshift_z.x) - py_tmp = PY_NEW(ntl_ZZ) + py_tmp = ntl_ZZ.__new__(ntl_ZZ) py_tmp.x = tmp L[i] = ntl_ZZ_p(py_tmp, ctx) elif PY_TYPE_CHECK(L[i], Integer) or PY_TYPE_CHECK(L[i], Rational) or isinstance(L[i], (int, long)): @@ -662,7 +662,7 @@ cdef preprocess_list(pAdicZZpXElement elt, L): L[i] = ntl_ZZ_p(L[i].lift()//pshift_m, ctx) elif (L[i].modulus_context() is not ctx) or min_val != zero: ZZ_div(tmp, (L[i].lift()).x, pshift_z.x) - py_tmp = PY_NEW(ntl_ZZ) + py_tmp = ntl_ZZ.__new__(ntl_ZZ) py_tmp.x = tmp L[i] = ntl_ZZ_p(py_tmp, ctx) else: @@ -844,7 +844,7 @@ cdef get_val_prec(PowComputer_ext pp, a): if PY_TYPE_CHECK(a, ntl_ZZ): if ZZ_IsZero((a).x): return (big, big, two) - py_tmp = PY_NEW(ntl_ZZ) + py_tmp = ntl_ZZ.__new__(ntl_ZZ) py_tmp.x = pp.pow_ZZ_tmp(1)[0] return (Integer(a.valuation(py_tmp)), big, two) #print "pre int/long check" @@ -899,7 +899,7 @@ cdef get_val_prec(PowComputer_ext pp, a): return (zero, Integer_val, zero) else: print long_val - py_tmp = PY_NEW(ntl_ZZ) + py_tmp = ntl_ZZ.__new__(ntl_ZZ) py_tmp.x = (a).c.p.x print py_tmp py_tmp.x = leftover_z diff --git a/src/sage/rings/padics/padic_capped_relative_element.pyx b/src/sage/rings/padics/padic_capped_relative_element.pyx index b187d5d3c05..7cf1f593ea0 100644 --- a/src/sage/rings/padics/padic_capped_relative_element.pyx +++ b/src/sage/rings/padics/padic_capped_relative_element.pyx @@ -160,7 +160,7 @@ cdef class pAdicCappedRelativeElement(CRElement): mpz_mul(ans.value, ans.value, self.prime_pow.pow_mpz_t_tmp(self.ordp)) return ans else: - ansr = PY_NEW(Rational) + ansr = Rational.__new__(Rational) if self.relprec == 0: mpq_set_si(ansr.value, 0, 1) return self diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index 079ea57976b..500bb4cdeaa 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -663,7 +663,7 @@ cdef class PowComputer_ext(PowComputer_class): """ cdef Integer _n = Integer(n) if _n < 0: raise ValueError - cdef ntl_ZZ ans = PY_NEW(ntl_ZZ) + cdef ntl_ZZ ans = ntl_ZZ.__new__(ntl_ZZ) ans.x = self.pow_ZZ_tmp(mpz_get_ui(_n.value))[0] return ans @@ -699,7 +699,7 @@ cdef class PowComputer_ext(PowComputer_class): n = Integer(n) if m < 0 or n < 0: raise ValueError, "m, n must be non-negative" - cdef ntl_ZZ ans = PY_NEW(ntl_ZZ) + cdef ntl_ZZ ans = ntl_ZZ.__new__(ntl_ZZ) ZZ_mul(ans.x, self.pow_ZZ_tmp(mpz_get_ui((m).value))[0], self.pow_ZZ_tmp(mpz_get_ui((n).value))[0]) return ans @@ -739,7 +739,7 @@ cdef class PowComputer_ext(PowComputer_class): sage: PC._pow_ZZ_top_test() 15625 """ - cdef ntl_ZZ ans = PY_NEW(ntl_ZZ) + cdef ntl_ZZ ans = ntl_ZZ.__new__(ntl_ZZ) ans.x = self.pow_ZZ_top()[0] return ans @@ -776,7 +776,7 @@ cdef class PowComputer_ZZ_pX(PowComputer_ext): cdef ZZ_pX_Modulus_c* tmp tmp.val() self.restore_top_context() - cdef ntl_ZZ_pX r = PY_NEW(ntl_ZZ_pX) + cdef ntl_ZZ_pX r = ntl_ZZ_pX.__new__(ntl_ZZ_pX) r.c = self.get_top_context() r.x = (self.get_top_modulus()[0]).val() return r @@ -791,7 +791,7 @@ cdef class PowComputer_ZZ_pX(PowComputer_ext): sage: PC._get_context_test(15) #indirect doctest NTL modulus 30517578125 """ - cdef ntl_ZZ pn = PY_NEW(ntl_ZZ) + cdef ntl_ZZ pn = ntl_ZZ.__new__(ntl_ZZ) if n < 0: n = -n elif n == 0: @@ -2218,7 +2218,7 @@ cdef class PowComputer_ZZ_pX_big(PowComputer_ZZ_pX): else: c = self.get_context(n) c.restore_c() - tmp = PY_NEW(ntl_ZZ_pX) + tmp = ntl_ZZ_pX.__new__(ntl_ZZ_pX) tmp.c = c ZZ_pX_conv_modulus(tmp.x, self.top_mod.val(), c.x) holder = ntl_ZZ_pX_Modulus(tmp) diff --git a/src/sage/rings/polynomial/cyclotomic.pyx b/src/sage/rings/polynomial/cyclotomic.pyx index 6003d5a9e18..13896823990 100644 --- a/src/sage/rings/polynomial/cyclotomic.pyx +++ b/src/sage/rings/polynomial/cyclotomic.pyx @@ -32,7 +32,7 @@ include "sage/ext/cdefs.pxi" from sage.rings.arith import factor from sage.rings.infinity import infinity -from sage.misc.misc import prod, subsets +from sage.misc.all import prod, subsets from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational from sage.libs.pari.gen cimport gen diff --git a/src/sage/rings/polynomial/groebner_fan.py b/src/sage/rings/polynomial/groebner_fan.py index c70cc91bc88..88d235f9cc4 100644 --- a/src/sage/rings/polynomial/groebner_fan.py +++ b/src/sage/rings/polynomial/groebner_fan.py @@ -1118,7 +1118,7 @@ def __iter__(self): sage: R. = PolynomialRing(QQ,2) sage: gf = R.ideal([x^3-y,y^3-x-1]).groebner_fan() sage: a = gf.__iter__() - sage: a.next() + sage: next(a) [y^9 - 3*y^6 + 3*y^3 - y - 1, -y^3 + x + 1] """ for x in self.reduced_groebner_bases(): diff --git a/src/sage/rings/polynomial/infinite_polynomial_element.py b/src/sage/rings/polynomial/infinite_polynomial_element.py index 1eff3cd69f1..72736fe42e3 100644 --- a/src/sage/rings/polynomial/infinite_polynomial_element.py +++ b/src/sage/rings/polynomial/infinite_polynomial_element.py @@ -629,7 +629,7 @@ def _div_(self, x): """ if not x.variables(): p = self.base_ring()(x._p) - divisor = self.base_ring().one_element()/p # use induction + divisor = self.base_ring().one()/p # use induction OUTP = self.parent().tensor_with_ring(divisor.base_ring()) return OUTP(self)*OUTP(divisor) else: @@ -1139,7 +1139,7 @@ def coefficient(self, monomial): elif isinstance(monomial, dict): if monomial: I = monomial.iterkeys() - K = I.next() + K = next(I) monomial.__delitem__(K) res = self.coefficient(K).coefficient(monomial) else: diff --git a/src/sage/rings/polynomial/infinite_polynomial_ring.py b/src/sage/rings/polynomial/infinite_polynomial_ring.py index 684ed57dd5e..3cffa6c2367 100644 --- a/src/sage/rings/polynomial/infinite_polynomial_ring.py +++ b/src/sage/rings/polynomial/infinite_polynomial_ring.py @@ -534,9 +534,9 @@ def next(self): sage: D = R.gens_dict() sage: D GenDict of Infinite polynomial ring in a, b over Univariate Polynomial Ring in t over Rational Field - sage: D.next() + sage: next(D) GenDict of Univariate Polynomial Ring in t over Rational Field - sage: sage_eval('t^2',D.next()) + sage: sage_eval('t^2', next(D)) t^2 """ @@ -759,40 +759,6 @@ def one(self): from sage.rings.polynomial.infinite_polynomial_element import InfinitePolynomial return InfinitePolynomial(self,self._base(1)) - @cached_method - def one_element(self): - """ - TESTS:: - - sage: X. = InfinitePolynomialRing(QQ) - sage: X.one_element() - 1 - """ - from sage.rings.polynomial.infinite_polynomial_element import InfinitePolynomial - return InfinitePolynomial(self,1) - - @cached_method - def zero_element(self): - """ - TESTS:: - - sage: X. = InfinitePolynomialRing(QQ) - sage: X.zero_element() - 0 - """ - return self(0) - - @cached_method - def zero(self): - """ - TESTS:: - - sage: X. = InfinitePolynomialRing(QQ) - sage: X.zero() - 0 - """ - return self(0) - ##################### ## coercion @@ -908,7 +874,7 @@ def _element_constructor_(self, x): try: from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict if isinstance(self._base, MPolynomialRing_polydict): - x = sage_eval(repr(), self._gens_dict.next()) + x = sage_eval(repr(), next(self._gens_dict)) else: x = self._base(x) # remark: Conversion to self._P (if applicable) @@ -1069,7 +1035,7 @@ def tensor_with_ring(self, R): return InfinitePolynomialRing(B.change_ring(R), self._names, self._order, implementation='sparse') # try to find the correct base ring in other ways: try: - o = B.one_element()*R.one_element() + o = B.one()*R.one() except Exception: raise TypeError("We can't tensor with "+repr(R)) return InfinitePolynomialRing(o.parent(), self._names, self._order, implementation='sparse') @@ -1569,7 +1535,7 @@ def tensor_with_ring(self, R): return InfinitePolynomialRing(B.change_ring(R), self._names, self._order, implementation='dense') # try to find the correct base ring in other ways: try: - o = B.one_element()*R.one_element() + o = B.one()*R.one() except Exception: raise TypeError("We can't tensor with "+repr(R)) return InfinitePolynomialRing(o.parent(), self._names, self._order, implementation='dense') diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 20aeec77dfc..abcde235a08 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -1395,7 +1395,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic): x*y """ cdef LaurentPolynomial_mpair ans - ans = PY_NEW(LaurentPolynomial_mpair) + ans = LaurentPolynomial_mpair.__new__(LaurentPolynomial_mpair) ans._parent = self._parent return ans @@ -1617,7 +1617,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic): if self._prod is None: self._compute_polydict() if t not in self._prod.exponents(): - return self.parent().base_ring().zero_element() + return self.parent().base_ring().zero() return self._prod[t] def __iter__(self): @@ -1635,7 +1635,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic): if self._prod is None: self._compute_polydict() for c, exps in self._prod.list(): - prod = self.parent().one_element() + prod = self.parent().one() for i in range(len(exps)): prod *= self.parent().gens()[i]**exps[i] yield (c, prod) @@ -1655,7 +1655,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic): if self._prod is None: self._compute_polydict() for c, exps in self._prod.list(): - prod = self.parent().one_element() + prod = self.parent().one() for i in range(len(exps)): prod *= self.parent().gens()[i]**exps[i] L.append(prod) diff --git a/src/sage/rings/polynomial/multi_polynomial.pyx b/src/sage/rings/polynomial/multi_polynomial.pyx index 605b9f05d4c..8869455538b 100644 --- a/src/sage/rings/polynomial/multi_polynomial.pyx +++ b/src/sage/rings/polynomial/multi_polynomial.pyx @@ -2,8 +2,6 @@ r""" Base class for elements of multivariate polynomial rings """ -import sage.misc.misc as misc - include "sage/ext/stdsage.pxi" from sage.rings.integer cimport Integer from sage.rings.integer_ring import ZZ @@ -11,6 +9,8 @@ from sage.rings.integer_ring import ZZ from sage.misc.derivative import multi_derivative from sage.rings.infinity import infinity +from sage.misc.all import prod + def is_MPolynomial(x): return isinstance(x, MPolynomial) @@ -287,7 +287,7 @@ cdef class MPolynomial(CommutativeRingElement): n = len(x) expr = fast_float_constant(0) for (m,c) in self.dict().iteritems(): - monom = misc.mul([ x[i]**m[i] for i in range(n) if m[i] != 0], fast_float_constant(c)) + monom = prod([ x[i]**m[i] for i in range(n) if m[i] != 0], fast_float_constant(c)) expr = expr + monom return expr @@ -329,7 +329,7 @@ cdef class MPolynomial(CommutativeRingElement): expr = etb.constant(self.base_ring()(0)) for (m, c) in self.dict().iteritems(): - monom = misc.mul([ x[i]**m[i] for i in range(n) if m[i] != 0], + monom = prod([ x[i]**m[i] for i in range(n) if m[i] != 0], etb.constant(c)) expr = expr + monom return expr @@ -1091,7 +1091,6 @@ cdef class MPolynomial(CommutativeRingElement): p = k.characteristic() e = k.degree() v = [self] + [self.map_coefficients(k.hom([k.gen()**(p**i)])) for i in range(1,e)] - from sage.misc.misc_c import prod return prod(v).change_ring(k.prime_subfield()) def sylvester_matrix(self, right, variable = None): @@ -1449,7 +1448,7 @@ cdef class MPolynomial(CommutativeRingElement): True """ if self.degree() == -1: - return self.base_ring().one_element() + return self.base_ring().one() x = self.coefficients() try: d = x[0].denominator() @@ -1457,7 +1456,7 @@ cdef class MPolynomial(CommutativeRingElement): d = d.lcm(y.denominator()) return d except(AttributeError): - return self.base_ring().one_element() + return self.base_ring().one() def numerator(self): """ diff --git a/src/sage/rings/polynomial/multi_polynomial_element.py b/src/sage/rings/polynomial/multi_polynomial_element.py index c7aa2437faf..11239961c9f 100644 --- a/src/sage/rings/polynomial/multi_polynomial_element.py +++ b/src/sage/rings/polynomial/multi_polynomial_element.py @@ -58,7 +58,7 @@ from sage.structure.element import CommutativeRingElement, canonical_coercion, coerce_binop -import sage.misc.misc as misc +from sage.misc.all import prod import sage.rings.integer import polydict @@ -153,7 +153,7 @@ def __call__(self, *x, **kwds): K = self.parent().base_ring() y = K(0) for (m,c) in self.element().dict().iteritems(): - y += c*misc.mul([ x[i]**m[i] for i in range(n) if m[i] != 0]) + y += c*prod([ x[i]**m[i] for i in range(n) if m[i] != 0]) return y def __cmp__(self, right): @@ -205,7 +205,7 @@ def _im_gens_(self, codomain, im_gens): return codomain._coerce_(self) y = codomain(0) for (m,c) in self.element().dict().iteritems(): - y += codomain(c)*misc.mul([ im_gens[i]**m[i] for i in range(n) if m[i] ]) + y += codomain(c)*prod([ im_gens[i]**m[i] for i in range(n) if m[i] ]) return y @@ -1336,7 +1336,7 @@ def lm(self): R = self.parent() f = self._MPolynomial_element__element.lcmt( R.term_order().greater_tuple ) one = R.base_ring()(1) - self.__lm = MPolynomial_polydict(R,polydict.PolyDict({f:one},zero=R.base_ring().zero_element(),force_int_exponents=False, force_etuples=False)) + self.__lm = MPolynomial_polydict(R,polydict.PolyDict({f:one},zero=R.base_ring().zero(),force_int_exponents=False, force_etuples=False)) return self.__lm def lc(self): @@ -1395,7 +1395,7 @@ def lt(self): R = self.parent() f = self._MPolynomial_element__element.dict() res = self._MPolynomial_element__element.lcmt( R.term_order().greater_tuple ) - self.__lt = MPolynomial_polydict(R,polydict.PolyDict({res:f[res]},zero=R.base_ring().zero_element(),force_int_exponents=False, force_etuples=False)) + self.__lt = MPolynomial_polydict(R,polydict.PolyDict({res:f[res]},zero=R.base_ring().zero(),force_int_exponents=False, force_etuples=False)) return self.__lt def __eq__(self,right): @@ -1465,7 +1465,7 @@ def __floordiv__(self,right): if len(right.dict()) == 1: P = self.parent() ret = P(0) - denC,denM = iter(right).next() + denC,denM = next(iter(right)) for c,m in self: t = c*m if denC.divides(c) and P.monomial_divides(denM, m): diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index 34e13503ee3..d940e3cd861 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -245,7 +245,7 @@ from sage.structure.sequence import Sequence from sage.misc.cachefunc import cached_method -from sage.misc.misc import prod, verbose, get_verbose +from sage.misc.all import prod, verbose, get_verbose from sage.misc.method_decorator import MethodDecorator from sage.rings.integer_ring import ZZ @@ -255,321 +255,9 @@ from warnings import warn -class LibSingularDefaultContext: - def __init__(self, singular=singular_default): - from sage.libs.singular.option import opt_ctx - self.libsingular_option_context = opt_ctx - def __enter__(self): - """ - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import SingularDefaultContext - sage: P. = PolynomialRing(QQ,3, order='lex') - sage: I = sage.rings.ideal.Katsura(P,3) - sage: singular.option('noredTail') - sage: singular.option('noredThrough') - sage: Is = I._singular_() - sage: with SingularDefaultContext(): rgb = Is.groebner() - sage: rgb - 84*c^4-40*c^3+c^2+c, - 7*b+210*c^3-79*c^2+3*c, - 7*a-420*c^3+158*c^2+8*c-7 - """ - self.libsingular_option_context.__enter__() - self.libsingular_option_context.opt.reset_default() - self.libsingular_option_context.opt['red_sb'] = True - self.libsingular_option_context.opt['red_tail'] = True - self.libsingular_option_context.opt['deg_bound'] = 0 - self.libsingular_option_context.opt['mult_bound'] = 0 - - def __exit__(self, typ, value, tb): - """ - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import SingularDefaultContext - sage: P. = PolynomialRing(QQ,3, order='lex') - sage: I = sage.rings.ideal.Katsura(P,3) - sage: singular.option('noredTail') - sage: singular.option('noredThrough') - sage: Is = I._singular_() - sage: with SingularDefaultContext(): rgb = Is.groebner() - sage: rgb - 84*c^4-40*c^3+c^2+c, - 7*b+210*c^3-79*c^2+3*c, - 7*a-420*c^3+158*c^2+8*c-7 - """ - self.libsingular_option_context.__exit__(typ,value,tb) - - -class SingularDefaultContext: - """ - Within this context all Singular Groebner basis calculations are - reduced automatically. - - AUTHORS: - - - Martin Albrecht - - Simon King - """ - def __init__(self, singular=singular_default): - """ - Within this context all Singular Groebner basis calculations - are reduced automatically. - - INPUT: - - - ``singular`` - Singular instance (default: default instance) - - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import SingularDefaultContext - sage: P. = PolynomialRing(QQ,3, order='lex') - sage: I = sage.rings.ideal.Katsura(P,3) - sage: singular.option('noredTail') - sage: singular.option('noredThrough') - sage: Is = I._singular_() - sage: gb = Is.groebner() - sage: gb - 84*c^4-40*c^3+c^2+c, - 7*b+210*c^3-79*c^2+3*c, - a+2*b+2*c-1 - - :: - - sage: with SingularDefaultContext(): rgb = Is.groebner() - sage: rgb - 84*c^4-40*c^3+c^2+c, - 7*b+210*c^3-79*c^2+3*c, - 7*a-420*c^3+158*c^2+8*c-7 - - Note that both bases are Groebner bases because they have - pairwise prime leading monomials but that the monic version of - the last element in ``rgb`` is smaller than the last element - of ``gb`` with respect to the lexicographical term ordering. :: - - sage: (7*a-420*c^3+158*c^2+8*c-7)/7 < (a+2*b+2*c-1) - True - - .. NOTE:: - - This context is used automatically internally whenever a - Groebner basis is computed so the user does not need to use - it manually. - """ - self.singular = singular - - def __enter__(self): - """ - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import SingularDefaultContext - sage: P. = PolynomialRing(QQ,3, order='lex') - sage: I = sage.rings.ideal.Katsura(P,3) - sage: singular.option('noredTail') - sage: singular.option('noredThrough') - sage: Is = I._singular_() - sage: with SingularDefaultContext(): rgb = Is.groebner() - sage: rgb - 84*c^4-40*c^3+c^2+c, - 7*b+210*c^3-79*c^2+3*c, - 7*a-420*c^3+158*c^2+8*c-7 - """ - from sage.interfaces.singular import SingularError - try: - self.bck_degBound = int(self.singular.eval('degBound')) - except SingularError: - self.bck_degBound = int(0) - try: - self.bck_multBound = int(self.singular.eval('multBound')) - except SingularError: - self.bck_multBound = int(0) - self.o = self.singular.option("get") - self.singular.option('set',self.singular._saved_options) - self.singular.option("redSB") - self.singular.option("redTail") - try: - self.singular.eval('degBound=0') - except SingularError: - pass - try: - self.singular.eval('multBound=0') - except SingularError: - pass - - def __exit__(self, typ, value, tb): - """ - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import SingularDefaultContext - sage: P. = PolynomialRing(QQ,3, order='lex') - sage: I = sage.rings.ideal.Katsura(P,3) - sage: singular.option('noredTail') - sage: singular.option('noredThrough') - sage: Is = I._singular_() - sage: with SingularDefaultContext(): rgb = Is.groebner() - sage: rgb - 84*c^4-40*c^3+c^2+c, - 7*b+210*c^3-79*c^2+3*c, - 7*a-420*c^3+158*c^2+8*c-7 - """ - from sage.interfaces.singular import SingularError - self.singular.option("set",self.o) - try: - self.singular.eval('degBound=%d'%self.bck_degBound) - except SingularError: - pass - try: - self.singular.eval('multBound=%d'%self.bck_multBound) - except SingularError: - pass - -def singular_standard_options(func): - r""" - Decorator to force a reduced Singular groebner basis. - - TESTS:: - - sage: P. = PolynomialRing(GF(127)) - sage: J = sage.rings.ideal.Cyclic(P).homogenize() - sage: from sage.misc.sageinspect import sage_getsource - sage: "buchberger" in sage_getsource(J.interreduced_basis) #indirect doctest - True - - The following tests against a bug that was fixed in trac ticket #11298:: - - sage: from sage.misc.sageinspect import sage_getsourcelines, sage_getargspec - sage: P. = QQ[] - sage: I = P*[x,y] - sage: sage_getargspec(I.interreduced_basis) - ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None) - sage: sage_getsourcelines(I.interreduced_basis) - ([' @singular_standard_options\n', - ' @libsingular_standard_options\n', - ' def interreduced_basis(self):\n', - ... - ' return ret\n'], ...) - - .. NOTE:: - - This decorator is used automatically internally so the user - does not need to use it manually. - """ - from sage.misc.decorators import sage_wraps - @sage_wraps(func) - def wrapper(*args, **kwds): -# """ -# Execute function in ``SingularDefaultContext``. -# """ - with SingularDefaultContext(): - return func(*args, **kwds) - return wrapper - -def libsingular_standard_options(func): - r""" - Decorator to force a reduced Singular groebner basis. - - TESTS:: - - sage: P. = PolynomialRing(GF(127)) - sage: J = sage.rings.ideal.Cyclic(P).homogenize() - sage: from sage.misc.sageinspect import sage_getsource - sage: "buchberger" in sage_getsource(J.interreduced_basis) - True - - The following tests against a bug that was fixed in trac ticket #11298:: - - sage: from sage.misc.sageinspect import sage_getsourcelines, sage_getargspec - sage: P. = QQ[] - sage: I = P*[x,y] - sage: sage_getargspec(I.interreduced_basis) - ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None) - sage: sage_getsourcelines(I.interreduced_basis) - ([' @singular_standard_options\n', - ' @libsingular_standard_options\n', - ' def interreduced_basis(self):\n', - ... - ' return ret\n'], ...) - - .. NOTE:: - - This decorator is used automatically internally so the user - does not need to use it manually. - """ - from sage.misc.decorators import sage_wraps - @sage_wraps(func) - def wrapper(*args, **kwds): - """ - Execute function in ``LibSingularDefaultContext``. - """ - with LibSingularDefaultContext(): - return func(*args, **kwds) - return wrapper - -class MagmaDefaultContext: - """ - Context to force preservation of verbosity options for Magma's - Groebner basis computation. - """ - def __init__(self, magma=magma_default): - """ - INPUT: - - - ``magma`` - (default: ``magma_default``) - - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import MagmaDefaultContext # optional - magma - sage: magma.SetVerbose('Groebner',1) # optional - magma - sage: with MagmaDefaultContext(): magma.GetVerbose('Groebner') # optional - magma - 0 - """ - self.magma = magma - def __enter__(self): - """ - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import MagmaDefaultContext - sage: magma.SetVerbose('Groebner',1) # optional - magma - sage: with MagmaDefaultContext(): magma.GetVerbose('Groebner') # optional - magma - 0 - """ - self.groebner_basis_verbose = self.magma.GetVerbose('Groebner') - self.magma.SetVerbose('Groebner',0) - def __exit__(self, typ, value, tb): - """ - EXAMPLE:: - - sage: from sage.rings.polynomial.multi_polynomial_ideal import MagmaDefaultContext - sage: magma.SetVerbose('Groebner',1) # optional - magma - sage: with MagmaDefaultContext(): magma.GetVerbose('Groebner') # optional - magma - 0 - sage: magma.GetVerbose('Groebner') # optional - magma - 1 - """ - self.magma.SetVerbose('Groebner',self.groebner_basis_verbose) - -def magma_standard_options(func): - """ - Decorator to force default options for Magma. - - EXAMPLE:: - - sage: P. = PolynomialRing(GF(127)) - sage: J = sage.rings.ideal.Cyclic(P).homogenize() - sage: from sage.misc.sageinspect import sage_getsource - sage: "mself" in sage_getsource(J._groebner_basis_magma) - True - - """ - from sage.misc.decorators import sage_wraps - @sage_wraps(func) - def wrapper(*args, **kwds): - """ - Execute function in ``MagmaDefaultContext``. - """ - with MagmaDefaultContext(): - return func(*args, **kwds) - return wrapper +from sage.interfaces.magma import magma_gb_standard_options +from sage.interfaces.singular import singular_gb_standard_options +from sage.libs.singular.standard_options import libsingular_gb_standard_options class RequireField(MethodDecorator): """ @@ -666,7 +354,7 @@ def _magma_init_(self, magma): G = magma(self.gens()) return 'ideal<%s|%s>'%(P.name(), G._ref()) - @magma_standard_options + @magma_gb_standard_options def _groebner_basis_magma(self, deg_bound=None, prot=False, magma=magma_default): """ Computes a Groebner Basis for this ideal using Magma if @@ -763,15 +451,15 @@ def syzygy_module(self): ALGORITHM: Uses Singular's syz command """ - import sage.libs.singular - syz = sage.libs.singular.ff.syz + import sage.libs.singular.function_factory + syz = sage.libs.singular.function_factory.ff.syz from sage.matrix.constructor import matrix #return self._singular_().syz().transpose().sage_matrix(self.ring()) S = syz(self) return matrix(self.ring(), S) - @libsingular_standard_options + @libsingular_gb_standard_options def _groebner_basis_libsingular(self, algorithm="groebner", *args, **kwds): """ Return the reduced Groebner basis of this ideal. If the @@ -825,11 +513,12 @@ def _groebner_basis_libsingular(self, algorithm="groebner", *args, **kwds): Uses libSINGULAR. """ from sage.rings.polynomial.multi_polynomial_ideal_libsingular import std_libsingular, slimgb_libsingular - from sage.libs.singular import singular_function + from sage.libs.singular.function import singular_function from sage.libs.singular.option import opt + from sage.misc.stopgap import stopgap - import sage.libs.singular - groebner = sage.libs.singular.ff.groebner + import sage.libs.singular.function_factory + groebner = sage.libs.singular.function_factory.ff.groebner if get_verbose()>=2: opt['prot'] = True @@ -840,10 +529,14 @@ def _groebner_basis_libsingular(self, algorithm="groebner", *args, **kwds): T = self.ring().term_order() if algorithm == "std": + if self.base_ring() == ZZ: + stopgap("Singular's std() and related computations in polynomial rings over ZZ contains bugs and may be mathematically unreliable.", 17676) S = std_libsingular(self) elif algorithm == "slimgb": S = slimgb_libsingular(self) elif algorithm == "groebner": + if self.base_ring() == ZZ: + stopgap("Singular's groebner() and related computations in polynomial rings over ZZ contains bugs and may be mathematically unreliable.", 17676) S = groebner(self) else: try: @@ -972,7 +665,7 @@ def plot(self, singular=singular_default): I.plot() @require_field - @libsingular_standard_options + @libsingular_gb_standard_options def complete_primary_decomposition(self, algorithm="sy"): r""" Return a list of primary ideals such that their intersection @@ -1075,13 +768,13 @@ def complete_primary_decomposition(self, algorithm="sy"): if self.is_one(): return [] - import sage.libs.singular + import sage.libs.singular.function_factory if algorithm == 'sy': - primdecSY = sage.libs.singular.ff.primdec__lib.primdecSY + primdecSY = sage.libs.singular.function_factory.ff.primdec__lib.primdecSY P = primdecSY(self) elif algorithm == 'gtz': - primdecGTZ = sage.libs.singular.ff.primdec__lib.primdecGTZ + primdecGTZ = sage.libs.singular.function_factory.ff.primdec__lib.primdecGTZ P = primdecGTZ(self) R = self.ring() @@ -1272,8 +965,8 @@ def is_prime(self, **kwds): return self == P @require_field - @singular_standard_options - @libsingular_standard_options + @singular_gb_standard_options + @libsingular_gb_standard_options def triangular_decomposition(self, algorithm=None, singular=singular_default): """ Decompose zero-dimensional ideal ``self`` into triangular @@ -1436,8 +1129,8 @@ def dimension(self, singular=singular_default): return self.__dimension except AttributeError: try: - import sage.libs.singular - dim = sage.libs.singular.ff.dim + import sage.libs.singular.function_factory + dim = sage.libs.singular.function_factory.ff.dim v = MPolynomialIdeal(self.ring(),self.groebner_basis()) self.__dimension = Integer(dim(v, attributes={v:{'isSB':1}})) except TypeError: @@ -1472,7 +1165,7 @@ def dimension(self, singular=singular_default): all_J = iter(all_J) while min_dimension == -1: try: - J = all_J.next() + J = next(all_J) except StopIteration: min_dimension = n break @@ -1520,8 +1213,8 @@ def vector_space_dimension(self): R = self.ring() gb = R.ideal(self.groebner_basis()) - import sage.libs.singular - vdim = sage.libs.singular.ff.vdim + import sage.libs.singular.function_factory + vdim = sage.libs.singular.function_factory.ff.vdim vd = Integer(vdim(gb, attributes={gb:{'isSB':1}})) if vd == -1: @@ -1601,7 +1294,7 @@ def _groebner_basis_ginv(self, algorithm="TQ", criteria='CritPartially', divisio G = Sequence([P(str(f)) for f in G.iterGB()]) return G - @singular_standard_options + @singular_gb_standard_options def _groebner_basis_singular(self, algorithm="groebner", *args, **kwds): """ Return the reduced Groebner basis of this ideal. If the @@ -1695,8 +1388,8 @@ def _groebner_basis_singular_raw(self, algorithm="groebner", singular=singular_d # return self.__gb_singular #except AttributeError: # pass - # singular options are preserved by @singular_standard_options, - # so we don't eed to do that here too + # singular options are preserved by @singular_gb_standard_options, + # so we don't need to do that here too from sage.libs.singular.option import _options_py_to_singular S = self._singular_() # for degBound, we need to ensure # that a ring is defined @@ -1796,12 +1489,12 @@ def genus(self): try: return self.__genus except AttributeError: - import sage.libs.singular - genus = sage.libs.singular.ff.normal__lib.genus + import sage.libs.singular.function_factory + genus = sage.libs.singular.function_factory.ff.normal__lib.genus self.__genus = Integer(genus(self)) return self.__genus - @libsingular_standard_options + @libsingular_gb_standard_options def intersection(self, *others): """ Return the intersection of the arguments with this ideal. @@ -1855,14 +1548,14 @@ def intersection(self, *others): if not isinstance(other, MPolynomialIdeal_singular_repr) or other.ring() != R: raise TypeError("Intersection is only available for ideals of the same ring.") - import sage.libs.singular - intersect = sage.libs.singular.ff.intersect + import sage.libs.singular.function_factory + intersect = sage.libs.singular.function_factory.ff.intersect K = intersect(self, *others) return R.ideal(K) @require_field - @libsingular_standard_options + @libsingular_gb_standard_options def minimal_associated_primes(self): """ OUTPUT: @@ -1884,15 +1577,15 @@ def minimal_associated_primes(self): Uses Singular. """ - import sage.libs.singular - minAssGTZ = sage.libs.singular.ff.primdec__lib.minAssGTZ + import sage.libs.singular.function_factory + minAssGTZ = sage.libs.singular.function_factory.ff.primdec__lib.minAssGTZ M = minAssGTZ(self) R = self.ring() return [R.ideal(J) for J in M] @require_field - @libsingular_standard_options + @libsingular_gb_standard_options def radical(self): r""" The radical of this ideal. @@ -1932,8 +1625,8 @@ def radical(self): sage: I.radical() Ideal (z^2 - y, y^2*z + y*z + 2*y + 2) of Multivariate Polynomial Ring in x, y, z over Finite Field of size 37 """ - import sage.libs.singular - radical = sage.libs.singular.ff.primdec__lib.radical + import sage.libs.singular.function_factory + radical = sage.libs.singular.function_factory.ff.primdec__lib.radical r = radical(self) S = self.ring() @@ -1945,7 +1638,7 @@ def radical(self): return S.ideal(r) @require_field - @libsingular_standard_options + @libsingular_gb_standard_options def integral_closure(self, p=0, r=True, singular=singular_default): """ Let `I` = ``self``. @@ -1979,8 +1672,8 @@ def integral_closure(self, p=0, r=True, singular=singular_default): from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence R = self.ring() - import sage.libs.singular - normalI = sage.libs.singular.ff.reesclos__lib.normalI + import sage.libs.singular.function_factory + normalI = sage.libs.singular.function_factory.ff.reesclos__lib.normalI ret = PolynomialSequence(normalI(self, p, int(r))[0], R, immutable=True) return ret @@ -2008,16 +1701,16 @@ def syzygy_module(self): Uses Singular's syz command. """ - import sage.libs.singular - syz = sage.libs.singular.ff.syz + import sage.libs.singular.function_factory + syz = sage.libs.singular.function_factory.ff.syz from sage.matrix.constructor import matrix #return self._singular_().syz().transpose().sage_matrix(self.ring()) S = syz(self) return matrix(self.ring(), S) - @singular_standard_options - @libsingular_standard_options + @singular_gb_standard_options + @libsingular_gb_standard_options def interreduced_basis(self): r""" If this ideal is spanned by `(f_1, ..., f_n)` this method @@ -2067,33 +1760,10 @@ def interreduced_basis(self): :func:`sage.rings.polynomial.toy_buchberger.inter_reduction` if conversion to Singular fails. """ - from sage.rings.polynomial.multi_polynomial_ideal_libsingular import interred_libsingular - from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence - - R = self.ring() - - if isinstance(R,MPolynomialRing_libsingular): - return PolynomialSequence(R, interred_libsingular(self), immutable=True) - else: - try: - s = self._singular_().parent() - o = s.option("get") - s.option("redTail") - ret = [] - for f in self._singular_().interred(): - f = R(f) - ret.append(f.lc()**(-1)*f) # lead coeffs are not reduced by interred - s.option("set",o) - except TypeError: - ret = toy_buchberger.inter_reduction(self.gens()) - - ret = sorted(ret, reverse=True) - ret = PolynomialSequence(R, ret, immutable=True) - return ret + return self.basis.reduced() @cached_method - @singular_standard_options + @singular_gb_standard_options def basis_is_groebner(self, singular=singular_default): r""" Returns ``True`` if the generators of this ideal @@ -2167,9 +1837,9 @@ def basis_is_groebner(self, singular=singular_default): """ from sage.matrix.constructor import matrix from sage.libs.singular.option import opt_verb_ctx - import sage.libs.singular - sing_reduce = sage.libs.singular.ff.reduce - syz = sage.libs.singular.ff.syz + import sage.libs.singular.function_factory + sing_reduce = sage.libs.singular.function_factory.ff.reduce + syz = sage.libs.singular.function_factory.ff.syz R = self.ring() if not R.base_ring().is_field(): @@ -2201,42 +1871,35 @@ def basis_is_groebner(self, singular=singular_default): return True @require_field - @singular_standard_options - @libsingular_standard_options + @singular_gb_standard_options + @libsingular_gb_standard_options def transformed_basis(self, algorithm="gwalk", other_ring=None, singular=singular_default): """ Returns a lex or ``other_ring`` Groebner Basis for this ideal. INPUT: - - ``algorithm`` - see below for options. + - ``algorithm`` - see below for options. - ``other_ring`` - only valid for algorithm 'fglm', if - provided conversion will be performed to this - ring. Otherwise a lex Groebner basis will be returned. + provided conversion will be performed to this + ring. Otherwise a lex Groebner basis will be returned. ALGORITHMS: - fglm - FGLM algorithm. The input ideal must be given with a reduced - Groebner Basis of a zero-dimensional ideal - - gwalk - Groebner Walk algorithm (*default*) + - ``fglm`` - FGLM algorithm. The input ideal must be given with a reduced + Groebner Basis of a zero-dimensional ideal - awalk1 - 'first alternative' algorithm + - ``gwalk`` - Groebner Walk algorithm (*default*) - awalk2 - 'second alternative' algorithm + - ``awalk1`` - 'first alternative' algorithm - twalk - Tran algorithm + - ``awalk2`` - 'second alternative' algorithm - fwalk - Fractal Walk algorithm + - ``twalk`` - Tran algorithm + - ``fwalk`` - Fractal Walk algorithm EXAMPLES:: @@ -2247,7 +1910,7 @@ def transformed_basis(self, algorithm="gwalk", other_ring=None, singular=singula sage: J = Ideal(I.transformed_basis('fglm',S)) sage: J Ideal (z^4 + y^3 - y, x^2 + y^3, x*y^3 - y^3, y^4 + y^3) - of Multivariate Polynomial Ring in z, x, y over Rational Field + of Multivariate Polynomial Ring in z, x, y over Rational Field :: @@ -2281,6 +1944,7 @@ def transformed_basis(self, algorithm="gwalk", other_ring=None, singular=singula lib("grwalk.lib") gb = singular_function(algorithm)(I) return PolynomialSequence(R, sorted(gb,reverse=True), immutable=True) + elif algorithm == "fglm": # new ring if other_ring is None: @@ -2298,7 +1962,7 @@ def transformed_basis(self, algorithm="gwalk", other_ring=None, singular=singula else: raise TypeError("Cannot convert basis with given algorithm") - @libsingular_standard_options + @libsingular_gb_standard_options def elimination_ideal(self, variables): r""" Returns the elimination ideal this ideal with respect to the @@ -2325,8 +1989,8 @@ def elimination_ideal(self, variables): Requires computation of a Groebner basis, which can be a very expensive operation. """ - import sage.libs.singular - eliminate = sage.libs.singular.ff.eliminate + import sage.libs.singular.function_factory + eliminate = sage.libs.singular.function_factory.ff.eliminate if not isinstance(variables, (list,tuple)): variables = (variables,) @@ -2335,7 +1999,7 @@ def elimination_ideal(self, variables): Is = MPolynomialIdeal(R,self.groebner_basis()) return MPolynomialIdeal(R, eliminate(Is, prod(variables)) ) - @libsingular_standard_options + @libsingular_gb_standard_options def quotient(self, J): r""" Given ideals `I` = ``self`` and `J` in the same polynomial @@ -2372,6 +2036,7 @@ def quotient(self, J): sage: I.quotient(eD).gens() [2, x*z + x, x*y] """ + from sage.misc.stopgap import stopgap R = self.ring() if not isinstance(J, MPolynomialIdeal): @@ -2380,8 +2045,10 @@ def quotient(self, J): if not R is J.ring() and not R == J.ring(): raise TypeError("base rings do not match") - import sage.libs.singular - quotient = sage.libs.singular.ff.quotient + import sage.libs.singular.function_factory + if self.base_ring() == ZZ: + stopgap("Singular's quotient()-routine for rings over ZZ contains bugs and may be mathematically unreliable", 12803) + quotient = sage.libs.singular.function_factory.ff.quotient return R.ideal(quotient(self, J)) def saturation(self, other): @@ -2404,7 +2071,7 @@ def saturation(self, other): sage: I.saturation(J) (Ideal (y, x^5) of Multivariate Polynomial Ring in x, y, z over Rational Field, 4) """ - from sage.libs.singular import ff + from sage.libs.singular.function_factory import ff sat = ff.elim__lib.sat R = self.ring() ideal, expo = sat(self, other) @@ -2712,8 +2379,8 @@ def hilbert_polynomial(self): if not self.is_homogeneous(): raise TypeError("Ideal must be homogeneous.") - import sage.libs.singular - hilbPoly = sage.libs.singular.ff.poly__lib.hilbPoly + import sage.libs.singular.function_factory + hilbPoly = sage.libs.singular.function_factory.ff.poly__lib.hilbPoly hp = hilbPoly(self) t = ZZ['t'].gen() @@ -2824,8 +2491,8 @@ def hilbert_numerator(self, singular=singular_default, grading=None): if not self.is_homogeneous(): raise TypeError("Ideal must be homogeneous.") - import sage.libs.singular - hilb = sage.libs.singular.ff.hilb + import sage.libs.singular.function_factory + hilb = sage.libs.singular.function_factory.ff.hilb gb = self.groebner_basis() t = ZZ['t'].gen() @@ -3018,12 +2685,12 @@ def __init__(self, ring, gens, coerce=True, side = "left"): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H.inject_variables() Defining x, y, z - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) # indirect doctest + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False) # indirect doctest sage: I Left Ideal (y^2, x^2, z^2 - 1) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {z*x: x*z + 2*x, z*y: y*z - 2*y, y*x: x*y - z} - sage: H.ideal([y^2, x^2, z^2-H.one_element()], side="twosided") + sage: H.ideal([y^2, x^2, z^2-H.one()], side="twosided") Twosided Ideal (y^2, x^2, z^2 - 1) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {z*x: x*z + 2*x, z*y: y*z - 2*y, y*x: x*y - z} - sage: H.ideal([y^2, x^2, z^2-H.one_element()], side="right") + sage: H.ideal([y^2, x^2, z^2-H.one()], side="right") Traceback (most recent call last): ... ValueError: Only left and two-sided ideals are allowed. @@ -3074,7 +2741,7 @@ def std(self): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H.inject_variables() Defining x, y, z - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False) sage: I.std() Left Ideal (z^2 - 1, y*z - y, x*z + x, y^2, 2*x*y - z - 1, x^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {z*x: x*z + 2*x, z*y: y*z - 2*y, y*x: x*y - z} @@ -3113,7 +2780,7 @@ def twostd(self): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H.inject_variables() Defining x, y, z - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False) sage: I.twostd() Twosided Ideal (z^2 - 1, y*z - y, x*z + x, y^2, 2*x*y - z - 1, x^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field... @@ -3135,7 +2802,7 @@ def _groebner_strategy(self): sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False) sage: I._groebner_strategy() Groebner Strategy for ideal generated by 6 elements over Noncommutative Multivariate Polynomial Ring in x, y, z over Rational @@ -3163,12 +2830,12 @@ def reduce(self,p): sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False, side='twosided') + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False, side='twosided') sage: Q = H.quotient(I); Q Quotient of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {z*x: x*z + 2*x, z*y: y*z - 2*y, y*x: x*y - z} by the ideal (y^2, x^2, z^2 - 1) - sage: Q.2^2 == Q.one_element() # indirect doctest + sage: Q.2^2 == Q.one() # indirect doctest True Here, we see that the relation that we just found in the quotient @@ -3231,7 +2898,7 @@ def syzygy_module(self): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H.inject_variables() Defining x, y, z - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False) sage: G = vector(I.gens()); G d...: UserWarning: You are constructing a free module over a noncommutative ring. Sage does not have a concept @@ -3262,8 +2929,8 @@ def syzygy_module(self): """ if self.side() == 'twosided': warn("The result of this Syzygy computation is one-sided (left)!") - import sage.libs.singular - syz = sage.libs.singular.ff.syz + import sage.libs.singular.function_factory + syz = sage.libs.singular.function_factory.ff.syz from sage.matrix.constructor import matrix #return self._singular_().syz().transpose().sage_matrix(self.ring()) @@ -3286,7 +2953,7 @@ def res(self, length): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H.inject_variables() Defining x, y, z - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False) sage: I.res(3) """ @@ -3326,7 +2993,7 @@ def __init__(self, ring, gens, coerce=True): @cached_method def gens(self): """ - Return a set of generators / a basis of self. This is usually the + Return a set of generators / a basis of this ideal. This is usually the set of generators provided during object creation. EXAMPLE:: @@ -3340,6 +3007,21 @@ def gens(self): from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence return PolynomialSequence(self.ring(), Ideal_generic.gens(self), immutable=True) + @property + def basis(self): + """ + Shortcut to ``gens()``. + + EXAMPLE:: + + sage: P. = PolynomialRing(QQ,2) + sage: I = Ideal([x,y+1]) + sage: I.basis + [x, y + 1] + + """ + return self.gens() + def __lt__(self, other): """ Decides whether ``self`` is contained in ``other``. @@ -3415,7 +3097,7 @@ def __lt__(self, other): if other_new.groebner_basis.is_in_cache(): r = other_new.groebner_basis() elif len(other_new._gb_by_ordering) != 0: - o, r = other_new._gb_by_ordering.iteritems().next() + o, r = next(other_new._gb_by_ordering.iteritems()) l = self.change_ring(R.change_ring(order=o)).gens() else: # use easy GB otherwise l = self.change_ring(R.change_ring(order="degrevlex")).gens() @@ -4508,6 +4190,93 @@ def plot(self, *args, **kwds): else: raise TypeError("Ideal generator may not have either 2 or 3 variables.") + def random_element(self, degree, compute_gb=False, *args, **kwds): + """ + Return a random element in this ideal as `r = \sum h_i·f_i`. + + INPUT: + + - ``compute_gb`` - if ``True`` then a Gröbner basis is computed first + and `f_i` are the elements in the Gröbner basis. Otherwise whatever + basis is returned by ``self.gens()`` is used. + + - ``*args`` and ``**kwds`` are passed to ``R.random_element()`` with + ``R = self.ring()``. + + EXAMPLE: + + We compute a uniformly random element up to the provided degree.:: + + sage: P. = GF(127)[] + sage: I = sage.rings.ideal.Katsura(P) + sage: I.random_element(degree=4, compute_gb=True, terms=infinity) + 34*x^4 - 33*x^3*y + 45*x^2*y^2 - 51*x*y^3 - 55*y^4 + 43*x^3*z ... - 28*y - 33*z + 45 + + Note that sampling uniformly at random from the ideal at some large enough degree is + equivalent to computing a Gröbner basis. We give an example showing how to compute a Gröbner + basis if we can sample uniformly at random from an ideal:: + + sage: n = 3; d = 4 + sage: P = PolynomialRing(GF(127), n, 'x') + sage: I = sage.rings.ideal.Cyclic(P) + + 1. We sample `n^d` uniformly random elements in the ideal:: + + sage: F = Sequence(I.random_element(degree=d, compute_gb=True, terms=infinity) for _ in range(n^d)) + + 2. We linearize and compute the echelon form:: + + sage: A,v = F.coefficient_matrix() + sage: A.echelonize() + + 3. The result is the desired Gröbner basis:: + + sage: G = Sequence((A*v).list()) + sage: G.is_groebner() + True + sage: Ideal(G) == I + True + + We return some element in the ideal with no guarantee on the distribution:: + + sage: P = PolynomialRing(GF(127), 10, 'x') + sage: I = sage.rings.ideal.Katsura(P) + sage: I.random_element(degree=3) + 7*x0^2*x1 + 14*x1^3 + 57*x0*x1*x2 - 32*x1^2*x2 - ... + 49*x4 + 48*x5 - 40*x7 - 6*x8 + + We show that the default method does not sample uniformly at random from the ideal:: + + sage: P. = GF(127)[] + sage: G = Sequence([x+7, y-2, z+110]) + sage: I = Ideal([sum(P.random_element() * g for g in G) for _ in range(4)]) + sage: all(I.random_element(degree=1) == 0 for _ in range(100)) + True + + If degree equals the degree of the generators a random linear + combination of the generators is returned:: + + sage: P. = QQ[] + sage: I = P.ideal([x^2,y^2]) + sage: I.random_element(degree=2) + 52*x^2 - 8/3*y^2 + + """ + if compute_gb: + gens = self.groebner_basis() + else: + gens = self.basis + + R = self.ring() + + r = R(0) + + for f in gens: + d = degree - f.degree() + if d >= 0: + h = R.random_element(degree=d, *args, **kwds) + r += h*f + return r + @require_field def weil_restriction(self): """ @@ -4689,7 +4458,7 @@ def weil_restriction(self): variables = iter(intermediate_ring.gens()[1:]) for _ in xrange(nvars): - map_ideal.append(sum([a**i * variables.next() for i in range(r)])) + map_ideal.append(sum([a**i * next(variables) for i in range(r)])) myminpoly = myminpoly(*map_ideal) l = [f(*map_ideal).reduce([myminpoly]) for f in l] @@ -4713,6 +4482,3 @@ def weil_restriction(self): result = [f(*map_ideal) for f in result] return result_ring.ideal(result) - - - diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx index dd966f7c92d..ce2e634c9ca 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx @@ -114,10 +114,24 @@ cdef ideal *sage_ideal_to_singular_ideal(I) except NULL: INPUT: - ``I`` -- a Sage ideal in a ring of type - :class:`~sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular` + :class:`~sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular` or a list of generators. + + TESTS: + + + We test conversion:: + + sage: P. = QQ[] + sage: sage.libs.singular.function_factory.ff.std(Sequence([x,y,z])) + [z, y, x] + sage: sage.libs.singular.function_factory.ff.std(Ideal([x,y,z])) + [z, y, x] """ R = I.ring() - gens = I.gens() + try: + gens = I.gens() + except AttributeError: + gens = I cdef ideal *result cdef ring *r cdef ideal *i @@ -288,10 +302,12 @@ def interred_libsingular(I): cdef int j cdef int bck - - if len(I.gens()) == 0: - return Sequence([], check=False, immutable=True) - + try: + if len(I.gens()) == 0: + return Sequence([], check=False, immutable=True) + except AttributeError: + pass + i = sage_ideal_to_singular_ideal(I) r = currRing diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index 636b52511b8..d2771ef9407 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -239,7 +239,7 @@ from sage.interfaces.all import macaulay2 from sage.interfaces.singular import singular as singular_default, is_SingularElement, SingularElement from sage.interfaces.macaulay2 import macaulay2 as macaulay2_default, is_Macaulay2Element -from sage.misc.misc import mul +from sage.misc.all import prod as mul from sage.misc.sage_eval import sage_eval import sage.libs.pari.gen @@ -2405,12 +2405,11 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn .... OverflowError: Exponent overflow (...). """ - if not PY_TYPE_CHECK_EXACT(exp, Integer) or \ - PY_TYPE_CHECK_EXACT(exp, int): - try: - exp = Integer(exp) - except TypeError: - raise TypeError, "non-integral exponents not supported" + if type(exp) is not Integer: + try: + exp = Integer(exp) + except TypeError: + raise TypeError("non-integral exponents not supported") if exp < 0: return 1/(self**(-exp)) @@ -3279,7 +3278,7 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn sage: P = QQ['x,y'] sage: x = var('x') - sage: parent(P.zero_element() / x) + sage: parent(P.zero() / x) Symbolic Ring We are catching overflows:: @@ -5137,7 +5136,7 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn Miguel Marco """ if self.is_zero(): - return self.parent().zero_element() + return self.parent().zero() n = self.degree(variable) d = self.derivative(variable) k = d.degree(variable) @@ -5353,7 +5352,7 @@ cdef inline MPolynomial_libsingular new_MP(MPolynomialRing_libsingular parent, p polynomial, so it is your repsonsiblity to make a copy if the Singular data structure is used elsewhere. """ - cdef MPolynomial_libsingular p = PY_NEW(MPolynomial_libsingular) + cdef MPolynomial_libsingular p = MPolynomial_libsingular.__new__(MPolynomial_libsingular) p._parent = parent p._parent_ring = singular_ring_reference(parent._ring) p._poly = juice diff --git a/src/sage/rings/polynomial/multi_polynomial_ring_generic.pyx b/src/sage/rings/polynomial/multi_polynomial_ring_generic.pyx index 05a865464ec..8a32ccf7ec0 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ring_generic.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_ring_generic.pyx @@ -737,9 +737,14 @@ cdef class MPolynomialRing_generic(sage.rings.ring.CommutativeRing): INPUT: - ``degree`` -- maximal degree (likely to be reached) (default: 2) - - ``terms`` -- number of terms requested (default: 5) + + - ``terms`` -- number of terms requested (default: 5). If more + terms are requested than exist, then this parameter is + silently reduced to the maximum number of available terms. + - ``choose_degree`` -- choose degrees of monomials randomly first rather than monomials uniformly random. + - ``**kwargs`` -- passed to the random element generator of the base ring @@ -750,43 +755,64 @@ cdef class MPolynomialRing_generic(sage.rings.ring.CommutativeRing): -6/5*x^2 + 2/3*z^2 - 1 sage: P.random_element(2, 5, choose_degree=True) - -1/4*x*y - 1/5*x*z - 1/14*y*z - z^2 + -1/4*x*y - x - 1/14*z - 1 Stacked rings:: sage: R = QQ['x,y'] sage: S = R['t,u'] sage: S.random_element(degree=2, terms=1) - -3*x*y + 5/2*y^2 - 1/2*x - 1/4*y + 4 + -1/2*x^2 - 1/4*x*y - 3*y^2 + 4*y sage: S.random_element(degree=2, terms=1) - (-1/2*x^2 - x*y - 2/7*y^2 + 3/2*x - y)*t*u + (-x^2 - 2*y^2 - 1/3*x + 2*y + 9)*u^2 Default values apply if no degree and/or number of terms is provided:: sage: random_matrix(QQ['x,y,z'], 2, 2) - [ 2*y^2 - 2/27*y*z - z^2 + 2*z 1/2*x*y - 1/2*y^2 + 2*x - 2*y] - [-1/27*x^2 + 2/5*y^2 - 1/10*z^2 - 2*z -13*y^2 + 2/3*z^2 + 2*y] + [357*x^2 + 1/4*y^2 + 2*y*z + 2*z^2 + 28*x 2*x*y + 3/2*y^2 + 2*y*z - 2*z^2 - z] + [ x*y - y*z + 2*z^2 -x^2 - 4/3*x*z + 2*z^2 - x + 4*y] sage: random_matrix(QQ['x,y,z'], 2, 2, terms=1, degree=2) - [-1/4*x 1/2] - [ 1/3*x x*y] + [ 1/2*y -1/4*x] + [ 1/2 1/3*x] sage: P.random_element(0, 1) - -1 + 1 sage: P.random_element(2, 0) 0 sage: R. = PolynomialRing(Integers(3), 1) sage: R.random_element() - x + 1 + -x^2 + x + + To produce a dense polynomial, pick ``terms=Infinity``:: + + sage: P. = GF(127)[] + sage: P.random_element(degree=2, terms=Infinity) + -55*x^2 - 51*x*y + 5*y^2 + 55*x*z - 59*y*z + 20*z^2 + 19*x - 55*y - 28*z + 17 + sage: P.random_element(degree=3, terms=Infinity) + -54*x^3 + 15*x^2*y - x*y^2 - 15*y^3 + 61*x^2*z - 12*x*y*z + 20*y^2*z - 61*x*z^2 - 5*y*z^2 + 62*z^3 + 15*x^2 - 47*x*y + 31*y^2 - 14*x*z + 29*y*z + 13*z^2 + 61*x - 40*y - 49*z + 30 + sage: P.random_element(degree=3, terms=Infinity, choose_degree=True) + 57*x^3 - 58*x^2*y + 21*x*y^2 + 36*y^3 + 7*x^2*z - 57*x*y*z + 8*y^2*z - 11*x*z^2 + 7*y*z^2 + 6*z^3 - 38*x^2 - 18*x*y - 52*y^2 + 27*x*z + 4*y*z - 51*z^2 - 63*x + 7*y + 48*z + 14 + + The number of terms is silently reduced to the maximum + available if more terms are requested:: + + sage: P. = GF(127)[] + sage: P.random_element(degree=2, terms=1000) + 5*x^2 - 10*x*y + 10*y^2 - 44*x*z + 31*y*z + 19*z^2 - 42*x - 50*y - 49*z - 60 + """ k = self.base_ring() n = self.ngens() counts, total = self._precomp_counts(n, degree) + if terms > total: + terms = total + if terms is None: if total >= 5: terms = 5 @@ -794,12 +820,10 @@ cdef class MPolynomialRing_generic(sage.rings.ring.CommutativeRing): terms = total if terms < 0: - raise TypeError, "Cannot compute polynomial with a negative number of terms." + raise TypeError("Cannot compute polynomial with a negative number of terms.") elif terms == 0: return self._zero_element if degree == 0: - if terms != 1: - raise TypeError, "Cannot compute polynomial with more terms than exist." return k.random_element(**kwargs) @@ -842,14 +866,11 @@ cdef class MPolynomialRing_generic(sage.rings.ring.CommutativeRing): for mi in xrange(terms): d = ZZ.random_element(0,len(M)) #choose degree at random m = ZZ.random_element(0,len(M[d])) # choose monomial at random - Mbar.append( M[degree].pop(m) ) # remove and insert - if len(M[degree]) == 0: - M.pop(degree) # bookkeeping + Mbar.append( M[d].pop(m) ) # remove and insert + if len(M[d]) == 0: + M.pop(d) # bookkeeping M = map(tuple, Mbar) - else: - raise TypeError, "Cannot compute polynomial with more terms than exist." - C = [k.random_element(*args,**kwargs) for _ in range(len(M))] return self(dict(zip(M,C))) diff --git a/src/sage/rings/polynomial/multi_polynomial_sequence.py b/src/sage/rings/polynomial/multi_polynomial_sequence.py index 623b56087e6..8a3786d7849 100644 --- a/src/sage/rings/polynomial/multi_polynomial_sequence.py +++ b/src/sage/rings/polynomial/multi_polynomial_sequence.py @@ -154,6 +154,8 @@ ------- """ +from sage.misc.cachefunc import cached_method + from types import GeneratorType from sage.misc.package import is_package_installed @@ -168,6 +170,8 @@ from sage.rings.polynomial.multi_polynomial import is_MPolynomial from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.interfaces.singular import singular_gb_standard_options +from sage.libs.singular.standard_options import libsingular_gb_standard_options from sage.interfaces.singular import singular def is_PolynomialSequence(F): @@ -236,8 +240,7 @@ def PolynomialSequence(arg1, arg2=None, immutable=False, cr=False, cr_str=None): 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c] - If a list of polynomials is provided, the system has only one - part:: + If a list of polynomials is provided, the system has only one part:: sage: F = Sequence(I.gens(), I.ring()); F [a + 2*b + 2*c + 2*d - 1, @@ -246,75 +249,95 @@ def PolynomialSequence(arg1, arg2=None, immutable=False, cr=False, cr_str=None): b^2 + 2*a*c + 2*b*d - c] sage: F.nparts() 1 + + We test that the ring is inferred correctly:: + + sage: P. = GF(2)[] + sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + sage: PolynomialSequence([1,x,y]).ring() + Multivariate Polynomial Ring in x, y, z over Finite Field of size 2 + + sage: PolynomialSequence([[1,x,y], [0]]).ring() + Multivariate Polynomial Ring in x, y, z over Finite Field of size 2 """ from sage.matrix.matrix import is_Matrix + from sage.rings.polynomial.pbori import BooleanMonomialMonoid, BooleanMonomial - if is_MPolynomialRing(arg1) or is_QuotientRing(arg1): - ring = arg1 - gens = arg2 - - elif is_MPolynomialRing(arg2) or is_QuotientRing(arg2): - ring = arg2 - gens = arg1 + is_ring = lambda r: is_MPolynomialRing(r) or isinstance(r, BooleanMonomialMonoid) or (is_QuotientRing(r) and is_MPolynomialRing(r.cover_ring())) + is_poly = lambda f: is_MPolynomial(f) or isinstance(f, QuotientRingElement) or isinstance(f, BooleanMonomial) - elif is_Matrix(arg1) and arg2 is None: - ring = arg1.base_ring() - gens = arg1.list() + if is_ring(arg1): + ring, gens = arg1, arg2 - elif isinstance(arg1, MPolynomialIdeal) and arg2 is None: - ring = arg1.ring() - gens = arg1.gens() + elif is_ring(arg2): + ring, gens = arg2, arg1 - elif isinstance(arg1, (list,tuple,GeneratorType)) and arg2 is None: - gens = arg1 + elif is_Matrix(arg1): + ring, gens = arg1.base_ring(), arg1.list() - try: - e = iter(gens).next() - except StopIteration: - raise ValueError("Cannot determine ring from provided information.") + elif isinstance(arg1, MPolynomialIdeal): + ring, gens = arg1.ring(), arg1.gens() + else: + gens = list(arg1) - if is_MPolynomial(e) or isinstance(e, QuotientRingElement): - ring = e.parent() + if arg2: + ring = arg2 + if not is_ring(ring): + raise TypeError("Ring '%s' not supported."%ring) else: - ring = iter(e).next().parent() - else: - raise TypeError("Cannot understand input.") + try: + e = next(iter(gens)) + except StopIteration: + raise ValueError("Cannot determine ring from provided information.") + + import sage.structure.element as coerce + + el = 0 + + for f in gens: + try: + el, _ = coerce.canonical_coercion(el, f) + except TypeError: + el = 0 + for part in gens: + for f in part: + el, _ = coerce.canonical_coercion(el, f) + + if is_ring(el.parent()): + ring = el.parent() + else: + raise TypeError("Cannot determine ring.") try: - e = iter(gens).next() + e = next(iter(gens)) - if is_MPolynomial(e) or isinstance(e, QuotientRingElement): - gens = tuple(gens) - parts = (gens,) - if not all(f.parent() is ring for f in gens): - parts = ((ring(f) for f in gens),) - else: - parts = [] - _gens = [] - for part in gens: - _part = [] - for gen in part: - if not gen.parent() is ring: - ring(gen) - _part.append(gen) - _gens.extend(_part) - parts.append(tuple(_part)) - gens = _gens + try: + parts = tuple(map(ring, gens)), + except TypeError: + parts = tuple(tuple(ring(f) for f in part) for part in gens) except StopIteration: - gens = tuple() parts = ((),) - k = ring.base_ring() + K = ring.base_ring() + + try: + c = K.characteristic() + except NotImplementedError: + # We assume that our ring has characteristic zero if it does not implement a + # characteristic(). For example, generic quotient rings do not have a characteristic() + # method implemented. It is okay to set c = 0 here because we're only using the + # characteristic to pick a more specialized implementation for c = 2. + c = 0 - try: c = k.characteristic() - except NotImplementedError: c = -1 + # make sure we use the polynomial ring as ring not the monoid + ring = (ring(1) + ring(1)).parent() if c != 2: return PolynomialSequence_generic(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str) - elif k.degree() == 1: + elif K.degree() == 1: return PolynomialSequence_gf2(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str) - elif k.degree() > 1: + elif K.degree() > 1: return PolynomialSequence_gf2e(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str) class PolynomialSequence_generic(Sequence_generic): @@ -912,6 +935,27 @@ def _groebner_strategy(self): from sage.libs.singular.groebner_strategy import GroebnerStrategy return GroebnerStrategy(self.ideal()) + def maximal_degree(self): + """ + Return the maximal degree of any polynomial in this sequence. + + EXAMPLE:: + + sage: P. = PolynomialRing(GF(7)) + sage: F = Sequence([x*y + x, x]) + sage: F.maximal_degree() + 2 + sage: P. = PolynomialRing(GF(7)) + sage: F = Sequence([], universe=P) + sage: F.maximal_degree() + -1 + + """ + try: + return max(f.degree() for f in self) + except ValueError: + return -1 # empty sequence + def __reduce__(self): """ TESTS:: @@ -923,6 +967,117 @@ def __reduce__(self): """ return PolynomialSequence, (self._ring, self._parts) + @singular_gb_standard_options + @libsingular_gb_standard_options + def reduced(self): + r""" + If this sequence is `(f_1, ..., f_n)` then this method + returns `(g_1, ..., g_s)` such that: + + - `(f_1,...,f_n) = (g_1,...,g_s)` + + - `LT(g_i) != LT(g_j)` for all `i != j` + + - `LT(g_i)` does not divide `m` for all monomials `m` of + `\{g_1,...,g_{i-1},g_{i+1},...,g_s\}` + + - `LC(g_i) == 1` for all `i` if the coefficient ring is a field. + + EXAMPLE:: + + sage: R. = PolynomialRing(QQ) + sage: F = Sequence([z*x+y^3,z+y^3,z+x*y]) + sage: F.reduced() + [y^3 + z, x*y + z, x*z - z] + + Note that tail reduction for local orderings is not well-defined:: + + sage: R. = PolynomialRing(QQ,order='negdegrevlex') + sage: F = Sequence([z*x+y^3,z+y^3,z+x*y]) + sage: F.reduced() + [z + x*y, x*y - y^3, x^2*y - y^3] + + A fixed error with nonstandard base fields:: + + sage: R.=QQ['t'] + sage: K.=R.fraction_field()['x,y'] + sage: I=t*x*K + sage: I.basis.reduced() + [x] + + The interreduced basis of 0 is 0:: + + sage: P. = GF(2)[] + sage: Sequence([P(0)]).reduced() + [0] + + Leading coefficients are reduced to 1:: + + sage: P. = QQ[] + sage: Sequence([2*x,y]).reduced() + [x, y] + + sage: P. = CC[] + sage: Sequence([2*x,y]).reduced() + [x, y] + + ALGORITHM: + + Uses Singular's interred command or + :func:`sage.rings.polynomial.toy_buchberger.inter_reduction`` + if conversion to Singular fails. + """ + from sage.rings.polynomial.multi_polynomial_ideal_libsingular import interred_libsingular + from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular + + R = self.ring() + + if isinstance(R,MPolynomialRing_libsingular): + return PolynomialSequence(R, interred_libsingular(self), immutable=True) + else: + try: + s = self._singular_().parent() + o = s.option("get") + s.option("redTail") + ret = [] + for f in self._singular_().interred(): + f = R(f) + ret.append(f.lc()**(-1)*f) # lead coeffs are not reduced by interred + s.option("set",o) + except TypeError: + ret = toy_buchberger.inter_reduction(self.gens()) + + ret = sorted(ret, reverse=True) + ret = PolynomialSequence(R, ret, immutable=True) + return ret + + @cached_method + @singular_gb_standard_options + def is_groebner(self, singular=singular): + r""" + Returns ``True`` if the generators of this ideal (``self.gens()``) + form a Grbner basis. + + Let `I` be the set of generators of this ideal. The check is + performed by trying to lift `Syz(LM(I))` to `Syz(I)` as `I` + forms a Groebner basis if and only if for every element `S` in + `Syz(LM(I))`: + + `S * G = \sum_{i=0}^{m} h_ig_i ---->_G 0.` + + EXAMPLE:: + + sage: R. = PolynomialRing(GF(127),10) + sage: I = sage.rings.ideal.Cyclic(R,4) + sage: I.basis.is_groebner() + False + sage: I2 = Ideal(I.groebner_basis()) + sage: I2.basis.is_groebner() + True + + """ + return self.ideal().basis_is_groebner() + class PolynomialSequence_gf2(PolynomialSequence_generic): """ Polynomial Sequences over `\mathbb{F}_2`. @@ -1308,8 +1463,34 @@ def solve(self, algorithm='polybori', n=1, eliminate_linear_variables=True, ver return solutions + def reduced(self): + """ + If this sequence is `(f_1, ..., f_n)` this method returns `(g_1, ..., g_s)` such that: + + - ` = ` + - `LT(g_i) != LT(g_j)` for all `i != j`` + - `LT(g_i)` does not divide `m` for all monomials `m` of + `{g_1,...,g_{i-1},g_{i+1},...,g_s}` + + EXAMPLE:: + + sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True) + sage: F,s = sr.polynomial_system() + sage: F.reduced() + [k100 + 1, k101 + k001 + 1, k102, k103 + 1, ..., s002, s003 + k001 + 1, k000 + 1, k002 + 1, k003 + 1] + + """ + from sage.rings.polynomial.pbori import BooleanPolynomialRing + R = self.ring() + if isinstance(R, BooleanPolynomialRing): + from polybori.interred import interred as inter_red + l = [p for p in self if not p==0] + l = sorted(inter_red(l, completely=True), reverse=True) + return PolynomialSequence(l, R, immutable=True) + else: + return PolynomialSequence_generic.reduced(self) class PolynomialSequence_gf2e(PolynomialSequence_generic): """ diff --git a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py index 4c708131686..294eb7d8c42 100644 --- a/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +++ b/src/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py @@ -104,7 +104,7 @@ def __init__(self, parent, x=None, check=True, is_gen=False, construct = False, x = [parentbr(a) for a in x.list()] check = False elif isinstance(x, dict): - zero = parentbr.zero_element() + zero = parentbr.zero() n = max(x.keys()) if x else 0 v = [zero for _ in xrange(n + 1)] for i, z in x.iteritems(): @@ -120,7 +120,7 @@ def __init__(self, parent, x=None, check=True, is_gen=False, construct = False, # In contrast to other polynomials, the zero element is not distinguished # by having its list empty. Instead, it has list [0] if not x: - x = [parentbr.zero_element()] + x = [parentbr.zero()] if check: x = [parentbr(z) for z in x] diff --git a/src/sage/rings/polynomial/pbori.pyx b/src/sage/rings/polynomial/pbori.pyx index d449ef43459..5de773ae0c5 100644 --- a/src/sage/rings/polynomial/pbori.pyx +++ b/src/sage/rings/polynomial/pbori.pyx @@ -189,6 +189,8 @@ include "sage/ext/python.pxi" import operator +from sage.misc.cachefunc import cached_method + from sage.misc.randstate import current_randstate import sage.misc.weak_dict from sage.rings.integer import Integer @@ -577,9 +579,9 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): Any boolean monomial is contained in the ring:: sage: e = B.random_element(); e - a*c + a*d + a + b*d + 1 + a*b + a*c + a + b*d + 1 sage: e.lt() - a*c + a*b sage: e.lt().parent() MonomialMonoid of Boolean PolynomialRing in a, b, c, d sage: e.lt() in B # indirect doctest @@ -702,10 +704,10 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): sage: P = BooleanPolynomialRing(3,'x,y,z') sage: F = GF(2) - sage: p = P(F.zero_element()) + sage: p = P(F.zero()) sage: p.is_zero() True - sage: p = P(F.one_element()) + sage: p = P(F.one()) sage: p.is_one() True @@ -1099,17 +1101,18 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): gens = flatten(gens) return BooleanPolynomialIdeal(self, gens, coerce) - def random_element(self, degree=None, terms=None, choose_degree=True, vars_set=None): + def random_element(self, degree=None, terms=None, choose_degree=False, vars_set=None): """ Return a random boolean polynomial. Generated polynomial has the given number of terms, and at most given degree. INPUT: - - ``degree`` - maximum degree (default: 2 for len(var_set) > 1, 1 otherwise) - - ``terms`` - number of terms (default: 5 for len(var_set) > 2, smaller otherwise) + - ``terms`` -- number of terms requested (default: 5). If more + terms are requested than exist, then this parameter is + silently reduced to the maximum number of available terms. - ``choose_degree`` - choose degree of monomials randomly first, rather than monomials uniformly random @@ -1122,7 +1125,7 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): sage: P. = BooleanPolynomialRing(3) sage: P.random_element(degree=3, terms=4) - x*y*z + x*z + y*z + z + x*y*z + x*z + x + y*z :: @@ -1133,11 +1136,17 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): sage: P = BooleanPolynomialRing(2,'y') sage: P.random_element() - y0*y1 + 1 + y0*y1 + y0 sage: P = BooleanPolynomialRing(1,'y') sage: P.random_element() - 1 + y + + We return uniformly random polynomials up to degree 2:: + + sage: B. = BooleanPolynomialRing() + sage: B.random_element(terms=Infinity) + a*b + a*c + a*d + b*c + b*d + d TESTS:: @@ -1147,19 +1156,11 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): ... ValueError: Given degree should be less than or equal to number of variables (3) - :: - - sage: t = P.random_element(degree=1, terms=5) - Traceback (most recent call last): - ... - ValueError: Cannot generate random polynomial with 5 terms and maximum degree 1 using 3 variables - - :: + sage: P.random_element(degree=1, terms=5) + y + 1 - sage: t = P.random_element(degree=2,terms=5,vars_set=(0,1)) - Traceback (most recent call last): - ... - ValueError: Cannot generate random polynomial with 5 terms using 2 variables + sage: P.random_element(degree=2, terms=5, vars_set=(0,1)) + x*y + y We test that :trac:`13845` is fixed:: @@ -1181,8 +1182,6 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): terms = 2 elif nvars == 1: terms = 1 - else: - terms = Integer(terms) if degree is None: if nvars > 1: @@ -1195,9 +1194,6 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): if degree > nvars: raise ValueError, "Given degree should be less than or equal to number of variables (%s)"%(nvars) - if Integer(terms-1).nbits() > nvars: - raise ValueError, "Cannot generate random polynomial with %s terms using %s variables"%(terms, nvars) - tot_terms=0 monom_counts = [] for i from 0 <= i <= degree: @@ -1205,7 +1201,9 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): monom_counts.append(tot_terms) if terms > tot_terms: - raise ValueError, "Cannot generate random polynomial with %s terms and maximum degree %s using %s variables"%(terms, degree, nvars) + terms = tot_terms//2 + (tot_terms%2) + else: + terms = Integer(terms) p = self._zero_element while len(p) < terms: @@ -1513,15 +1511,15 @@ cdef class BooleanPolynomialRing(MPolynomialRing_generic): z = zeros else: z = sum([prod([x[i] for i in xrange(n) if v[i]], - self.one_element()) for v in zeros], - self.zero_element()) + self.one()) for v in zeros], + self.zero()) z = z.set() if PY_TYPE_CHECK(ones, BooleSet): o = ones else: o = sum([prod([x[i] for i in xrange(n) if v[i]], - self.one_element()) for v in ones], - self.zero_element()) + self.one()) for v in ones], + self.zero()) o = o.set() return interpolate_smallest_lex(z, o) @@ -2783,7 +2781,7 @@ cdef class BooleanMonomial(MonoidElement): cdef inline BooleanMonomial new_BM(parent, BooleanPolynomialRing ring): cdef BooleanMonomial m - m = PY_NEW(BooleanMonomial) + m = BooleanMonomial.__new__(BooleanMonomial) m._parent = parent m._ring = ring return m @@ -2844,7 +2842,7 @@ cdef inline BooleanMonomialVariableIterator new_BMVI_from_BooleanMonomial(\ monomial. """ cdef BooleanMonomialVariableIterator m - m = PY_NEW(BooleanMonomialVariableIterator) + m = BooleanMonomialVariableIterator.__new__(BooleanMonomialVariableIterator) m.parent = monom._parent m._ring = monom._ring m.obj = monom @@ -2895,7 +2893,7 @@ cdef inline BooleanMonomialIterator new_BMI_from_BooleanMonomial(BooleanMonomial Construct a new BooleanMonomialIterator """ cdef BooleanMonomialIterator m - m = PY_NEW(BooleanMonomialIterator) + m = BooleanMonomialIterator.__new__(BooleanMonomialIterator) m._iter = monom._pbmonom.begin() m._end = monom._pbmonom.end() m.obj = monom @@ -3035,7 +3033,7 @@ cdef class BooleanPolynomial(MPolynomial): if left: return new_BP_from_PBPoly(self._parent, self._pbpoly) else: - return self._parent.zero_element() + return self._parent.zero() cpdef ModuleElement _lmul_(self, RingElement right): """ @@ -3574,7 +3572,7 @@ cdef class BooleanPolynomial(MPolynomial): :: - sage: P.one_element().is_one() + sage: P.one().is_one() True :: @@ -3599,7 +3597,7 @@ cdef class BooleanPolynomial(MPolynomial): EXAMPLE:: sage: P. = BooleanPolynomialRing(2) - sage: P.one_element().is_unit() + sage: P.one().is_unit() True :: @@ -3686,12 +3684,12 @@ cdef class BooleanPolynomial(MPolynomial): :: - sage: P.zero_element().vars_as_monomial() + sage: P.zero().vars_as_monomial() 1 :: - sage: P.one_element().vars_as_monomial() + sage: P.one().vars_as_monomial() 1 TESTS:: @@ -3726,16 +3724,16 @@ cdef class BooleanPolynomial(MPolynomial): :: - sage: P.zero_element().variables() + sage: P.zero().variables() () :: - sage: P.one_element().variables() + sage: P.one().variables() () """ P = self.parent() - o = P.one_element() + o = P.one() if self is o or self == o: return tuple() return tuple(self.vars_as_monomial()) @@ -3968,7 +3966,7 @@ cdef class BooleanPolynomial(MPolynomial): :: - sage: len(P.one_element()) + sage: len(P.one()) 1 :: @@ -3978,7 +3976,7 @@ cdef class BooleanPolynomial(MPolynomial): :: - sage: len(P.zero_element()) + sage: len(P.zero()) 0 """ return self._pbpoly.length() @@ -4612,8 +4610,8 @@ cdef class BooleanPolynomial(MPolynomial): B = self.parent() n = B.ngens() x = B.gens() - one = B.one_element() - zero = B.zero_element() + one = B.one() + zero = B.zero() s = sum([prod([x[i] for i in reversed(range(n)) if v[i]], one) for v in s], zero) s = s.set() @@ -4863,7 +4861,7 @@ cdef class BooleanPolynomialIterator: sage: B. = BooleanPolynomialRing() sage: list(B.random_element()) # indirect doctest - [a*c, a*d, a, b*d, 1] + [a*b, a*c, a, b*d, 1] """ return self @@ -4878,7 +4876,7 @@ cdef class BooleanPolynomialIterator: sage: B. = BooleanPolynomialRing() sage: it = iter(B.random_element()) sage: it.next() # indirect doctest - a*c + a*b """ cdef PBMonom value if self._iter.equal(self._end): @@ -4893,7 +4891,7 @@ cdef inline BooleanPolynomialIterator new_BPI_from_BooleanPolynomial(BooleanPoly Construct a new BooleanMonomialIterator """ cdef BooleanPolynomialIterator m - m = PY_NEW(BooleanPolynomialIterator) + m = BooleanPolynomialIterator.__new__(BooleanPolynomialIterator) m.obj = f m._iter = f._pbpoly.orderedBegin() m._end = f._pbpoly.orderedEnd() @@ -4901,19 +4899,16 @@ cdef inline BooleanPolynomialIterator new_BPI_from_BooleanPolynomial(BooleanPoly class BooleanPolynomialIdeal(MPolynomialIdeal): def __init__(self, ring, gens=[], coerce=True): - r""" + """ Construct an ideal in the boolean polynomial ring. INPUT: - - ``ring`` - the ring this ideal is defined in - ``gens`` - a list of generators - - ``coerce`` - coerce all elements to the ring ``ring`` - (default: ``True``) - + - ``coerce`` - coerce all elements to the ring ``ring`` (default: ``True``) EXAMPLES:: @@ -4945,12 +4940,15 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): return 0 - def groebner_basis(self, **kwds): - r""" + def groebner_basis(self, algorithm='polybori', **kwds): + """ Return a Groebner basis of this ideal. INPUT: + - ``algorithm`` - either ``"polybori"`` (built-in default) + or ``"magma"`` (requires Magma). + - ``red_tail`` - tail reductions in intermediate polynomials, this options affects mainly heuristics. The reducedness of the output polynomials can only be guaranteed by the option @@ -4973,7 +4971,7 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): to ``True`` linear algebra takes affect in this block. (default: ``True``) - - "gauss_on_linear" - perform Gaussian elimination on linear + - ``gauss_on_linear`` - perform Gaussian elimination on linear polynomials (default: ``True``) - ``selection_size`` - maximum number of polynomials for @@ -5016,6 +5014,22 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): sage: I.groebner_basis() Polynomial Sequence with 36 Polynomials in 36 Variables + We compute the same example with Magma:: + + sage: sr = mq.SR(2,1,1,4,gf2=True, polybori=True) + sage: F,s = sr.polynomial_system() + sage: I = F.ideal() + sage: I.groebner_basis(algorithm='magma', prot='sage') # optional - magma + Leading term degree: 1. Critical pairs: 148. + Leading term degree: 2. Critical pairs: 144. + Leading term degree: 3. Critical pairs: 462. + Leading term degree: 1. Critical pairs: 167. + Leading term degree: 2. Critical pairs: 147. + Leading term degree: 3. Critical pairs: 101 (all pairs of current degree eliminated by criteria). + + Highest degree reached during computation: 3. + Polynomial Sequence with 35 Polynomials in 36 Variables + TESTS: This example shows, that a bug in our variable indices was @@ -5057,13 +5071,17 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): except AttributeError: pass - if "redsb" not in kwds: - kwds["redsb"]=True - sig_on() - gb = self._groebner_basis(**kwds) - sig_off() - if gb: - if kwds.get("deg_bound", False) is False: + if algorithm == 'magma': + from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal_magma_repr + gb = MPolynomialIdeal_magma_repr._groebner_basis_magma(self, **kwds) + else: + if "redsb" not in kwds: + kwds["redsb"]=True + sig_on() + gb = self._groebner_basis(**kwds) + sig_off() + + if kwds.get("deg_bound", False) is False: g = GroebnerStrategy(gb[0].ring()) for p in gb: g.add_as_you_wish(p) @@ -5195,7 +5213,7 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): If this ideal is spanned by ``(f_1, ..., f_n)`` this method returns ``(g_1, ..., g_s)`` such that: - - ``(f_1,...,f_n) = (g_1,...,g_s)`` + - `` = `` - ``LT(g_i) != LT(g_j)`` for all ``i != j``` - ``LT(g_i)`` does not divide ``m`` for all monomials ``m`` of ``{g_1,...,g_{i-1},g_{i+1},...,g_s}`` @@ -5208,12 +5226,7 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): sage: I.interreduced_basis() [k100 + 1, k101 + k001 + 1, k102, k103 + 1, x100 + k001 + 1, x101 + k001, x102, x103 + k001, w100 + 1, w101 + k001 + 1, w102 + 1, w103 + 1, s000 + k001, s001 + k001 + 1, s002, s003 + k001 + 1, k000 + 1, k002 + 1, k003 + 1] """ - R = self.ring() - - from polybori.interred import interred as inter_red - l = [p for p in self.gens() if not p==0] - l = sorted(inter_red(l, completely=True), reverse=True) - return Sequence(l, R, check=False, immutable=True) + return self.basis.reduced() def __cmp__(self, other): """ @@ -5236,33 +5249,6 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): r = cmp(self.groebner_basis(),other.groebner_basis()) return r -# def __richcmp__(self, other, int op): -# """ -# EXAMPLE:: -# sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True) -# sage: F,s = sr.polynomial_system() -# sage: I = F.ideal() -# sage: J = Ideal(I.interreduced_basis()) -# sage: I == J -# True -# sage: J = Ideal(I.gens()[1:] + (I.gens()[0] + 1,)) -# sage: I == J -# False -# """ -# r = self.__cmp__(other) -# if op == 0: #< -# return r < 0 -# elif op == 2: #== -# return r == 0 -# elif op == 4: #> -# return r > 0 -# elif op == 1: #<= -# return r <= 0 -# elif op == 3: #!= -# return r != 0 -# elif op == 5: #>= -# return r >= 0 - ## # # Various internal constructors for boolean polynomials from various @@ -5272,7 +5258,7 @@ class BooleanPolynomialIdeal(MPolynomialIdeal): cdef inline BooleanPolynomial new_BP(BooleanPolynomialRing parent): cdef BooleanPolynomial p - p = PY_NEW(BooleanPolynomial) + p = BooleanPolynomial.__new__(BooleanPolynomial) p._parent = parent return p @@ -5942,7 +5928,7 @@ cdef inline BooleSet new_BS_from_PBSet(PBSet juice, BooleanPolynomialRing ring): Construct a new BooleSet """ cdef BooleSet s - s = PY_NEW(BooleSet) + s = BooleSet.__new__(BooleSet) s._pbset = juice s._ring = ring @@ -5973,10 +5959,10 @@ cdef class BooleSetIterator: sage: B. = BooleanPolynomialRing() sage: f = B.random_element() sage: f - a*c + a*d + a + b*d + 1 + a*b + a*c + a + b*d + 1 sage: it = iter(f.set()) sage: it.next() - a*c + a*b """ cdef PBMonom value if self._iter.equal(self._end): @@ -5990,7 +5976,7 @@ cdef inline BooleSetIterator new_BSI_from_PBSetIter(BooleSet s): Construct a new BooleSetIterator """ cdef BooleSetIterator m - m = PY_NEW(BooleSetIterator) + m = BooleSetIterator.__new__(BooleSetIterator) m._ring = s._ring m._parent = m._ring._monom_monoid m.obj = s @@ -6061,9 +6047,9 @@ cdef class BooleanPolynomialVector: sage: len(v) 3 sage: v[0] - a*b + a*d + a + d + e + a*b + a + b*e + c*d + e*f sage: list(v) - [a*b + a*d + a + d + e, a*e + a + c*f + d*f + 1, b*c + c*f + d*f + e + 1] + [a*b + a + b*e + c*d + e*f, a*d + c*d + d*f + e + f, a*c + a*e + b*c + c*f + f] """ def __init__(self, I=None): """ @@ -6082,9 +6068,9 @@ cdef class BooleanPolynomialVector: sage: len(v) 3 sage: v[0] - a*b + a*d + a + d + e + a*b + a + b*e + c*d + e*f sage: list(v) - [a*b + a*d + a + d + e, a*e + a + c*f + d*f + 1, b*c + c*f + d*f + e + 1] + [a*b + a + b*e + c*d + e*f, a*d + c*d + d*f + e + f, a*c + a*e + b*c + c*f + f] """ # This is used by PolyBoRi python code PBPolyVector_construct(&self._vec) @@ -6108,7 +6094,7 @@ cdef class BooleanPolynomialVector: sage: l = [B.random_element() for _ in range(3)] sage: v = BooleanPolynomialVector(l) sage: list(iter(v)) - [a*b + a*d + a + d + e, a*e + a + c*f + d*f + 1, b*c + c*f + d*f + e + 1] + [a*b + a + b*e + c*d + e*f, a*d + c*d + d*f + e + f, a*c + a*e + b*c + c*f + f] """ return new_BPVI_from_PBPolyVectorIter(self) @@ -6139,9 +6125,9 @@ cdef class BooleanPolynomialVector: sage: len(v) 3 sage: v[0] - a*b + a*d + a + d + e + a*b + a + b*e + c*d + e*f sage: v[-1] - b*c + c*f + d*f + e + 1 + a*c + a*e + b*c + c*f + f sage: v[3] Traceback (most recent call last): ... @@ -6199,11 +6185,7 @@ cdef class BooleanPolynomialVector: ... v.append(B.random_element()) sage: list(v) - [a*b + a*d + a + d + e, - a*e + a + c*f + d*f + 1, - b*c + c*f + d*f + e + 1, - a*e + a + c*f + d*f + 1, - b*e + d + e*f + f + 1] + [a*b + a + b*e + c*d + e*f, a*d + c*d + d*f + e + f, a*c + a*e + b*c + c*f + f, a*c + a*d + a*e + a*f + b*e, b*c + b*d + c*d + c + 1] """ if not self._parent: self._parent = el.ring() @@ -6219,7 +6201,7 @@ cdef class BooleanPolynomialVector: cdef inline BooleanPolynomialVector new_BPV_from_PBPolyVector(\ BooleanPolynomialRing parent, PBPolyVector juice): cdef BooleanPolynomialVector m - m = PY_NEW(BooleanPolynomialVector) + m = BooleanPolynomialVector.__new__(BooleanPolynomialVector) m._vec = juice m._parent = parent return m @@ -6247,7 +6229,7 @@ cdef inline BooleanPolynomialVectorIterator new_BPVI_from_PBPolyVectorIter(\ Construct a new BooleanPolynomialVectorIterator """ cdef BooleanPolynomialVectorIterator m - m = PY_NEW(BooleanPolynomialVectorIterator) + m = BooleanPolynomialVectorIterator.__new__(BooleanPolynomialVectorIterator) m._parent = vec._parent m.obj = vec m._iter = vec._vec.begin() @@ -7146,7 +7128,7 @@ cdef inline CCuddNavigator new_CN_from_PBNavigator(PBNavigator juice, Construct a new CCuddNavigator """ cdef CCuddNavigator n - n = PY_NEW(CCuddNavigator) + n = CCuddNavigator.__new__(CCuddNavigator) n._pbnav = juice n._pbind = pbind return n @@ -7183,9 +7165,9 @@ def add_up_polynomials(BooleanPolynomialVector v, BooleanPolynomial init): sage: l = [B.random_element() for _ in range(5)] sage: _ = [v.append(e) for e in l] sage: add_up_polynomials(v, B.zero()) - a*c + a*d + b*c + b*d + c*d + c + 1 + a*d + b*c + b*d + c + 1 sage: sum(l) - a*c + a*d + b*c + b*d + c*d + c + 1 + a*d + b*c + b*d + c + 1 """ return new_BP_from_PBPoly(v._parent, pb_add_up_polynomials(v._vec, init._pbpoly)) @@ -7696,7 +7678,7 @@ cdef BooleanPolynomialRing BooleanPolynomialRing_from_PBRing(PBRing _ring): Get BooleanPolynomialRing from C++-implementation """ cdef int i,j - cdef BooleanPolynomialRing self = PY_NEW(BooleanPolynomialRing) + cdef BooleanPolynomialRing self = BooleanPolynomialRing.__new__(BooleanPolynomialRing) cdef int n = _ring.nVariables() @@ -7747,29 +7729,30 @@ def gauss_on_polys(inp): sage: l = [B.random_element() for _ in range(B.ngens())] sage: A,v = Sequence(l,B).coefficient_matrix() sage: A - [1 0 1 0 1 0 0 0 0 1 0 1 0 0] - [0 0 0 1 1 0 0 1 1 0 0 0 0 1] - [0 0 0 0 0 1 0 1 1 0 0 1 0 1] - [0 0 0 1 1 0 0 1 1 0 0 0 0 1] - [0 0 0 0 0 0 1 0 0 1 1 0 1 1] - [0 1 1 0 0 0 0 0 0 0 0 1 1 1] + [1 0 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0] + [0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0] + [0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0] + [0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1] + [0 1 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1] sage: e = gauss_on_polys(l) sage: E,v = Sequence(e,B).coefficient_matrix() sage: E - [1 0 1 0 1 0 0 0 0 1 0 1 0 0] - [0 1 1 0 0 0 0 0 0 0 0 1 1 1] - [0 0 0 1 1 0 0 1 1 0 0 0 0 1] - [0 0 0 0 0 1 0 1 1 0 0 1 0 1] - [0 0 0 0 0 0 1 0 0 1 1 0 1 1] + [1 0 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0] + [0 1 0 0 0 0 0 0 1 1 1 0 1 1 0 1 0 1] + [0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0] + [0 0 0 1 0 0 0 1 1 0 0 1 1 1 0 1 1 0] + [0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 1 0 1] + [0 0 0 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1] sage: A.echelon_form() - [1 0 1 0 1 0 0 0 0 1 0 1 0 0] - [0 1 1 0 0 0 0 0 0 0 0 1 1 1] - [0 0 0 1 1 0 0 1 1 0 0 0 0 1] - [0 0 0 0 0 1 0 1 1 0 0 1 0 1] - [0 0 0 0 0 0 1 0 0 1 1 0 1 1] - [0 0 0 0 0 0 0 0 0 0 0 0 0 0] + [1 0 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0] + [0 1 0 0 0 0 0 0 1 1 1 0 1 1 0 1 0 1] + [0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0] + [0 0 0 1 0 0 0 1 1 0 0 1 1 1 0 1 1 0] + [0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 1 0 1] + [0 0 0 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1] """ cdef BooleanPolynomialVector _vec = BooleanPolynomialVector(inp) @@ -8252,5 +8235,3 @@ cdef class PolynomialFactory: self._factory.call_monom((arg)._pbmonom)) raise TypeError, "Cannot convert %s to BooleanPolynomial"%(type(arg)) - - diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 73e87689e92..c4f3871d0cf 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -345,7 +345,7 @@ cdef class NCPolynomialRing_plural(Ring): if check: - from sage.libs.singular import ff + from sage.libs.singular.function_factory import ff test = ff.nctools__lib.ndcond(ring = self) if (len(test) != 1) or (test[0] != 0): raise ValueError("NDC check failed!") @@ -974,7 +974,8 @@ cdef class NCPolynomialRing_plural(Ring): """ cdef poly *res cdef ring *r = self._ring - cdef number *n, *denom + cdef number *n + cdef number *denom if not self is f._parent: f = self._coerce_c(f) @@ -1230,15 +1231,16 @@ cdef class NCPolynomialRing_plural(Ring): sage: P.monomial_pairwise_prime(x^2*z^3, x1^4) # not tested True - sage: P.monomial_pairwise_prime((2)*x^3*y^2, Q.zero_element()) # not tested + sage: P.monomial_pairwise_prime((2)*x^3*y^2, Q.zero()) # not tested True - sage: P.monomial_pairwise_prime(2*P.one_element(),x) + sage: P.monomial_pairwise_prime(2*P.one(),x) False """ cdef int i cdef ring *r - cdef poly *p, *q + cdef poly *p + cdef poly *q if h._parent is not g._parent: g = (h._parent)._coerce_c(g) @@ -1318,7 +1320,8 @@ def unpickle_NCPolynomial_plural(NCPolynomialRing_plural R, d): """ cdef ring *r = R._ring - cdef poly *m, *p + cdef poly *m + cdef poly *p cdef int _i, _e p = p_ISet(0,r) rChangeCurrRing(r) @@ -1649,12 +1652,11 @@ cdef class NCPolynomial_plural(RingElement): .... OverflowError: Exponent overflow (...). """ - if not PY_TYPE_CHECK_EXACT(exp, Integer) or \ - PY_TYPE_CHECK_EXACT(exp, int): - try: - exp = Integer(exp) - except TypeError: - raise TypeError("non-integral exponents not supported") + if type(exp) is not Integer: + try: + exp = Integer(exp) + except TypeError: + raise TypeError("non-integral exponents not supported") if exp < 0: return 1/(self**(-exp)) @@ -1693,7 +1695,7 @@ cdef class NCPolynomial_plural(RingElement): sage: A. = FreeAlgebra(QQ, 3) sage: H. = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) - sage: I = H.ideal([y^2, x^2, z^2-H.one_element()],coerce=False) + sage: I = H.ideal([y^2, x^2, z^2-H.one()],coerce=False) The result of reduction is not the normal form, if one reduces by a list of polynomials:: @@ -2688,7 +2690,7 @@ cdef inline NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent, z """ - cdef NCPolynomial_plural p = PY_NEW(NCPolynomial_plural) + cdef NCPolynomial_plural p = NCPolynomial_plural.__new__(NCPolynomial_plural) p._parent = parent p._poly = juice p_Normalize(p._poly, parent._ring) @@ -2734,7 +2736,7 @@ cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring): """ assert( rw.is_commutative() ) - cdef MPolynomialRing_libsingular self = PY_NEW(MPolynomialRing_libsingular) + cdef MPolynomialRing_libsingular self = MPolynomialRing_libsingular.__new__(MPolynomialRing_libsingular) self._ring = rw._ring @@ -2806,7 +2808,7 @@ cpdef NCPolynomialRing_plural new_NRing(RingWrap rw, base_ring): assert( not rw.is_commutative() ) - cdef NCPolynomialRing_plural self = PY_NEW(NCPolynomialRing_plural) + cdef NCPolynomialRing_plural self = NCPolynomialRing_plural.__new__(NCPolynomialRing_plural) self._ring = rw._ring wrapped_ring = wrap_ring(self._ring) diff --git a/src/sage/rings/polynomial/polydict.pyx b/src/sage/rings/polynomial/polydict.pyx index cdb713e767a..3faaaf66408 100644 --- a/src/sage/rings/polynomial/polydict.pyx +++ b/src/sage/rings/polynomial/polydict.pyx @@ -912,8 +912,8 @@ cdef class ETuple: Quickly creates a new initialized ETuple with the same length as self. """ - cdef ETuple x - x = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef ETuple x = t.__new__(t) x._length = self._length return x @@ -990,7 +990,7 @@ cdef class ETuple: (1, 1, 0, 0, 2, 0) """ cdef size_t index = 0 - cdef ETuple result = PY_NEW(ETuple) + cdef ETuple result = ETuple.__new__(ETuple) result._length = self._length+other._length result._nonzero = self._nonzero+other._nonzero result._data = sage_malloc(sizeof(int)*result._nonzero*2) @@ -1013,7 +1013,7 @@ cdef class ETuple: (1, 2, 3, 1, 2, 3) """ cdef int _factor = factor - cdef ETuple result = PY_NEW(ETuple) + cdef ETuple result = ETuple.__new__(ETuple) if factor <= 0: result._length = 0 result._nonzero = 0 diff --git a/src/sage/rings/polynomial/polynomial_element.pxd b/src/sage/rings/polynomial/polynomial_element.pxd index 6c8bf46fd2f..303ec8de106 100644 --- a/src/sage/rings/polynomial/polynomial_element.pxd +++ b/src/sage/rings/polynomial/polynomial_element.pxd @@ -29,7 +29,6 @@ cdef class Polynomial_generic_dense(Polynomial): # cdef _dict_to_list(self, x, zero) cpdef is_Polynomial(f) -cpdef Polynomial_generic_dense _new_constant_dense_poly(list coeffs, Parent P, sample) #cdef class Polynomial_generic_sparse(Polynomial): # cdef object __coeffs # a python dict (for now) diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index a7f2aa8965c..8bddf7f68be 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -315,7 +315,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # that could be in derived class. # Note that we are guaranteed that right is in the base ring, so this could be fast. if left == 0: - return self.parent().zero_element() + return self.parent().zero() return self.parent()(left) * self cpdef ModuleElement _rmul_(self, RingElement right): @@ -335,7 +335,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # that could be in derived class. # Note that we are guaranteed that right is in the base ring, so this could be fast. if right == 0: - return self.parent().zero_element() + return self.parent().zero() return self * self.parent()(right) def subs(self, *x, **kwds): @@ -625,7 +625,7 @@ cdef class Polynomial(CommutativeAlgebraElement): if d == -1: try: - return a.parent().zero_element() + return a.parent().zero() except AttributeError: pass try: # for things like the interface to the PARI C library @@ -635,7 +635,7 @@ cdef class Polynomial(CommutativeAlgebraElement): if d == 0: try: - return a.parent().one_element() * result + return a.parent().one() * result except AttributeError: pass try: # for things like the interface to the PARI C library @@ -1041,7 +1041,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: ~f 1/(x - 90283) """ - return self.parent().one_element()/self + return self.parent().one()/self def inverse_of_unit(self): """ @@ -1163,7 +1163,7 @@ cdef class Polynomial(CommutativeAlgebraElement): for i in range(n+1): for j in range(n-1): M[i+j, j+n] = m[i] - v = vector(R, [R.one_element()] + [R.zero_element()]*(2*n-2)) # the constant polynomial 1 + v = vector(R, [R.one()] + [R.zero()]*(2*n-2)) # the constant polynomial 1 if M.is_invertible(): x = M.solve_right(v) # there has to be a better way to solve return a.parent()(list(x)[0:n]) @@ -1208,7 +1208,7 @@ cdef class Polynomial(CommutativeAlgebraElement): (t^4 + O(t^5))*s^4 + (2*t^3 + O(t^4))*s^3 + (3*t^2 + O(t^3))*s^2 + (2*t + O(t^2))*s + 1 """ if right == 0 or self == 0: - return self._parent.zero_element() + return self._parent.zero() if self._parent.is_exact(): return self._mul_karatsuba(right) @@ -1715,12 +1715,11 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: pow(f, 10**7, h) 4*x*t^3 + 2*x*t^2 + 4*x*t + 4 """ - if not PY_TYPE_CHECK_EXACT(right, Integer) or \ - PY_TYPE_CHECK_EXACT(right, int): - try: - right = Integer(right) - except TypeError: - raise TypeError("non-integral exponents not supported") + if type(right) is not Integer: + try: + right = Integer(right) + except TypeError: + raise TypeError("non-integral exponents not supported") if self.degree() <= 0: return self.parent()(self[0]**right) @@ -1733,9 +1732,9 @@ cdef class Polynomial(CommutativeAlgebraElement): P = self.parent() R = P.base_ring() if P.is_sparse(): - v = {right:R.one_element()} + v = {right:R.one()} else: - v = [R.zero_element()]*right + [R.one_element()] + v = [R.zero()]*right + [R.one()] return self.parent()(v, check=False) else: return generic_power(self,right) @@ -2108,7 +2107,7 @@ cdef class Polynomial(CommutativeAlgebraElement): x = self.list() cdef Py_ssize_t i, j cdef Py_ssize_t d = len(x)-1 - zero = self._parent.base_ring().zero_element() + zero = self._parent.base_ring().zero() two = self._parent.base_ring()(2) coeffs = [zero] * (2 * d + 1) for i from 0 <= i <= d: @@ -2622,7 +2621,7 @@ cdef class Polynomial(CommutativeAlgebraElement): """ if self.degree() == -1: - return self.base_ring().one_element() + return self.base_ring().one() #This code was in the original algorithm, but seems irrelevant #R = self.base_ring() x = self.list() @@ -2634,7 +2633,7 @@ cdef class Polynomial(CommutativeAlgebraElement): #start to fail, ex. "sage/rings/polynomial/complex_roots.py" return d except(AttributeError): - return self.base_ring().one_element() + return self.base_ring().one() def numerator(self): """ @@ -2819,7 +2818,7 @@ cdef class Polynomial(CommutativeAlgebraElement): return self cdef Py_ssize_t n, degree = self.degree() if degree == 0: - return self.parent().zero_element() + return self.parent().zero() coeffs = self.list() return self._parent([n*coeffs[n] for n from 1 <= n <= degree]) @@ -3493,14 +3492,14 @@ cdef class Polynomial(CommutativeAlgebraElement): else: # Otherwise we have to adjust for # the content ignored by PARI. - content_fix = R.base_ring().one_element() + content_fix = R.base_ring().one() for f, e in F: if not f.is_monic(): content_fix *= f.leading_coefficient()**e unit //= content_fix if not unit.is_unit(): F.append((R(unit), ZZ(1))) - unit = R.base_ring().one_element() + unit = R.base_ring().one() if not n is None: pari.set_real_precision(n) # restore precision @@ -4444,7 +4443,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f.coefficients(sparse=False) [1, 0, 2, 0, 1] """ - zero = self.parent().base_ring().zero_element() + zero = self.parent().base_ring().zero() if (sparse): return [c for c in self.list() if c != zero] else: @@ -4461,7 +4460,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f.exponents() [0, 2, 4] """ - zero = self.parent().base_ring().zero_element() + zero = self.parent().base_ring().zero() l = self.list() return [i for i in range(len(l)) if l[i] != zero] @@ -4557,7 +4556,7 @@ cdef class Polynomial(CommutativeAlgebraElement): if n < 0: raise ValueError("n must be at least 0") if len(v) < n: - z = self._parent.base_ring().zero_element() + z = self._parent.base_ring().zero() return v + [z]*(n - len(v)) else: return v[:int(n)] @@ -5137,7 +5136,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # Late import to avoid cyclic dependencies: from sage.rings.power_series_ring import is_PowerSeriesRing if self.is_zero(): - return self.parent().zero_element() + return self.parent().zero() n = self.degree() base_ring = self.parent().base_ring() if (is_MPolynomialRing(base_ring) or @@ -6355,7 +6354,7 @@ cdef class Polynomial(CommutativeAlgebraElement): if n == 0 or self.degree() < 0: return self # safe because immutable. if n > 0: - output = [self.base_ring().zero_element()] * n + output = [self.base_ring().zero()] * n output.extend(self.coefficients(sparse=False)) return self._parent(output, check=False) if n < 0: @@ -7138,12 +7137,6 @@ cdef do_karatsuba(left, right, Py_ssize_t K_threshold,Py_ssize_t start_l, Py_ssi return bd + ac -cpdef Polynomial_generic_dense _new_constant_dense_poly(list coeffs, Parent P, sample): - cdef Polynomial_generic_dense f = PY_NEW_SAME_TYPE(sample) - f._parent = P - f.__coeffs = coeffs - return f - cdef class Polynomial_generic_dense(Polynomial): """ A generic dense polynomial. @@ -7200,7 +7193,7 @@ cdef class Polynomial_generic_dense(Polynomial): return elif isinstance(x, dict): - x = self._dict_to_list(x, R.zero_element()) + x = self._dict_to_list(x, R.zero()) elif isinstance(x, pari_gen): x = [R(w, **kwds) for w in x.list()] @@ -7218,7 +7211,8 @@ cdef class Polynomial_generic_dense(Polynomial): self.__coeffs = x cdef Polynomial_generic_dense _new_c(self, list coeffs, Parent P): - cdef Polynomial_generic_dense f = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef Polynomial_generic_dense f = t.__new__(t) f._parent = P f.__coeffs = coeffs return f @@ -7308,13 +7302,13 @@ cdef class Polynomial_generic_dense(Polynomial): start = 0 zeros = [] elif start > 0: - zeros = [self._parent.base_ring().zero_element()] * start + zeros = [self._parent.base_ring().zero()] * start if stop is None: stop = len(self.__coeffs) return self._parent(zeros + self.__coeffs[start:stop]) else: if n < 0 or n >= len(self.__coeffs): - return self.base_ring().zero_element() + return self.base_ring().zero() return self.__coeffs[n] def _unsafe_mutate(self, n, value): @@ -7345,7 +7339,7 @@ cdef class Polynomial_generic_dense(Polynomial): elif n < 0: raise IndexError("polynomial coefficient index must be nonnegative") elif value != 0: - zero = self.base_ring().zero_element() + zero = self.base_ring().zero() for _ in xrange(len(self.__coeffs), n): self.__coeffs.append(zero) self.__coeffs.append(value) @@ -7508,7 +7502,7 @@ cdef class Polynomial_generic_dense(Polynomial): t """ if len(self.__coeffs) == 0: - return self.base_ring().zero_element() + return self.base_ring().zero() else: return self.__coeffs[0] @@ -7582,7 +7576,7 @@ cdef class Polynomial_generic_dense(Polynomial): if n == 0 or self.degree() < 0: return self if n > 0: - output = [self.base_ring().zero_element()] * n + output = [self.base_ring().zero()] * n output.extend(self.__coeffs) return self._new_c(output, self._parent) if n < 0: @@ -7638,7 +7632,7 @@ cdef class Polynomial_generic_dense(Polynomial): quo = list() for k from m-n >= k >= 0: q = x[n+k-1]/y[n-1] - x[n+k-1] = R.zero_element() + x[n+k-1] = R.zero() for j from n+k-2 >= j >= k: x[j] -= q * y[j-k] quo.insert(0,q) @@ -7745,7 +7739,7 @@ cdef class ConstantPolynomialSection(Map): To: Finite Field of size 3 sage: type(phi) - sage: phi(P0.one_element()) + sage: phi(P0.one()) 1 sage: phi(y_1) Traceback (most recent call last): diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 463cfc920a1..a37238d79a7 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -624,17 +624,17 @@ def quo_rem(self, other): d = other.degree() if self.degree() < d: - return R.zero_element(), self + return R.zero(), self - quo = R.zero_element() + quo = R.zero() rem = self - inv_lc = R.base_ring().one_element()/other.leading_coefficient() + inv_lc = R.base_ring().one()/other.leading_coefficient() while rem.degree() >= d: c = rem.leading_coefficient()*inv_lc e = rem.degree() - d - quo += c*R.one_element().shift(e) + quo += c*R.one().shift(e) # we know that the leading coefficient of rem vanishes # thus we avoid doing a useless computation rem = rem[:rem.degree()] - c*other[:d].shift(e) @@ -702,7 +702,7 @@ def quo_rem(self, other): A = self B = other R = A - Q = P.zero_element() + Q = P.zero() while R.degree() >= B.degree(): aaa = R.leading_coefficient()/B.leading_coefficient() diff_deg=R.degree()-B.degree() @@ -732,6 +732,13 @@ def gcd(self, other): sage: (2*x).gcd(2*x^2) x + sage: zero = R.zero() + sage: zero.gcd(2*x) + x + sage: (2*x).gcd(zero) + x + sage: zero.gcd(zero) + 0 """ from sage.categories.euclidean_domains import EuclideanDomains g = EuclideanDomains().ElementMethods().gcd(self, other) @@ -774,25 +781,43 @@ def xgcd(self, other): sage: g == u*P(0) + v*x True + TESTS: + + We check that the behavior of xgcd with zero elements is compatible with + gcd (:trac:`17671`):: + + sage: R. = QQbar[] + sage: zero = R.zero() + sage: zero.xgcd(2*x) + (x, 0, 1/2) + sage: (2*x).xgcd(zero) + (x, 1/2, 0) + sage: zero.xgcd(zero) + (0, 0, 0) """ + R = self.parent() + zero = R.zero() + one = R.one() if other.is_zero(): - R = self.parent() - return self, R.one_element(), R.zero_element() + if self.is_zero(): + return (zero, zero, zero) + else: + c = self.leading_coefficient() + return (self/c, one/c, zero) + elif self.is_zero(): + c = other.leading_coefficient() + return (other/c, zero, one/c) + # Algorithm 3.2.2 of Cohen, GTM 138 - R = self.parent() A = self B = other - U = R.one_element() + U = one G = A - V1 = R.zero_element() + V1 = zero V3 = B while not V3.is_zero(): Q, R = G.quo_rem(V3) - T = U - V1*Q - U = V1 - G = V3 - V1 = T - V3 = R + G, U, V1, V3 = V3, V1, U-V1*Q, R V = (G-A*U)//B lc = G.leading_coefficient() return G/lc, U/lc, V/lc diff --git a/src/sage/rings/polynomial/polynomial_gf2x.pyx b/src/sage/rings/polynomial/polynomial_gf2x.pyx index 0aa6a9dd490..3ba7b1cf932 100644 --- a/src/sage/rings/polynomial/polynomial_gf2x.pyx +++ b/src/sage/rings/polynomial/polynomial_gf2x.pyx @@ -77,6 +77,7 @@ cdef class Polynomial_GF2X(Polynomial_template): sage: f[1:] x^3 + x^2 """ + cdef type t cdef long c = 0 cdef Polynomial_template r if isinstance(i, slice): @@ -88,7 +89,8 @@ cdef class Polynomial_GF2X(Polynomial_template): x = (self)._parent.gen() v = [self[t] for t from start <= t < stop] - r = PY_NEW(self.__class__) + t = self.__class__ + r = t.__new__(t) Polynomial_template.__init__(r, (self)._parent, v) return r << start else: @@ -157,7 +159,7 @@ cdef class Polynomial_GF2X(Polynomial_template): cdef GF2XModulus_c modulus GF2XModulus_build(modulus, (h).x) - res = PY_NEW(Polynomial_GF2X) + res = Polynomial_GF2X.__new__(Polynomial_GF2X) res._parent = self._parent res._cparent = self._cparent diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx index 4aaa88dc0de..560d02aa9f3 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx @@ -74,7 +74,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): Quickly creates a new initialized Polynomial_integer_dense_flint with the correct parent and _is_gen == 0. """ - cdef Polynomial_integer_dense_flint x = PY_NEW(Polynomial_integer_dense_flint) + cdef Polynomial_integer_dense_flint x = Polynomial_integer_dense_flint.__new__(Polynomial_integer_dense_flint) x._parent = self._parent x._is_gen = 0 return x @@ -95,7 +95,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): 2 """ - cdef Polynomial_integer_dense_flint x = PY_NEW(Polynomial_integer_dense_flint) + cdef Polynomial_integer_dense_flint x = Polynomial_integer_dense_flint.__new__(Polynomial_integer_dense_flint) x._parent = P x._is_gen = 0 if not PY_TYPE_CHECK(a, Integer): @@ -195,7 +195,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): # find max degree to allocate only once for ii, a in x: # mpoly dict style has tuple keys - i = ii[0] if PY_TYPE_CHECK_EXACT(ii, tuple) else ii + i = ii[0] if type(ii) is tuple else ii if i < 0: raise ValueError, "Negative monomial degrees not allowed: %s" % i elif i > degree: @@ -208,8 +208,8 @@ cdef class Polynomial_integer_dense_flint(Polynomial): raise OverflowError, "Cannot allocate memory!" # now fill them in for ii, a in x: - i = ii[0] if PY_TYPE_CHECK_EXACT(ii, tuple) else ii - if PY_TYPE_CHECK_EXACT(a, int): + i = ii[0] if type(ii) is tuple else ii + if type(a) is int: sig_on() fmpz_poly_set_coeff_si(self.__poly, i, a) sig_off() @@ -247,7 +247,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): sig_off() for i from 0 <= i < len(x): a = x[i] - if PY_TYPE_CHECK_EXACT(a, int): + if type(a) is int: sig_on() fmpz_poly_set_coeff_si(self.__poly, i, a) sig_off() @@ -707,38 +707,72 @@ cdef class Polynomial_integer_dense_flint(Polynomial): @coerce_binop def xgcd(self, right): """ - This function can't in general return ``(g,s,t)`` as above, - since they need not exist. Instead, over the integers, we - first multiply `g` by a divisor of the resultant of `a/g` and - `b/g`, up to sign, and return ``g, u, v`` such that - ``g = s*self + s*right``. But note that this `g` may be a - multiple of the gcd. + Return a triple ``(g,s,t)`` such that `g = s*self + t*right` and such + that `g` is the `gcd` of ``self`` and ``right`` up to a divisor of the + resultant of ``self`` and ``other``. + + As integer polynomials do not form a principal ideal domain, it is not + always possible given `a` and `b` to find a pair `s,t` such that + `gcd(a,b) = sa + tb`. Take `a=x+2` and `b=x+4` as an example for which the + gcd is `1` but the best you can achieve in the Bezout identity is `2`. If ``self`` and ``right`` are coprime as polynomials over the rationals, then ``g`` is guaranteed to be the resultant of - self and right, as a constant polynomial. + ``self`` and ``right``, as a constant polynomial. EXAMPLES:: sage: P. = PolynomialRing(ZZ) + + sage: (x+2).xgcd(x+4) + (2, -1, 1) + sage: (x+2).resultant(x+4) + 2 + sage: (x+2).gcd(x+4) + 1 + sage: F = (x^2 + 2)*x^3; G = (x^2+2)*(x-3) sage: g, u, v = F.xgcd(G) sage: g, u, v (27*x^2 + 54, 1, -x^2 - 3*x - 9) sage: u*F + v*G 27*x^2 + 54 - sage: x.xgcd(P(0)) + + sage: zero = P(0) + sage: x.xgcd(zero) (x, 1, 0) - sage: f = P(0) - sage: f.xgcd(x) + sage: zero.xgcd(x) (x, 0, 1) + sage: F = (x-3)^3; G = (x-15)^2 sage: g, u, v = F.xgcd(G) sage: g, u, v (2985984, -432*x + 8208, 432*x^2 + 864*x + 14256) sage: u*F + v*G 2985984 + + TESTS: + + Check that :trac:`17675` is fixed:: + + sage: R. = ZZ['x'] + sage: R(2).xgcd(R(2)) + (2, 0, 1) + sage: R.zero().xgcd(R(2)) + (2, 0, 1) + sage: R(2).xgcd(R.zero()) + (2, 1, 0) """ + # trivial cases first + if self.is_zero(): + return (right, Integer(0), Integer(1)) + elif right.is_zero(): + return (self, Integer(1), Integer(0)) + elif self.is_constant() and right.is_constant(): + # this case is needed as the behavior of the function fmpz_poly_xgcd + # in FLINT is not defined with constant input + return self.constant_coefficient().xgcd(right.constant_coefficient()) + cdef Polynomial_integer_dense_flint ss = self._new() cdef Polynomial_integer_dense_flint tt = self._new() cdef fmpz_t r @@ -1055,6 +1089,13 @@ cdef class Polynomial_integer_dense_flint(Polynomial): -339 sage: f.discriminant(proof=False) -339 + + TESTS: + + Confirm that :trac:`17603` has been applied:: + + sage: f.disc() + -339 """ cdef ZZX_c ntl_poly cdef ZZ_c* temp @@ -1068,6 +1109,8 @@ cdef class Polynomial_integer_dense_flint(Polynomial): return x + # Alias for discriminant + disc = discriminant def _pari_(self, variable=None): """ diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx index 1427f9dbb3c..5e7c609ffb4 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx @@ -83,7 +83,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): Quickly creates a new initialized Polynomial_integer_dense_ntl with the correct parent and _is_gen == 0. """ - cdef Polynomial_integer_dense_ntl x = PY_NEW(Polynomial_integer_dense_ntl) + cdef Polynomial_integer_dense_ntl x = Polynomial_integer_dense_ntl.__new__(Polynomial_integer_dense_ntl) x._parent = self._parent x._is_gen = 0 return x @@ -185,7 +185,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): degree = 0 # find max degree to allocate only once for ii, a in x: - i = ii[0] if PY_TYPE_CHECK_EXACT(ii, tuple) else ii # mpoly dict style has tuple keys + i = ii[0] if type(ii) is tuple else ii # mpoly dict style has tuple keys if i < 0: raise ValueError, "Negative monomial degrees not allowed: %s" % i elif i > degree: @@ -195,8 +195,8 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): ZZX_SetCoeff_long(self.__poly, degree, 1) # now fill them in for ii, a in x: - i = ii[0] if PY_TYPE_CHECK_EXACT(ii, tuple) else ii - if PY_TYPE_CHECK_EXACT(a, int): + i = ii[0] if type(ii) is tuple else ii + if type(a) is int: ZZX_SetCoeff_long(self.__poly, i, a) else: if not PY_TYPE_CHECK(a, Integer): @@ -229,7 +229,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): for i from 0 <= i < len(x): a = x[i] - if PY_TYPE_CHECK_EXACT(a, int): + if type(a) is int: ZZX_SetCoeff_long(self.__poly, i, a) else: if not PY_TYPE_CHECK(a, Integer): @@ -500,7 +500,8 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): if ZZX_IsZero(self.__poly): return self, self - cdef ZZX_c *q, *r + cdef ZZX_c *q + cdef ZZX_c *r cdef Polynomial_integer_dense_ntl qq = self._new() cdef Polynomial_integer_dense_ntl rr = self._new() cdef int divisible @@ -604,7 +605,8 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): sage: u*F + v*G 2985984 """ - cdef ZZX_c *s, *t + cdef ZZX_c *s + cdef ZZX_c *t cdef ZZ_c *r ZZX_xgcd(&self.__poly, &(right).__poly, &r, &s, &t, 1) # proof = 1 diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 50a93e95172..421656236fe 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -43,11 +43,12 @@ import polynomial_singular_interface from sage.interfaces.all import singular as singular_default from sage.structure.element import generic_power, canonical_coercion, bin_op, coerce_binop +from sage.structure.element cimport have_same_parent_c -from sage.libs.ntl.ntl_ZZ_p_decl cimport *, ZZ_p_c -from sage.libs.ntl.ntl_lzz_p_decl cimport *, zz_p_c -from sage.libs.ntl.ntl_lzz_pX_decl cimport *, zz_pX_c, zz_pX_Modulus_c -from sage.libs.ntl.ntl_ZZ_pX_decl cimport *, ZZ_pX_c, ZZ_pX_Modulus_c +from sage.libs.ntl.ntl_ZZ_p_decl cimport * +from sage.libs.ntl.ntl_lzz_p_decl cimport * +from sage.libs.ntl.ntl_lzz_pX_decl cimport * +from sage.libs.ntl.ntl_ZZ_pX_decl cimport * def make_element(parent, args): return parent(*args) @@ -624,7 +625,7 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n): self.c = ntl.c cdef Polynomial_dense_modn_ntl_zz _new(self): - cdef Polynomial_dense_modn_ntl_zz y = PY_NEW(Polynomial_dense_modn_ntl_zz) + cdef Polynomial_dense_modn_ntl_zz y = Polynomial_dense_modn_ntl_zz.__new__(Polynomial_dense_modn_ntl_zz) y.c = self.c y._parent = self._parent return y @@ -920,7 +921,7 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n): sage: f - q*g x + 1 """ - if PY_TYPE(self) != PY_TYPE(right) or (self)._parent is not (right)._parent: + if not have_same_parent_c(self, right): self, right = canonical_coercion(self, right) return self // right cdef Polynomial_dense_modn_ntl_zz numer = self @@ -943,7 +944,7 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n): sage: g * x^4 + r x^7 + x + 1 """ - if PY_TYPE(self) != PY_TYPE(right) or (self)._parent is not (right)._parent: + if not have_same_parent_c(self, right): self, right = canonical_coercion(self, right) return self % right cdef Polynomial_dense_modn_ntl_zz numer = self @@ -1202,7 +1203,7 @@ cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n): cdef Polynomial_dense_modn_ntl_ZZ _new(self): - cdef Polynomial_dense_modn_ntl_ZZ y = PY_NEW(Polynomial_dense_modn_ntl_ZZ) + cdef Polynomial_dense_modn_ntl_ZZ y = Polynomial_dense_modn_ntl_ZZ.__new__(Polynomial_dense_modn_ntl_ZZ) y.c = self.c y._parent = self._parent return y @@ -1481,7 +1482,7 @@ cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n): sage: f - q*g x + 1 """ - if PY_TYPE(self) != PY_TYPE(right) or (self)._parent is not (right)._parent: + if not have_same_parent_c(self, right): self, right = canonical_coercion(self, right) return self // right cdef Polynomial_dense_modn_ntl_ZZ numer = self @@ -1504,7 +1505,7 @@ cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n): sage: g * (x^4 + x) + r x^7 + x + 1 """ - if PY_TYPE(self) != PY_TYPE(right) or (self)._parent is not (right)._parent: + if not have_same_parent_c(self, right): self, right = canonical_coercion(self, right) return self % right cdef Polynomial_dense_modn_ntl_ZZ numer = self diff --git a/src/sage/rings/polynomial/polynomial_number_field.pyx b/src/sage/rings/polynomial/polynomial_number_field.pyx index 5fa8bb4fc81..a25c7f55ea8 100644 --- a/src/sage/rings/polynomial/polynomial_number_field.pyx +++ b/src/sage/rings/polynomial/polynomial_number_field.pyx @@ -190,7 +190,7 @@ class Polynomial_absolute_number_field_dense(Polynomial_generic_dense_field): elif other.is_zero(): return self.monic() elif self.degree() == 0 or other.degree() == 0: - return self.parent().one_element() + return self.parent().one() # If the extension is of degree one, use the gcd from QQ[x] if self.base_ring().degree().is_one(): @@ -318,7 +318,7 @@ class Polynomial_relative_number_field_dense(Polynomial_generic_dense_field): elif other.is_zero(): return self.monic() elif self.degree() == 0 or other.degree() == 0: - return self.parent().one_element() + return self.parent().one() L = self.parent() x = L.variable_name() diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 3560dd95ce1..1507485f1f0 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -225,7 +225,7 @@ class PolynomialQuotientRing_generic(sage.rings.commutative_ring.CommutativeRing TESTS: - By trac ticket #11900, polynomial quotient rings use Sage's + By trac ticket :trac:`11900`, polynomial quotient rings use Sage's category framework. They do so in an unusual way: During their initialisation, they are declared to be objects in the category of quotients of commutative algebras over a base ring. However, if it @@ -276,10 +276,11 @@ class of the category, and store the current class of the quotient new methods from the category of fields, thanks to :meth:`Element.__getattr__`:: - sage: isinstance(Q.an_element(),Q.element_class) + sage: e = Q.an_element() + sage: isinstance(e, Q.element_class) False - sage: Q.an_element().gcd.__module__ - 'sage.categories.fields' + sage: e.gcd(e+1) + 1 Since the category has changed, we repeat the test suite. However, we have to skip the test for its elements, since `an_element` has been cached in the previous run of the test suite, diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index 139f4439708..f52221e0b03 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -27,7 +27,7 @@ from sage.libs.flint.fmpz_poly cimport * from sage.interfaces.all import singular as singular_default -from sage.libs.all import pari, pari_gen +from sage.libs.pari.gen import gen as pari_gen from sage.rings.integer cimport Integer from sage.rings.integer_ring import ZZ @@ -41,7 +41,8 @@ from sage.rings.polynomial.polynomial_integer_dense_flint cimport Polynomial_int from sage.structure.parent cimport Parent from sage.structure.element cimport Element, ModuleElement, RingElement from sage.structure.element import coerce_binop -from sage.structure.factorization import Factorization + +from cpython.number cimport PyNumber_AsSsize_t cdef inline bint _do_sig(fmpq_poly_t op): """ @@ -95,7 +96,7 @@ cdef class Polynomial_rational_flint(Polynomial): sage: f + g # indirect doctest 2/3*t^2 - 1/2*t + 2 """ - cdef Polynomial_rational_flint res = PY_NEW(Polynomial_rational_flint) + cdef Polynomial_rational_flint res = Polynomial_rational_flint.__new__(Polynomial_rational_flint) res._parent = self._parent res._is_gen = 0 return res @@ -123,7 +124,7 @@ cdef class Polynomial_rational_flint(Polynomial): ValueError: invalid literal for int() with base 10: '2.1' """ - cdef Polynomial_rational_flint res = PY_NEW(Polynomial_rational_flint) + cdef Polynomial_rational_flint res = Polynomial_rational_flint.__new__(Polynomial_rational_flint) res._parent = P res._is_gen = 0 if PY_TYPE_CHECK(x, int): @@ -218,7 +219,7 @@ cdef class Polynomial_rational_flint(Polynomial): if len(x) == 0: return elif len(x) == 1: - Polynomial_rational_flint.__init__(self, parent, x[0], \ + Polynomial_rational_flint.__init__(self, parent, x[0], check=check, is_gen=False, construct=construct) return @@ -249,7 +250,7 @@ cdef class Polynomial_rational_flint(Polynomial): elif PY_TYPE_CHECK(x, pari_gen): k = self._parent.base_ring() x = [k(w) for w in x.list()] - Polynomial_rational_flint.__init__(self, parent, x, check=True, \ + Polynomial_rational_flint.__init__(self, parent, x, check=True, is_gen=False, construct=construct) elif PY_TYPE_CHECK(x, Polynomial_integer_dense_flint): @@ -258,17 +259,17 @@ cdef class Polynomial_rational_flint(Polynomial): elif PY_TYPE_CHECK(x, Polynomial): k = self._parent.base_ring() x = [k(w) for w in list(x)] - Polynomial_rational_flint.__init__(self, parent, x, check=True, \ + Polynomial_rational_flint.__init__(self, parent, x, check=True, is_gen=False, construct=construct) elif PY_TYPE_CHECK(x, FractionFieldElement) and (x.parent().base() is parent or x.parent().base() == parent) and x.denominator() == 1: x = x.numerator() - Polynomial_rational_flint.__init__(self, parent, x, check=check, \ + Polynomial_rational_flint.__init__(self, parent, x, check=check, is_gen=is_gen, construct=construct) else: x = parent.base_ring()(x) - Polynomial_rational_flint.__init__(self, parent, x, check=check, \ + Polynomial_rational_flint.__init__(self, parent, x, check=check, is_gen=is_gen, construct=construct) def __reduce__(self): @@ -286,8 +287,8 @@ cdef class Polynomial_rational_flint(Polynomial): sage: loads(dumps(f)) == f True """ - return Polynomial_rational_flint, \ - (self.parent(), self.list(), False, self.is_gen()) + return (Polynomial_rational_flint, + (self.parent(), self.list(), False, self.is_gen())) def __copy__(self): """ @@ -384,12 +385,12 @@ cdef class Polynomial_rational_flint(Polynomial): sage: f[1:3] # indirect doctest 1/2*t^2 + t """ - cdef Rational z = PY_NEW(Rational) + cdef Rational z = Rational.__new__(Rational) cdef Polynomial_rational_flint res = self._new() cdef bint do_sig = _do_sig(self.__poly) if isinstance(n, slice): start, stop, step = n.indices(self.degree() + 1) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_get_slice(res.__poly, self.__poly, start, stop) if do_sig: sig_off() return res @@ -419,20 +420,20 @@ cdef class Polynomial_rational_flint(Polynomial): cdef bint do_sig = _do_sig(self.__poly) if PY_TYPE_CHECK(value, int): - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_set_coeff_si(self.__poly, n, value) if do_sig: sig_off() elif PY_TYPE_CHECK(value, Integer): - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_set_coeff_mpz(self.__poly, n, ( value).value) if do_sig: sig_off() elif PY_TYPE_CHECK(value, Rational): - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_set_coeff_mpq(self.__poly, n, ( value).value) if do_sig: sig_off() else: value = Rational(value) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_set_coeff_mpq(self.__poly, n, ( value).value) if do_sig: sig_off() @@ -469,20 +470,20 @@ cdef class Polynomial_rational_flint(Polynomial): a = x[0] if isinstance(a, Polynomial_rational_flint): f = ( a)._new() - sig_on() - fmpq_poly_compose(f.__poly, self.__poly, \ + sig_str("FLINT exception") + fmpq_poly_compose(f.__poly, self.__poly, ( a).__poly) sig_off() return f if isinstance(a, Rational): - r = PY_NEW(Rational) - sig_on() + r = Rational.__new__(Rational) + sig_str("FLINT exception") fmpq_poly_evaluate_mpq(r.value, self.__poly, ( a).value) sig_off() return r if isinstance(a, Integer): - r = PY_NEW(Rational) - sig_on() + r = Rational.__new__(Rational) + sig_str("FLINT exception") fmpq_poly_evaluate_mpz(r.value, self.__poly, ( a).value) sig_off() return r @@ -515,7 +516,7 @@ cdef class Polynomial_rational_flint(Polynomial): res = self._new() if n > 0: do_sig = _do_sig(self.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_get_slice(res.__poly, self.__poly, 0, n) if do_sig: sig_off() return res @@ -608,7 +609,7 @@ cdef class Polynomial_rational_flint(Polynomial): res = self._new() do_sig = _do_sig(self.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_reverse(res.__poly, self.__poly, len) if do_sig: sig_off() return res @@ -643,7 +644,7 @@ cdef class Polynomial_rational_flint(Polynomial): if not self[0].is_zero() or not self[1].is_unit(): raise ValueError("self must have constant coefficient 0 and a unit for coefficient {}^1".format(self.parent().gen())) - sig_on() + sig_str("FLINT exception") fmpq_poly_revert_series(res.__poly, self.__poly, m) sig_off() @@ -715,7 +716,7 @@ cdef class Polynomial_rational_flint(Polynomial): res = f._new() do_sig = fmpq_poly_length(f.__poly) > 5000 or n > 5000 - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_shift_left(res.__poly, f.__poly, k) if do_sig: sig_off() return res @@ -743,7 +744,7 @@ cdef class Polynomial_rational_flint(Polynomial): res = f._new() do_sig = _do_sig(f.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_shift_right(res.__poly, f.__poly, k) if do_sig: sig_off() return res @@ -775,7 +776,7 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint res = self._new() cdef bint do_sig = _do_sig(self.__poly) or _do_sig(op2.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_add(res.__poly, self.__poly, op2.__poly) if do_sig: sig_off() return res @@ -805,7 +806,7 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint res = self._new() cdef bint do_sig = _do_sig(self.__poly) or _do_sig(op2.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_sub(res.__poly, self.__poly, op2.__poly) if do_sig: sig_off() return res @@ -831,7 +832,7 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint res = self._new() cdef bint do_sig = _do_sig(self.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_neg(res.__poly, self.__poly) if do_sig: sig_off() return res @@ -861,8 +862,8 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint qq = self._new() cdef Polynomial_rational_flint rr = self._new() - sig_on() - fmpq_poly_divrem(qq.__poly, rr.__poly, self.__poly, \ + sig_str("FLINT exception") + fmpq_poly_divrem(qq.__poly, rr.__poly, self.__poly, ( right).__poly) sig_off() return qq, rr @@ -890,8 +891,8 @@ cdef class Polynomial_rational_flint(Polynomial): """ cdef Polynomial_rational_flint res = self._new() - sig_on() - fmpq_poly_gcd(res.__poly, self.__poly, \ + sig_str("FLINT exception") + fmpq_poly_gcd(res.__poly, self.__poly, ( right).__poly) sig_off() return res @@ -917,8 +918,8 @@ cdef class Polynomial_rational_flint(Polynomial): """ cdef Polynomial_rational_flint res = self._new() - sig_on() - fmpq_poly_lcm(res.__poly, self.__poly, \ + sig_str("FLINT exception") + fmpq_poly_lcm(res.__poly, self.__poly, ( right).__poly) sig_off() return res @@ -959,7 +960,7 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint s = self._new() cdef Polynomial_rational_flint t = self._new() - sig_on() + sig_str("FLINT exception") fmpq_poly_xgcd(d.__poly, s.__poly, t.__poly, self.__poly, (right).__poly) sig_off() return d, s, t @@ -988,7 +989,7 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint res = self._new() cdef bint do_sig = _do_sig(self.__poly) or _do_sig(op2.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_mul(res.__poly, self.__poly, op2.__poly) if do_sig: sig_off() return res @@ -1007,8 +1008,8 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint res = self._new() cdef bint do_sig = _do_sig(self.__poly) - if do_sig: sig_on() - fmpq_poly_scalar_mul_mpq(res.__poly, self.__poly, \ + if do_sig: sig_str("FLINT exception") + fmpq_poly_scalar_mul_mpq(res.__poly, self.__poly, ( left).value) if do_sig: sig_off() return res @@ -1027,8 +1028,8 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint res = self._new() cdef bint do_sig = _do_sig(self.__poly) - if do_sig: sig_on() - fmpq_poly_scalar_mul_mpq(res.__poly, self.__poly, \ + if do_sig: sig_str("FLINT exception") + fmpq_poly_scalar_mul_mpq(res.__poly, self.__poly, ( right).value) if do_sig: sig_off() return res @@ -1059,51 +1060,64 @@ cdef class Polynomial_rational_flint(Polynomial): 1 sage: f^3 -1/27*t^6 + 2/3*t^5 - 23/6*t^4 + 6*t^3 + 23/4*t^2 + 3/2*t + 1/8 + sage: f^(-3) + 1/(-1/27*t^6 + 2/3*t^5 - 23/6*t^4 + 6*t^3 + 23/4*t^2 + 3/2*t + 1/8) TESTS:: sage: R. = QQ[] - sage: f = 1/2 + t - sage: f^0 + sage: t^0 1 sage: R(0)^0 1 + sage: R(0)^(-1) + Traceback (most recent call last): + ... + ZeroDivisionError: negative exponent in power of zero - We verify the size condition on the exponent:: + We verify the checking of the exponent:: sage: R. = QQ[] + sage: (1 + t)^(2/3) + Traceback (most recent call last): + ... + TypeError: non-integral exponents not supported sage: (1 + t)^(2^63) Traceback (most recent call last): ... - OverflowError: Python int too large to convert to C long + OverflowError: cannot fit 'sage.rings.integer.Integer' into an index-sized integer + + FLINT memory errors do not crash Sage (:trac:`17629`):: + + sage: t^(sys.maxsize//2) + Traceback (most recent call last): + ... + RuntimeError: FLINT exception """ - cdef long n + cdef Py_ssize_t n cdef Polynomial_rational_flint res - if not PY_TYPE_CHECK(exp, Integer): - try: - exp = Integer(exp) - except TypeError: - raise TypeError, "non-integral exponents not supported" - - n = exp + try: + n = PyNumber_AsSsize_t(exp, OverflowError) + except TypeError: + raise TypeError("non-integral exponents not supported") if n < 0: if fmpq_poly_is_zero(self.__poly): - raise ZeroDivisionError, "negative exponent in power of zero" + raise ZeroDivisionError("negative exponent in power of zero") res = self._new() - sig_on() + sig_str("FLINT exception") fmpq_poly_pow(res.__poly, self.__poly, -n) sig_off() return ~res else: res = self._new() + sig_str("FLINT exception") if self._is_gen: fmpq_poly_set_coeff_si(res.__poly, n, 1) else: - sig_on() fmpq_poly_pow(res.__poly, self.__poly, n) - sig_off() + sig_off() return res def __floordiv__(Polynomial_rational_flint self, right): @@ -1140,7 +1154,7 @@ cdef class Polynomial_rational_flint(Polynomial): res = self._new() do_sig = _do_sig(self.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_scalar_div_mpq(res.__poly, self.__poly, ( QQ(right)).value) if do_sig: sig_off() @@ -1149,7 +1163,7 @@ cdef class Polynomial_rational_flint(Polynomial): right = self._parent(right) res = self._new() - sig_on() + sig_str("FLINT exception") fmpq_poly_div(res.__poly, self.__poly, (right).__poly) sig_off() @@ -1187,7 +1201,7 @@ cdef class Polynomial_rational_flint(Polynomial): right = self._parent(right) res = self._new() - sig_on() + sig_str("FLINT exception") fmpq_poly_rem(res.__poly, self.__poly, (right).__poly) sig_off() @@ -1212,12 +1226,12 @@ cdef class Polynomial_rational_flint(Polynomial): sage: f.numerator() -3*t^3 - 1 """ - cdef Polynomial_integer_dense_flint num = \ - PY_NEW(Polynomial_integer_dense_flint) + cdef Polynomial_integer_dense_flint num + num = Polynomial_integer_dense_flint.__new__(Polynomial_integer_dense_flint) parent = ZZ[self.variable_name()] - sig_on() - Polynomial_integer_dense_flint.__init__(num, parent, x=None, \ + Polynomial_integer_dense_flint.__init__(num, parent, x=None, check=False, is_gen=False, construct=False) + sig_str("FLINT exception") fmpq_poly_get_numerator(num.__poly, self.__poly) sig_off() return num @@ -1283,7 +1297,7 @@ cdef class Polynomial_rational_flint(Polynomial): der = self._new() do_sig = _do_sig(self.__poly) - if do_sig: sig_on() + if do_sig: sig_str("FLINT exception") fmpq_poly_derivative(der.__poly, self.__poly) if do_sig: sig_off() return der @@ -1334,11 +1348,11 @@ cdef class Polynomial_rational_flint(Polynomial): sage: f.resultant(h) 0 """ - cdef Rational res = PY_NEW(Rational) + cdef Rational res = Rational.__new__(Rational) cdef fmpq_t t fmpq_init(t) - sig_on() - fmpq_poly_resultant(t, self.__poly, \ + sig_str("FLINT exception") + fmpq_poly_resultant(t, self.__poly, (right).__poly) fmpq_get_mpq(res.value, t) sig_off() @@ -1387,15 +1401,14 @@ cdef class Polynomial_rational_flint(Polynomial): elif length == 2: return True else: - primitive = PY_NEW(Polynomial_integer_dense_flint) + primitive = Polynomial_integer_dense_flint.__new__(Polynomial_integer_dense_flint) parent = ZZ[self.variable_name()] - sig_on() - Polynomial_integer_dense_flint.__init__(primitive, parent, \ + Polynomial_integer_dense_flint.__init__(primitive, parent, x=None, check=True, is_gen=False, construct=False) + sig_str("FLINT exception") fmpq_poly_get_numerator(primitive.__poly, self.__poly) fmpz_poly_primitive_part(primitive.__poly, primitive.__poly) - sig_off() return primitive.is_irreducible() @@ -1500,10 +1513,10 @@ cdef class Polynomial_rational_flint(Polynomial): algorithm = 'kash' if self.degree() > 23 and algorithm == 'kash': - raise NotImplementedError, "Galois group computation is " + \ - "supported for degrees up to 11 using Pari, or up to 23 " + \ - "if the optional package KASH is installed. Try " + \ - "algorithm='magma' if you have magma." + raise NotImplementedError("Galois group computation is " + "supported for degrees up to 11 using PARI, or up to 23 " + "if the optional package KASH is installed. Try " + "algorithm='magma' if you have magma.") if algorithm == 'pari': G = self._pari_().Polrev().polgalois() diff --git a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx index b5c3629806f..45d3261d610 100644 --- a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +++ b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx @@ -113,15 +113,15 @@ cdef class PolynomialRealDense(Polynomial): mpfr_init2(coeffs[i], prec) self._degree += 1 a = x[i] - if PY_TYPE_CHECK_EXACT(a, RealNumber): + if type(a) is RealNumber: mpfr_set(coeffs[i], (a).value, rnd) - elif PY_TYPE_CHECK_EXACT(a, int): + elif type(a) is int: mpfr_set_si(coeffs[i], PyInt_AS_LONG(a), rnd) - elif PY_TYPE_CHECK_EXACT(a, float): + elif type(a) is float: mpfr_set_d(coeffs[i], PyFloat_AS_DOUBLE(a), rnd) - elif PY_TYPE_CHECK_EXACT(a, Integer): + elif type(a) is Integer: mpfr_set_z(coeffs[i], (a).value, rnd) - elif PY_TYPE_CHECK_EXACT(a, Rational): + elif type(a) is Rational: mpfr_set_q(coeffs[i], (a).value, rnd) else: a = self._base_ring(a) @@ -213,7 +213,7 @@ cdef class PolynomialRealDense(Polynomial): cdef PolynomialRealDense _new(self, Py_ssize_t degree): cdef Py_ssize_t i cdef int prec = self._base_ring.__prec - cdef PolynomialRealDense f = PY_NEW(PolynomialRealDense) + cdef PolynomialRealDense f = PolynomialRealDense.__new__(PolynomialRealDense) f._parent = self._parent f._base_ring = self._base_ring f._degree = degree diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index b12899972eb..038b8f6f04e 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -785,7 +785,7 @@ def _is_valid_homomorphism_(self, codomain, im_gens): # of the polynomial ring canonically coerce into codomain. # Since poly rings are free, any image of the gen # determines a homomorphism - codomain.coerce(self.base_ring().one_element()) + codomain.coerce(self.base_ring().one()) except TypeError: return False return True @@ -1229,7 +1229,7 @@ def _monics_degree( self, of_degree ): Refer to monics() for full documentation. """ base = self.base_ring() - for coeffs in sage.misc.mrange.xmrange_iter([[base.one_element()]]+[base]*of_degree): + for coeffs in sage.misc.mrange.xmrange_iter([[base.one()]]+[base]*of_degree): # Each iteration returns a *new* list! # safe to mutate the return coeffs.reverse() @@ -1248,7 +1248,7 @@ def _polys_degree( self, of_degree ): Refer to polynomials() for full documentation. """ base = self.base_ring() - base0 = base.zero_element() + base0 = base.zero() for leading_coeff in base: if leading_coeff != base0: for lt1 in sage.misc.mrange.xmrange_iter([base]*(of_degree)): diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 31af15a9afd..96440671b3c 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -41,7 +41,7 @@ import sage.rings.fraction_field import sage.rings.number_field as number_field -from sage.interfaces.all import singular as singular_default +from sage.interfaces.all import singular from sage.rings.complex_field import is_ComplexField from sage.rings.real_mpfr import is_RealField from sage.rings.complex_double import is_ComplexDoubleField @@ -64,7 +64,7 @@ class PolynomialRing_singular_repr: polynomial rings which support conversion from and to Singular rings. """ - def _singular_(self, singular=singular_default): + def _singular_(self, singular=singular): r""" Returns a singular ring for this polynomial ring. Currently `\QQ`, `{\rm GF}(p), {\rm GF}(p^n)`, `\CC`, `\RR`, `\ZZ` and @@ -214,7 +214,7 @@ def _singular_(self, singular=singular_default): except (AttributeError, ValueError): return self._singular_init_(singular) - def _singular_init_(self, singular=singular_default): + def _singular_init_(self, singular=singular): """ Return a newly created Singular ring matching this ring. @@ -380,13 +380,13 @@ class Polynomial_singular_repr: Due to the incompatibility of Python extension classes and multiple inheritance, this just defers to module-level functions. """ - def _singular_(self, singular=singular_default, have_ring=False): + def _singular_(self, singular=singular, have_ring=False): return _singular_func(self, singular, have_ring) - def _singular_init_func(self, singular=singular_default, have_ring=False): + def _singular_init_func(self, singular=singular, have_ring=False): return _singular_init_func(self, singular, have_ring) -def _singular_func(self, singular=singular_default, have_ring=False): +def _singular_func(self, singular=singular, have_ring=False): """ Return Singular polynomial matching this polynomial. @@ -433,7 +433,7 @@ def _singular_func(self, singular=singular_default, have_ring=False): # return self._singular_init_(singular,have_ring=have_ring) return _singular_init_func(self, singular,have_ring=have_ring) -def _singular_init_func(self, singular=singular_default, have_ring=False): +def _singular_init_func(self, singular=singular, have_ring=False): """ Return corresponding Singular polynomial but enforce that a new instance is created in the Singular interpreter. diff --git a/src/sage/rings/polynomial/polynomial_template.pxi b/src/sage/rings/polynomial/polynomial_template.pxi index d147c474b41..9f45ced80e7 100644 --- a/src/sage/rings/polynomial/polynomial_template.pxi +++ b/src/sage/rings/polynomial/polynomial_template.pxi @@ -40,7 +40,8 @@ cdef inline Polynomial_template element_shift(self, int n): cdef celement *gen = celement_new((self)._cparent) celement_gen(gen, 0, (self)._cparent) celement_pow(gen, gen, abs(n), NULL, (self)._cparent) - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -227,7 +228,8 @@ cdef class Polynomial_template(Polynomial): sage: x + 1 x + 1 """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent @@ -244,7 +246,8 @@ cdef class Polynomial_template(Polynomial): sage: x - 1 x + 1 """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -260,7 +263,8 @@ cdef class Polynomial_template(Polynomial): sage: -x x """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -290,7 +294,8 @@ cdef class Polynomial_template(Polynomial): sage: (-2^81)*u 3*y^2 + 3*y + 3 """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -326,7 +331,8 @@ cdef class Polynomial_template(Polynomial): sage: x*(x+1) x^2 + x """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -353,7 +359,8 @@ cdef class Polynomial_template(Polynomial): if(celement_is_zero(&other.x, (self)._cparent)): return self - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -380,17 +387,18 @@ cdef class Polynomial_template(Polynomial): if(celement_is_zero(&other.x, (self)._cparent)): return self, self._parent(1), self._parent(0) - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent - cdef Polynomial_template s = PY_NEW(self.__class__) + cdef Polynomial_template s = T.__new__(T) celement_construct(&s.x, (self)._cparent) s._parent = (self)._parent s._cparent = (self)._cparent - cdef Polynomial_template t = PY_NEW(self.__class__) + cdef Polynomial_template t = T.__new__(T) celement_construct(&t.x, (self)._cparent) t._parent = (self)._parent t._cparent = (self)._cparent @@ -421,7 +429,8 @@ cdef class Polynomial_template(Polynomial): if celement_is_zero(&_right.x, (self)._cparent): raise ZeroDivisionError - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -457,7 +466,8 @@ cdef class Polynomial_template(Polynomial): if celement_is_zero(&_other.x, (self)._cparent): raise ZeroDivisionError - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -478,12 +488,13 @@ cdef class Polynomial_template(Polynomial): if celement_is_zero(&right.x, (self)._cparent): raise ZeroDivisionError - cdef Polynomial_template q = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template q = T.__new__(T) celement_construct(&q.x, (self)._cparent) q._parent = (self)._parent q._cparent = (self)._cparent - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -614,7 +625,8 @@ cdef class Polynomial_template(Polynomial): if not self: if e == 0: raise ArithmeticError("0^0 is undefined.") - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) parent = (self)._parent @@ -644,7 +656,8 @@ cdef class Polynomial_template(Polynomial): sage: copy(x) == x True """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -753,7 +766,8 @@ cdef class Polynomial_template(Polynomial): sage: f.truncate(6) x^5 + x^4 + x^3 + x^2 + x + 1 """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type T = self.__class__ + cdef Polynomial_template r = T.__new__(T) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index 00aff0ce94f..100381bfe0c 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -109,7 +109,8 @@ cdef class Polynomial_zmod_flint(Polynomial_template): sage: (2*x+1).monic() #indirect doctest x + 3 """ - cdef Polynomial_template e = PY_NEW(self.__class__) + cdef type t = self.__class__ + cdef Polynomial_template e = t.__new__(t) nmod_poly_init(&e.x, self._parent.modulus()) e._parent = self._parent e._cparent = self._cparent @@ -139,7 +140,8 @@ cdef class Polynomial_zmod_flint(Polynomial_template): ValueError: invalid literal for int() with base 10: '4.1' """ - cdef Polynomial_template r = PY_NEW(self.__class__) + cdef type t = self.__class__ + cdef Polynomial_template r = t.__new__(t) r._parent = P r._cparent = get_cparent(P) nmod_poly_init(&r.x, nmod_poly_modulus(&self.x)) @@ -235,6 +237,7 @@ cdef class Polynomial_zmod_flint(Polynomial_template): sage: f[-5:50] == f True """ + cdef type t cdef unsigned long c = 0 cdef Polynomial_template r if isinstance(i, slice): @@ -246,7 +249,8 @@ cdef class Polynomial_zmod_flint(Polynomial_template): x = (self)._parent.gen() v = [self[t] for t from start <= t < stop] - r = PY_NEW(self.__class__) + t = self.__class__ + r = t.__new__(t) Polynomial_template.__init__(r, (self)._parent, v) return r << start else: @@ -438,7 +442,8 @@ cdef class Polynomial_zmod_flint(Polynomial_template): """ cdef Polynomial_zmod_flint _other = self._parent._coerce_(other) - cdef Polynomial_zmod_flint r = PY_NEW(self.__class__) + cdef type t = self.__class__ + cdef Polynomial_zmod_flint r = t.__new__(t) r._parent = (self)._parent r._cparent = (self)._cparent @@ -546,7 +551,7 @@ cdef class Polynomial_zmod_flint(Polynomial_template): P = self._parent cdef Polynomial_zmod_flint s0 = self._new() - cdef Polynomial_zmod_flint t0 = P.one_element() + cdef Polynomial_zmod_flint t0 = P.one() cdef Polynomial_zmod_flint s1 = m cdef Polynomial_zmod_flint t1 = self%m diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 4dc0ed6c97a..32a2b3802ea 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -165,6 +165,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: f[-5:50] == f True """ + cdef type t cdef ZZ_pE_c c_pE cdef Polynomial_template r if isinstance(i, slice): @@ -176,7 +177,8 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): x = (self)._parent.gen() v = [self[t] for t from start <= t < stop] - r = PY_NEW(self.__class__) + t = self.__class__ + r = t.__new__(t) Polynomial_template.__init__(r, (self)._parent, v) return r << start else: @@ -218,7 +220,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): """ cdef ntl_ZZ_pE d cdef Polynomial_ZZ_pEX r - r = PY_NEW(Polynomial_ZZ_pEX) + r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent @@ -438,7 +440,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): """ self._parent._modulus.restore() cdef Polynomial_ZZ_pEX r - r = PY_NEW(Polynomial_ZZ_pEX) + r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) celement_construct(&r.x, (self)._cparent) r._parent = (self)._parent r._cparent = (self)._cparent diff --git a/src/sage/rings/polynomial/toy_buchberger.py b/src/sage/rings/polynomial/toy_buchberger.py index 70e03c9038d..8ee60b44e4f 100644 --- a/src/sage/rings/polynomial/toy_buchberger.py +++ b/src/sage/rings/polynomial/toy_buchberger.py @@ -414,14 +414,16 @@ def inter_reduction(Q): :: - sage: (x,y) = QQ['x,y'].gens() + sage: P. = QQ[] sage: reduced = inter_reduction(set([x^2-5*y^2,x^3])) sage: reduced == set([x*y^2, x^2-5*y^2]) True + sage: reduced == inter_reduction(set([2*(x^2-5*y^2),x^3])) + True """ if not Q: return Q # if Q is empty we cannot get a base ring - base_ring = iter(Q).next().base_ring() + base_ring = next(iter(Q)).base_ring() Q = set(Q) while True: diff --git a/src/sage/rings/power_series_poly.pyx b/src/sage/rings/power_series_poly.pyx index 818e2eae299..04e407e83dd 100644 --- a/src/sage/rings/power_series_poly.pyx +++ b/src/sage/rings/power_series_poly.pyx @@ -15,6 +15,7 @@ import arith from sage.libs.all import PariError from power_series_ring_element import is_PowerSeries import rational_field +from sage.misc.superseded import deprecated_function_alias cdef class PowerSeries_poly(PowerSeries): @@ -906,14 +907,14 @@ cdef class PowerSeries_poly(PowerSeries): return PowerSeries_poly(self._parent, self.__f.integral(var), self.prec()+1, check=False) - def reversion(self, precision=None): + def reverse(self, precision=None): """ - Return the reversion of f, i.e., the series g such that g(f(x)) = - x. Given an optional argument ``precision``, return the reversion - with given precision (note that the reversion can have precision at - most ``f.prec()``). If ``f`` has infinite precision, and the argument - ``precision`` is not given, then the precision of the reversion - defaults to the default precision of ``f.parent()``. + Return the reverse of f, i.e., the series g such that g(f(x)) = x. + Given an optional argument ``precision``, return the reverse with given + precision (note that the reverse can have precision at most + ``f.prec()``). If ``f`` has infinite precision, and the argument + ``precision`` is not given, then the precision of the reverse defaults + to the default precision of ``f.parent()``. Note that this is only possible if the valuation of self is exactly 1. @@ -925,14 +926,14 @@ cdef class PowerSeries_poly(PowerSeries): a message if passing to pari fails. If the base ring has positive characteristic, then we attempt to - lift to a characteristic zero ring and perform the reversion there. + lift to a characteristic zero ring and perform the reverse there. If this fails, an error is raised. EXAMPLES:: sage: R. = PowerSeriesRing(QQ) sage: f = 2*x + 3*x^2 - x^4 + O(x^5) - sage: g = f.reversion() + sage: g = f.reverse() sage: g 1/2*x - 3/8*x^2 + 9/16*x^3 - 131/128*x^4 + O(x^5) sage: f(g) @@ -942,7 +943,7 @@ cdef class PowerSeries_poly(PowerSeries): sage: A. = PowerSeriesRing(ZZ) sage: a = t - t^2 - 2*t^4 + t^5 + O(t^6) - sage: b = a.reversion(); b + sage: b = a.reverse(); b t + t^2 + 2*t^3 + 7*t^4 + 25*t^5 + O(t^6) sage: a(b) t + O(t^6) @@ -952,7 +953,7 @@ cdef class PowerSeries_poly(PowerSeries): sage: B. = PolynomialRing(ZZ) sage: A. = PowerSeriesRing(B) sage: f = t + b*t^2 + c*t^3 + O(t^4) - sage: g = f.reversion(); g + sage: g = f.reverse(); g t - b*t^2 + (2*b^2 - c)*t^3 + O(t^4) sage: f(g) t + O(t^4) @@ -963,7 +964,7 @@ cdef class PowerSeries_poly(PowerSeries): sage: B. = A[[]] sage: f = (1 - 3*t + 4*t^3 + O(t^4))*s + (2 + t + t^2 + O(t^3))*s^2 + O(s^3) sage: set_verbose(1) - sage: g = f.reversion(); g + sage: g = f.reverse(); g verbose 1 () passing to pari failed; trying Lagrange inversion (1 + 3*t + 9*t^2 + 23*t^3 + O(t^4))*s + (-2 - 19*t - 118*t^2 + O(t^3))*s^2 + O(s^3) sage: set_verbose(0) @@ -975,13 +976,13 @@ cdef class PowerSeries_poly(PowerSeries): sage: A. = PowerSeriesRing(ZZ) sage: a = 2*t - 4*t^2 + t^4 - t^5 + O(t^6) - sage: a.reversion() + sage: a.reverse() 1/2*t + 1/2*t^2 + t^3 + 79/32*t^4 + 437/64*t^5 + O(t^6) sage: B. = PolynomialRing(ZZ) sage: A. = PowerSeriesRing(B) sage: f = 2*b*t + b*t^2 + 3*b^2*t^3 + O(t^4) - sage: g = f.reversion(); g + sage: g = f.reverse(); g 1/(2*b)*t - 1/(8*b^2)*t^2 + ((-3*b + 1)/(16*b^3))*t^3 + O(t^4) sage: f(g) t + O(t^4) @@ -992,7 +993,7 @@ cdef class PowerSeries_poly(PowerSeries): sage: A8. = PowerSeriesRing(Zmod(8)) sage: a = t - 15*t^2 - 2*t^4 + t^5 + O(t^6) - sage: b = a.reversion(); b + sage: b = a.reverse(); b t + 7*t^2 + 2*t^3 + 5*t^4 + t^5 + O(t^6) sage: a(b) t + O(t^6) @@ -1003,7 +1004,7 @@ cdef class PowerSeries_poly(PowerSeries): sage: R. = PowerSeriesRing(QQ) sage: f = 2*x + 3*x^2 - 7*x^3 + x^4 + O(x^5) - sage: g = f.reversion(precision=3); g + sage: g = f.reverse(precision=3); g 1/2*x - 3/8*x^2 + O(x^3) sage: f(g) x + O(x^3) @@ -1015,9 +1016,9 @@ cdef class PowerSeries_poly(PowerSeries): ring:: sage: R. = PowerSeriesRing(QQ, default_prec=20) - sage: (x - x^2).reversion() # get some Catalan numbers + sage: (x - x^2).reverse() # get some Catalan numbers x + x^2 + 2*x^3 + 5*x^4 + 14*x^5 + 42*x^6 + 132*x^7 + 429*x^8 + 1430*x^9 + 4862*x^10 + 16796*x^11 + 58786*x^12 + 208012*x^13 + 742900*x^14 + 2674440*x^15 + 9694845*x^16 + 35357670*x^17 + 129644790*x^18 + 477638700*x^19 + O(x^20) - sage: (x - x^2).reversion(precision=3) + sage: (x - x^2).reverse(precision=3) x + x^2 + O(x^3) @@ -1025,7 +1026,7 @@ cdef class PowerSeries_poly(PowerSeries): sage: R. = PowerSeriesRing(QQ) sage: f = 1 + 2*x + 3*x^2 - x^4 + O(x^5) - sage: f.reversion() + sage: f.reverse() Traceback (most recent call last): ... ValueError: Series must have valuation one for reversion. @@ -1076,7 +1077,7 @@ cdef class PowerSeries_poly(PowerSeries): verbose("characteristic zero base is "+str(base_lift)) f_lift = f.change_ring(base_lift) verbose("f_lift is "+str(f_lift)) - rev_lift = f_lift.reversion() + rev_lift = f_lift.reverse() return rev_lift.change_ring(f.base_ring()) t = f.parent().gen() @@ -1091,6 +1092,8 @@ cdef class PowerSeries_poly(PowerSeries): g = g.add_bigoh(out_prec) return PowerSeries_poly(out_parent, g, out_prec, check=False) + reversion = deprecated_function_alias(17724, reverse) + def pade(self, m, n): r""" Returns the Padé approximant of ``self`` of index `(m, n)`. diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 02a01498d4a..5fadaa4a6bd 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -415,7 +415,7 @@ cdef class PowerSeries(AlgebraElement): sage: f.coefficients() [1, 1, -10/3] """ - zero = self.parent().base_ring().zero_element() + zero = self.parent().base_ring().zero() return [c for c in self.list() if c != zero] def exponents(self): @@ -429,7 +429,7 @@ cdef class PowerSeries(AlgebraElement): sage: f.exponents() [1, 2, 3] """ - zero = self.parent().base_ring().zero_element() + zero = self.parent().base_ring().zero() l = self.list() return [i for i in range(len(l)) if l[i] != zero] @@ -1068,6 +1068,22 @@ cdef class PowerSeries(AlgebraElement): return self._parent(current, prec=prec) + def inverse(self): + """ + Return the inverse of self, i.e., self^(-1). + + EXAMPLES:: + + sage: R. = PowerSeriesRing(QQ, sparse=True) + sage: t.inverse() + t^-1 + sage: type(_) + + sage: (1-t).inverse() + 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + t^7 + t^8 + ... + """ + return self.__invert__() + def valuation_zero_part(self): r""" Factor self as as `q^n \cdot (a_0 + a_1 q + \cdots)` with diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 21bd1f40391..6b2cf3cda39 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -1537,7 +1537,7 @@ def prec_seq(): EXAMPLE:: sage: g = sage.rings.qqbar.prec_seq() - sage: [g.next(), g.next(), g.next()] + sage: [next(g), next(g), next(g)] [64, 128, 256] """ # XXX Should do some testing to see where the efficiency breaks are @@ -1571,7 +1571,7 @@ def tail_prec_seq(): sage: from sage.rings.qqbar import tail_prec_seq sage: g = tail_prec_seq() - sage: [g.next(), g.next(), g.next()] + sage: [next(g), next(g), next(g)] [256, 512, 1024] """ bits = 256 diff --git a/src/sage/rings/quotient_ring.py b/src/sage/rings/quotient_ring.py index 915ed18d8d4..9c487ff3b30 100644 --- a/src/sage/rings/quotient_ring.py +++ b/src/sage/rings/quotient_ring.py @@ -994,7 +994,7 @@ def _element_constructor_(self, x, coerce=True): def _coerce_map_from_(self, R): """ - Returns ``True`` if there is a coercion map from ``R`` to ``self``. + Return ``True`` if there is a coercion map from ``R`` to ``self``. EXAMPLES:: @@ -1009,8 +1009,53 @@ def _coerce_map_from_(self, R): False sage: T.has_coerce_map_from(R) True + + TESTS: + + We check that :trac:`13682` is fixed:: + + sage: R. = PolynomialRing(QQ) + sage: I = R.ideal(x^2+y^2) + sage: J = R.ideal(x^2+y^2, x^3 - y) + sage: I < J + True + sage: S = R.quotient(I) + sage: T = R.quotient(J) + sage: T.has_coerce_map_from(S) + True + sage: S.quotient_ring(x^4-x*y+1).has_coerce_map_from(S) + True + sage: S.has_coerce_map_from(T) + False + + We also allow coercions with the cover rings:: + + sage: Rp. = PolynomialRing(ZZ) + sage: Ip = Rp.ideal(x^2+y^2) + sage: Jp = Rp.ideal(x^2+y^2, x^3 - y) + sage: Sp = Rp.quotient(Ip) + sage: Tp = Rp.quotient(Jp) + sage: R.has_coerce_map_from(Rp) + True + sage: Sp.has_coerce_map_from(Sp) + True + sage: T.has_coerce_map_from(Sp) + True + sage: Sp.has_coerce_map_from(T) + False """ - return self.cover_ring().has_coerce_map_from(R) + C = self.cover_ring() + if isinstance(R, QuotientRing_nc): + if C == R.cover_ring(): + if R.defining_ideal() <= self.defining_ideal(): + return True + elif C.has_coerce_map_from(R.cover_ring()): + try: + if R.defining_ideal().change_ring(C) <= self.defining_ideal(): + return True + except AttributeError: # Not all ideals have a change_ring + pass + return C.has_coerce_map_from(R) def __cmp__(self, other): r""" diff --git a/src/sage/rings/quotient_ring_element.py b/src/sage/rings/quotient_ring_element.py index 774e0119bb9..be8028ca500 100644 --- a/src/sage/rings/quotient_ring_element.py +++ b/src/sage/rings/quotient_ring_element.py @@ -271,7 +271,7 @@ def _add_(self, right): sage: a._add_(b) a + b """ - return self.parent()(self.__rep + right.__rep) + return self.__class__(self.parent(), self.__rep + right.__rep) def _sub_(self, right): """ @@ -291,7 +291,7 @@ def _sub_(self, right): sage: a._sub_(b) a - b """ - return self.parent()(self.__rep - right.__rep) + return self.__class__(self.parent(), self.__rep - right.__rep) def _mul_(self, right): """ @@ -313,7 +313,7 @@ def _mul_(self, right): sage: a._mul_(a) -b^2 """ - return self.parent()(self.__rep * right.__rep) + return self.__class__(self.parent(), self.__rep * right.__rep) def _div_(self, right): """ @@ -540,7 +540,7 @@ def __neg__(self): sage: -(a+b) -a - b """ - return self.parent()(-self.__rep) + return self.__class__(self.parent(), -self.__rep) def __pos__(self): """ @@ -579,8 +579,8 @@ def __invert__(self): try: inv = self.__rep.inverse_mod(self.parent().defining_ideal()) except NotImplementedError: - return self.parent()(1)/self - return self.parent()(inv) + return self.parent().one()/self + return self.__class__(self.parent(), inv) def __float__(self): """ @@ -671,7 +671,7 @@ def lt(self): sage: (a+3*a*b+b).lt() 3*a*b """ - return self.parent()(self.__rep.lt()) + return self.__class__(self.parent(), self.__rep.lt()) def lm(self): """ @@ -694,7 +694,7 @@ def lm(self): a*b """ - return self.parent()(self.__rep.lm()) + return self.__class__(self.parent(), self.__rep.lm()) def lc(self): """ @@ -742,7 +742,7 @@ def variables(self): sage: (a+b).variables() (a, b) """ - return tuple([self.parent()(v) for v in self.__rep.variables()]) + return tuple(self.__class__(self.parent(), v) for v in self.__rep.variables()) def monomials(self): """ @@ -763,7 +763,7 @@ def monomials(self): sage: R.zero().monomials() [] """ - return [self.parent()(m) for m in self.__rep.monomials()] + return [self.__class__(self.parent(), m) for m in self.__rep.monomials()] def _singular_(self, singular=singular_default): """ @@ -822,7 +822,7 @@ def _magma_init_(self, magma): """ g = magma(self.__rep) R = magma(self.parent()) - return '%s!%s'%(R.name(), g._ref()) + return '{}!{}'.format(R.name(), g._ref()) def reduce(self, G): r""" @@ -851,4 +851,5 @@ def reduce(self, G): pass # reduction w.r.t. the defining ideal is performed in the # constructor - return self.parent()(self.__rep.reduce(G)) + return self.__class__(self.parent(), self.__rep.reduce(G)) + diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 8093339bc14..df36710bdd0 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -24,6 +24,8 @@ AUTHORS: - Travis Scrimshaw (2012-10-18): Added doctests for full coverage. +- Vincent Delecroix (2013): continued fraction + TESTS:: sage: a = -2/3 @@ -112,7 +114,7 @@ cdef inline void set_from_Integer(Rational self, integer.Integer other): cdef object Rational_mul_(Rational a, Rational b): cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) sig_on() mpq_mul(x.value, a.value, b.value) @@ -122,7 +124,7 @@ cdef object Rational_mul_(Rational a, Rational b): cdef object Rational_div_(Rational a, Rational b): cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) sig_on() mpq_div(x.value, a.value, b.value) @@ -132,7 +134,7 @@ cdef object Rational_div_(Rational a, Rational b): cdef Rational_add_(Rational self, Rational other): cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) sig_on() mpq_add(x.value, self.value, other.value) sig_off() @@ -140,7 +142,7 @@ cdef Rational_add_(Rational self, Rational other): cdef Rational_sub_(Rational self, Rational other): cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) sig_on() mpq_sub(x.value, self.value, other.value) @@ -575,6 +577,125 @@ cdef class Rational(sage.structure.element.FieldElement): """ return [ self ] + def continued_fraction_list(self, type="std"): + r""" + Return the list of partial quotients of this rational number. + + INPUT: + + - ``type`` - either "std" (the default) for the standard continued + fractions or "hj" for the Hirzebruch-Jung ones. + + EXAMPLES:: + + sage: (13/9).continued_fraction_list() + [1, 2, 4] + sage: 1 + 1/(2 + 1/4) + 13/9 + + sage: (225/157).continued_fraction_list() + [1, 2, 3, 4, 5] + sage: 1 + 1/(2 + 1/(3 + 1/(4 + 1/5))) + 225/157 + + sage: (fibonacci(20)/fibonacci(19)).continued_fraction_list() + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2] + + sage: (-1/3).continued_fraction_list() + [-1, 1, 2] + + Check that the partial quotients of an integer ``n`` is simply ``[n]``:: + + sage: QQ(1).continued_fraction_list() + [1] + sage: QQ(0).continued_fraction_list() + [0] + sage: QQ(-1).continued_fraction_list() + [-1] + + Hirzebruch-Jung continued fractions:: + + sage: (11/19).continued_fraction_list("hj") + [1, 3, 2, 3, 2] + sage: 1 - 1/(3 - 1/(2 - 1/(3 - 1/2))) + 11/19 + + sage: (225/137).continued_fraction_list("hj") + [2, 3, 5, 10] + sage: 2 - 1/(3 - 1/(5 - 1/10)) + 225/137 + + sage: (-23/19).continued_fraction_list("hj") + [-1, 5, 4] + sage: -1 - 1/(5 - 1/4) + -23/19 + """ + cdef Integer z + cdef mpz_t p,q,tmp + cdef list res = [] + + mpz_init(tmp) + mpz_init(p) + mpz_init(q) + mpz_set(p, mpq_numref(self.value)) + mpz_set(q, mpq_denref(self.value)) + + if type == "std": + while mpz_sgn(q) != 0: + z = PY_NEW(Integer) + mpz_fdiv_qr(z.value,tmp,p,q) + mpz_set(p,q) + mpz_set(q,tmp) + res.append(z) + elif type == "hj": + while mpz_sgn(q) != 0: + z = PY_NEW(Integer) + mpz_cdiv_qr(z.value,tmp,p,q) + mpz_set(p,q) + mpz_set(q,tmp) + res.append(z) + if mpz_sgn(q) == 0: + break + z = PY_NEW(Integer) + mpz_fdiv_qr(z.value,tmp,p,q) + mpz_set(p,q) + mpz_set(q,tmp) + mpz_neg(z.value,z.value) + res.append(z) + else: + mpz_clear(p) + mpz_clear(q) + mpz_clear(tmp) + raise ValueError("the type must be one of 'floor', 'hj'") + + mpz_clear(p) + mpz_clear(q) + mpz_clear(tmp) + + return res + + def continued_fraction(self): + r""" + Return the continued fraction of that rational. + + EXAMPLES:: + + sage: (641/472).continued_fraction() + [1; 2, 1, 3, 1, 4, 1, 5] + + sage: a = (355/113).continued_fraction(); a + [3; 7, 16] + sage: a.n(digits=10) + 3.141592920 + sage: pi.n(digits=10) + 3.141592654 + + It's almost pi! + """ + #TODO: do better + from sage.rings.continued_fraction import ContinuedFraction_periodic + l = self.continued_fraction_list() + return ContinuedFraction_periodic(l) def __richcmp__(left, right, int op): """ @@ -629,7 +750,7 @@ cdef class Rational(sage.structure.element.FieldElement): False """ cdef Rational z - z = PY_NEW(Rational) + z = Rational.__new__(Rational) mpq_set(z.value, self.value) return z @@ -977,10 +1098,10 @@ cdef class Rational(sage.structure.element.FieldElement): else: R = RealField(prec) if self.is_zero(): - return R.zero_element() + return R.zero() val = self.valuation(p) if val >= 0: - return R.zero_element() + return R.zero() return -val * R(p).log() def local_height_arch(self, prec=None): @@ -1016,7 +1137,7 @@ cdef class Rational(sage.structure.element.FieldElement): R = RealField(prec) a = self.abs() if a <= 1: - return R.zero_element() + return R.zero() return R(a).log() def global_height_non_arch(self, prec=None): @@ -1059,7 +1180,7 @@ cdef class Rational(sage.structure.element.FieldElement): R = RealField(prec) d = self.denominator() if d.is_one(): - return R.zero_element() + return R.zero() return R(d).log() def global_height_arch(self, prec=None): @@ -1573,11 +1694,11 @@ cdef class Rational(sage.structure.element.FieldElement): raise ValueError, "p must be at least 2." if mpq_sgn(self.value) == 0: import sage.rings.infinity - u = PY_NEW(Rational) + u = Rational.__new__(Rational) mpq_set_ui(u.value, 1, 1) return (sage.rings.infinity.infinity, u) v = PY_NEW(integer.Integer) - u = PY_NEW(Rational) + u = Rational.__new__(Rational) sig_on() mpz_set_ui(v.value, mpz_remove(mpq_numref(u.value), mpq_numref(self.value), p.value)) sig_off() @@ -1705,7 +1826,7 @@ cdef class Rational(sage.structure.element.FieldElement): from sage.functions.other import _do_sqrt return _do_sqrt(self, prec=prec, all=all) - cdef Rational z = PY_NEW(Rational) + cdef Rational z = Rational.__new__(Rational) cdef mpz_t tmp cdef int non_square = 0 @@ -1968,15 +2089,15 @@ cdef class Rational(sage.structure.element.FieldElement): Test larger rationals:: - sage: Q = continued_fraction(pi, bits=3000).convergents() - sage: all([RDF(q) == RR(q) for q in Q]) + sage: Q = continued_fraction(pi).convergents()[:100] + sage: all([RDF(q) == RR(q) for q in Q]) True At some point, the continued fraction and direct conversion to ``RDF`` should agree:: sage: RDFpi = RDF(pi) - sage: all([RDF(q) == RDFpi for q in Q[20:]]) + sage: all([RDF(q) == RDFpi for q in Q[20:]]) True """ return mpq_get_d_nearest(self.value) @@ -2045,7 +2166,7 @@ cdef class Rational(sage.structure.element.FieldElement): 5/6 """ cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_add(x.value, self.value, (right).value) return x @@ -2071,7 +2192,7 @@ cdef class Rational(sage.structure.element.FieldElement): """ # self and right are guaranteed to be Integers cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_sub(x.value, self.value, (right).value) return x @@ -2098,7 +2219,7 @@ cdef class Rational(sage.structure.element.FieldElement): -2/3 """ cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_neg(x.value, self.value) return x @@ -2112,7 +2233,7 @@ cdef class Rational(sage.structure.element.FieldElement): 3/7 """ cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) if mpz_sizeinbase (mpq_numref(self.value), 2) > 100000 or \ mpz_sizeinbase (mpq_denref(self.value), 2) > 100000: # We only use the signal handler (to enable ctrl-c out) in case @@ -2160,7 +2281,7 @@ cdef class Rational(sage.structure.element.FieldElement): if mpq_cmp_si(( right).value, 0, 1) == 0: raise ZeroDivisionError, "Rational division by zero" cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_div(x.value, self.value, (right).value) return x @@ -2200,7 +2321,7 @@ cdef class Rational(sage.structure.element.FieldElement): if self.is_zero(): raise ZeroDivisionError, "rational division by zero" cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_inv(x.value, self.value) return x @@ -2351,7 +2472,7 @@ cdef class Rational(sage.structure.element.FieldElement): return self if n % 2 else -self raise RuntimeError("exponent must be at most %s" % sys.maxsize) - cdef Rational x = PY_NEW(Rational) + cdef Rational x = Rational.__new__(Rational) if nn == 0: mpq_set_si(x.value, 1, 1) @@ -2424,7 +2545,7 @@ cdef class Rational(sage.structure.element.FieldElement): 4/17 """ cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_neg(x.value, self.value) return x @@ -2460,7 +2581,7 @@ cdef class Rational(sage.structure.element.FieldElement): 4/17 """ cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) mpq_abs(x.value, self.value) return x @@ -3265,7 +3386,7 @@ cdef class Rational(sage.structure.element.FieldElement): Return ``self * 2^exp``. """ cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) sig_on() if exp < 0: mpq_div_2exp(x.value,self.value,-exp) @@ -3313,7 +3434,7 @@ cdef class Rational(sage.structure.element.FieldElement): Return ``self / 2^exp``. """ cdef Rational x - x = PY_NEW(Rational) + x = Rational.__new__(Rational) sig_on() if exp < 0: mpq_mul_2exp(x.value,self.value,-exp) @@ -3702,7 +3823,7 @@ cdef class Z_to_Q(Morphism): 2 """ cdef Rational rat - rat = PY_NEW(Rational) + rat = Rational.__new__(Rational) mpq_set_z(rat.value, (x).value) return rat @@ -3813,7 +3934,7 @@ cdef class int_to_Q(Morphism): 14 """ cdef Rational rat - rat = PY_NEW(Rational) + rat = Rational.__new__(Rational) mpq_set_si(rat.value, PyInt_AS_LONG(a), 1) return rat diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index f3e1bb214c3..88b4c7f0235 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -1108,10 +1108,11 @@ def selmer_group_iterator(self, S, m, proof=True): [1, 5, -1, -5] """ KSgens, ords = self.selmer_group(S=S, m=m, proof=proof, orders=True) - one = self.one_element() - from sage.misc.all import prod, cartesian_product_iterator - for ev in cartesian_product_iterator([range(o) for o in ords]): - yield prod([p**e for p,e in zip(KSgens, ev)], one) + one = self.one() + from sage.misc.all import prod + from itertools import product + for ev in product(*[range(o) for o in ords]): + yield prod((p**e for p,e in zip(KSgens, ev)), one) ################################# diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index 6e8b74eb567..b373c77817d 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -858,20 +858,6 @@ cdef class RealDoubleElement(FieldElement): """ return Integer(self._value) - def parent(self): - """ - Return the real double field, which is the parent of ``self``. - - EXAMPLES:: - - sage: a = RDF(2.3) - sage: a.parent() - Real Double Field - sage: parent(a) - Real Double Field - """ - return self._parent - def _interface_init_(self, I=None): """ Return ``self`` formatted as a string, suitable as input to another diff --git a/src/sage/rings/real_interval_absolute.pyx b/src/sage/rings/real_interval_absolute.pyx index 750a306d01c..7d9690109fe 100644 --- a/src/sage/rings/real_interval_absolute.pyx +++ b/src/sage/rings/real_interval_absolute.pyx @@ -312,7 +312,7 @@ cdef class RealIntervalAbsoluteElement(FieldElement): cdef _new_c(self, Integer _mantissa, Integer _diameter): cdef RealIntervalAbsoluteElement x - x = PY_NEW(RealIntervalAbsoluteElement) + x = RealIntervalAbsoluteElement.__new__(RealIntervalAbsoluteElement) x._parent = self._parent x._mantissa = _mantissa x._diameter = _diameter diff --git a/src/sage/rings/real_lazy.pyx b/src/sage/rings/real_lazy.pyx index b2d1431e930..fbb01ba0e92 100644 --- a/src/sage/rings/real_lazy.pyx +++ b/src/sage/rings/real_lazy.pyx @@ -679,13 +679,13 @@ cdef class LazyFieldElement(FieldElement): return hash(complex(self)) cdef LazyFieldElement _new_wrapper(self, value): - cdef LazyWrapper e = PY_NEW(LazyWrapper) + cdef LazyWrapper e = LazyWrapper.__new__(LazyWrapper) e._parent = self._parent e._value = value return e cdef LazyFieldElement _new_binop(self, LazyFieldElement left, LazyFieldElement right, op): - cdef LazyBinop e = PY_NEW(LazyBinop) + cdef LazyBinop e = LazyBinop.__new__(LazyBinop) e._parent = self._parent e._left = left e._right = right @@ -693,7 +693,7 @@ cdef class LazyFieldElement(FieldElement): return e cdef LazyFieldElement _new_unop(self, LazyFieldElement arg, op): - cdef LazyUnop e = PY_NEW(LazyUnop) + cdef LazyUnop e = LazyUnop.__new__(LazyUnop) e._parent = self._parent e._op = op e._arg = arg @@ -1318,7 +1318,7 @@ cdef class LazyNamedUnop(LazyUnop): """ arg = self._arg.eval(R) cdef bint has_extra_args = self._extra_args is not None and len(self._extra_args) > 0 - if PY_TYPE_CHECK_EXACT(R, type): + if type(R) is type: f = getattr(math, self._op) if has_extra_args: return f(arg, *self._extra_args) @@ -1704,9 +1704,9 @@ cdef class LazyWrapperMorphism(Morphism): sage: f(x)._value 20 """ - cdef LazyWrapper e = PY_NEW(LazyWrapper) + cdef LazyWrapper e = LazyWrapper.__new__(LazyWrapper) e._parent = self._codomain - if PY_TYPE_CHECK_EXACT(x, LazyWrapper): + if type(x) is LazyWrapper: e._value = (x)._value else: e._value = x diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 7648833a41a..8ae3d248bf4 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -564,7 +564,7 @@ cdef class RealIntervalField_class(sage.rings.ring.Field): Return a new real number with parent ``self``. """ cdef RealIntervalFieldElement x - x = PY_NEW(RealIntervalFieldElement) + x = RealIntervalFieldElement.__new__(RealIntervalFieldElement) x._parent = self mpfi_init2(x.value, self.__prec) x.init = 1 @@ -1118,7 +1118,7 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): Return a new real interval with same parent as ``self``. """ cdef RealIntervalFieldElement x - x = PY_NEW(RealIntervalFieldElement) + x = RealIntervalFieldElement.__new__(RealIntervalFieldElement) x._parent = self._parent mpfi_init2(x.value, (self._parent).__prec) x.init = 1 @@ -1442,19 +1442,6 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): """ return self - def parent(self): - """ - Return the parent of ``self``. - - EXAMPLES:: - - sage: R = RealIntervalField() - sage: a = R('1.2456') - sage: a.parent() - Real Interval Field with 53 bits of precision - """ - return self._parent - # MPFR had an elaborate "truncation" scheme to avoid printing # inaccurate-looking results; this has been removed for MPFI, # because I think it's less confusing to get such results than to @@ -3690,13 +3677,14 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): mpfi_union(x.value, self.value, other_intv.value) return x - def min(self, _other): + def min(self, *_others): """ - Return an interval containing the minimum of ``self`` and ``other``. + Return an interval containing the minimum of ``self`` and the + arguments. EXAMPLES:: - sage: a=RIF(-1, 1).min(0).endpoints() + sage: a = RIF(-1, 1).min(0).endpoints() sage: a[0] == -1.0 and a[1].abs() == 0.0 # in MPFI, the sign of 0.0 is not specified True sage: RIF(-1, 1).min(pi).endpoints() @@ -3705,6 +3693,30 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): (-100.000000000000, 1.00000000000000) sage: RIF(-1, 1).min(RIF(-100, 0)).endpoints() (-100.000000000000, 0.000000000000000) + sage: RIF(-1, 1).min(RIF(-100, 2), RIF(-200, -3)).endpoints() + (-200.000000000000, -3.00000000000000) + + Note that if the minimum is one of the given elements, + that element will be returned. :: + + sage: a = RIF(-1, 1) + sage: b = RIF(2, 3) + sage: c = RIF(3, 4) + sage: c.min(a, b) is a + True + sage: b.min(a, c) is a + True + sage: a.min(b, c) is a + True + + It might also be convenient to call the method as a function:: + + sage: from sage.rings.real_mpfi import RealIntervalFieldElement + sage: RealIntervalFieldElement.min(a, b, c) is a + True + sage: elements = [a, b, c] + sage: RealIntervalFieldElement.min(*elements) is a + True The generic min does not always do the right thing:: @@ -3712,24 +3724,56 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): 0 sage: min(RIF(-1, 1), RIF(-100, 100)).endpoints() (-1.00000000000000, 1.00000000000000) + + .. SEEALSO:: + + :meth:`~sage.rings.real_mpfi.RealIntervalFieldElement.max` + + TESTS:: + + sage: a.min('x') + Traceback (most recent call last): + ... + TypeError: Unable to convert number to real interval. """ + cdef RealIntervalFieldElement constructed + cdef RealIntervalFieldElement result cdef RealIntervalFieldElement other - if isinstance(_other, RealIntervalFieldElement): - other = _other - else: - other = self._parent(_other) - if mpfr_cmp(&self.value.right, &other.value.left) <= 0: - return self - elif mpfr_cmp(&other.value.right, &self.value.left) <= 0: - return other - cdef RealIntervalFieldElement x = self._new() - mpfr_min(&x.value.left, &self.value.left, &other.value.left, GMP_RNDD) - mpfr_min(&x.value.right, &self.value.right, &other.value.right, GMP_RNDU) - return x + cdef bint initialized - def max(self, _other): - """ - Return an interval containing the maximum of ``self`` and ``other``. + initialized = False + result = self + + for _other in _others: + if isinstance(_other, RealIntervalFieldElement): + other = _other + else: + other = self._parent(_other) + + if mpfr_cmp(&result.value.right, &other.value.left) <= 0: + pass + elif mpfr_cmp(&other.value.right, &result.value.left) <= 0: + result = other + else: + if not initialized: + constructed = self._new() + initialized = True + mpfr_min(&constructed.value.left, + &result.value.left, + &other.value.left, + GMP_RNDD) + mpfr_min(&constructed.value.right, + &result.value.right, + &other.value.right, + GMP_RNDU) + result = constructed + + return result + + def max(self, *_others): + """ + Return an interval containing the maximum of ``self`` and the + arguments. EXAMPLES:: @@ -3739,6 +3783,30 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): (2.00000000000000, 3.00000000000000) sage: RIF(-1, 1).max(RIF(-100, 100)).endpoints() (-1.00000000000000, 100.000000000000) + sage: RIF(-1, 1).max(RIF(-100, 100), RIF(5, 10)).endpoints() + (5.00000000000000, 100.000000000000) + + Note that if the maximum is one of the given elements, + that element will be returned. :: + + sage: a = RIF(-1, 1) + sage: b = RIF(2, 3) + sage: c = RIF(3, 4) + sage: c.max(a, b) is c + True + sage: b.max(a, c) is c + True + sage: a.max(b, c) is c + True + + It might also be convenient to call the method as a function:: + + sage: from sage.rings.real_mpfi import RealIntervalFieldElement + sage: RealIntervalFieldElement.max(a, b, c) is c + True + sage: elements = [a, b, c] + sage: RealIntervalFieldElement.max(*elements) is c + True The generic max does not always do the right thing:: @@ -3746,20 +3814,52 @@ cdef class RealIntervalFieldElement(sage.structure.element.RingElement): 0 sage: max(RIF(-1, 1), RIF(-100, 100)).endpoints() (-1.00000000000000, 1.00000000000000) + + .. SEEALSO:: + + :meth:`~sage.rings.real_mpfi.RealIntervalFieldElement.min` + + TESTS:: + + sage: a.max('x') + Traceback (most recent call last): + ... + TypeError: Unable to convert number to real interval. """ + cdef RealIntervalFieldElement constructed + cdef RealIntervalFieldElement result cdef RealIntervalFieldElement other - if isinstance(_other, RealIntervalFieldElement): - other = _other - else: - other = self._parent(_other) - if mpfr_cmp(&self.value.right, &other.value.left) <= 0: - return other - elif mpfr_cmp(&other.value.right, &self.value.left) <= 0: - return self - cdef RealIntervalFieldElement x = self._new() - mpfr_max(&x.value.left, &self.value.left, &other.value.left, GMP_RNDD) - mpfr_max(&x.value.right, &self.value.right, &other.value.right, GMP_RNDU) - return x + cdef bint initialized + + initialized = False + result = self + + for _other in _others: + if isinstance(_other, RealIntervalFieldElement): + other = _other + else: + other = self._parent(_other) + + if mpfr_cmp(&result.value.right, &other.value.left) <= 0: + result = other + elif mpfr_cmp(&other.value.right, &result.value.left) <= 0: + pass + else: + if not initialized: + constructed = self._new() + initialized = True + + mpfr_max(&constructed.value.left, + &result.value.left, + &other.value.left, + GMP_RNDD) + mpfr_max(&constructed.value.right, + &result.value.right, + &other.value.right, + GMP_RNDU) + result = constructed + + return result ############################ # Special Functions diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 97d457c60fe..4532719c385 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -135,7 +135,6 @@ import sage.structure.element cdef bin_op from sage.structure.element import bin_op -import sage.misc.misc as misc import sage.misc.weak_dict import operator @@ -465,14 +464,14 @@ cdef class RealField_class(sage.rings.ring.Field): ParentWithGens.__init__(self, self, tuple([]), False, category = Fields()) # hack, we cannot call the constructor here - rn = PY_NEW(RealNumber) + rn = RealNumber.__new__(RealNumber) rn._parent = self mpfr_init2(rn.value, self.__prec) rn.init = 1 mpfr_set_d(rn.value, 0.0, self.rnd) self._zero_element = rn - rn = PY_NEW(RealNumber) + rn = RealNumber.__new__(RealNumber) rn._parent = self mpfr_init2(rn.value, self.__prec) rn.init = 1 @@ -486,7 +485,7 @@ cdef class RealField_class(sage.rings.ring.Field): Return a new real number with parent ``self``. """ cdef RealNumber x - x = PY_NEW(RealNumber) + x = RealNumber.__new__(RealNumber) x._parent = self mpfr_init2(x.value, self.__prec) x.init = 1 @@ -1286,7 +1285,7 @@ cdef class RealNumber(sage.structure.element.RingElement): Return a new real number with same parent as self. """ cdef RealNumber x - x = PY_NEW(RealNumber) + x = RealNumber.__new__(RealNumber) x._parent = self._parent mpfr_init2(x.value, (self._parent).__prec) x.init = 1 @@ -1461,20 +1460,13 @@ cdef class RealNumber(sage.structure.element.RingElement): mpfr_set_ui(self.value, 0, GMP_RNDN) return - cdef int wordsize - - if sage.misc.misc.is_64_bit: - wordsize = 64 - else: - wordsize = 32 + cdef int wordsize = 8 * sizeof(long) cdef mpz_t mantissa mpz_init(mantissa) - mpz_import(mantissa, lg(g) - 2, 1, wordsize/8, 0, 0, &g[2]) - cdef mp_exp_t exponent - exponent = expo(g) + cdef mp_exp_t exponent = expo(g) # Round to nearest for best results when setting a low-precision # MPFR from a high-precision GEN @@ -1769,19 +1761,6 @@ cdef class RealNumber(sage.structure.element.RingElement): """ return ZZ(0) - def parent(self): - """ - Return the parent of ``self``. - - EXAMPLES:: - - sage: R = RealField() - sage: a = R('1.2456') - sage: a.parent() - Real Field with 53 bits of precision - """ - return self._parent - def str(self, int base=10, no_sci=None, e=None, int truncate=1, bint skip_zeroes=0): """ Return a string representation of ``self``. @@ -5702,7 +5681,7 @@ cdef inline RealNumber empty_RealNumber(RealField_class parent): True """ - cdef RealNumber y = PY_NEW(RealNumber) + cdef RealNumber y = RealNumber.__new__(RealNumber) y._parent = parent mpfr_init2(y.value, parent.__prec) y.init = 1 @@ -5735,7 +5714,7 @@ cdef class RRtoRR(Map): """ cdef RealField_class parent = self._codomain cdef RealNumber y = empty_RealNumber(parent) - if PY_TYPE_CHECK_EXACT(x, RealLiteral): + if type(x) is RealLiteral: mpfr_set_str(y.value, (x).literal, (x).base, parent.rnd) else: mpfr_set(y.value, (x).value, parent.rnd) diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 6447593b95d..ef521b3e12b 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -66,17 +66,11 @@ AUTHORS: # http://www.gnu.org/licenses/ #***************************************************************************** -include "sage/ext/stdsage.pxi" -from cpython.bool cimport * - -from types import GeneratorType - -from sage.misc.lazy_attribute import lazy_class_attribute -from sage.misc.superseded import deprecation +from sage.misc.cachefunc import cached_method from sage.structure.parent_gens cimport ParentWithGens from sage.structure.parent cimport Parent from sage.structure.category_object import check_default_category -from sage.misc.prandom import randint, randrange +from sage.misc.prandom import randint from sage.categories.rings import Rings from sage.categories.commutative_rings import CommutativeRings from sage.categories.integral_domains import IntegralDomains @@ -121,6 +115,7 @@ cdef class Ring(ParentWithGens): running ._test_elements_neq() . . . pass running ._test_eq() . . . pass running ._test_euclidean_degree() . . . pass + running ._test_gcd_vs_xgcd() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_one() . . . pass running ._test_pickling() . . . pass @@ -384,7 +379,7 @@ cdef class Ring(ParentWithGens): break if len(gens) == 0: - gens = [self.zero_element()] + gens = [self.zero()] if coerce: #print [type(g) for g in gens] @@ -576,7 +571,7 @@ cdef class Ring(ParentWithGens): """ if self._zero_ideal is None: - I = Ring.ideal(self, [self.zero_element()], coerce=False) + I = Ring.ideal(self, [self.zero()], coerce=False) self._zero_ideal = I return I return self._zero_ideal @@ -682,22 +677,22 @@ cdef class Ring(ParentWithGens): """ return self.quotient(I, names) - def zero_element(self): + def zero(self): """ Return the zero element of this ring (cached). EXAMPLES:: - sage: ZZ.zero_element() + sage: ZZ.zero() 0 - sage: QQ.zero_element() + sage: QQ.zero() 0 - sage: QQ['x'].zero_element() + sage: QQ['x'].zero() 0 The result is cached:: - sage: ZZ.zero_element() is ZZ.zero_element() + sage: ZZ.zero() is ZZ.zero() True """ if self._zero_element is None: @@ -706,24 +701,22 @@ cdef class Ring(ParentWithGens): return x return self._zero_element - zero = zero_element # transitional - - def one_element(self): + def one(self): """ Return the one element of this ring (cached), if it exists. EXAMPLES:: - sage: ZZ.one_element() + sage: ZZ.one() 1 - sage: QQ.one_element() + sage: QQ.one() 1 - sage: QQ['x'].one_element() + sage: QQ['x'].one() 1 The result is cached:: - sage: ZZ.one_element() is ZZ.one_element() + sage: ZZ.one() is ZZ.one() True """ if self._one_element is None: @@ -732,8 +725,6 @@ cdef class Ring(ParentWithGens): return x return self._one_element - one = one_element # Transitional - def is_commutative(self): """ Return ``True`` if this ring is commutative. @@ -1176,6 +1167,60 @@ cdef class Ring(ParentWithGens): self.__ideal_monoid = M return M + @cached_method + def epsilon(self): + """ + Return the precision error of elements in this ring. + + EXAMPLES:: + + sage: RDF.epsilon() + 2.220446049250313e-16 + sage: ComplexField(53).epsilon() + 2.22044604925031e-16 + sage: RealField(10).epsilon() + 0.0020 + + For exact rings, zero is returned:: + + sage: ZZ.epsilon() + 0 + + This also works over derived rings:: + + sage: RR['x'].epsilon() + 2.22044604925031e-16 + sage: QQ['x'].epsilon() + 0 + + For the symbolic ring, there is no reasonable answer:: + + sage: SR.epsilon() + Traceback (most recent call last): + ... + NotImplementedError + """ + one = self.one() + try: + return one.ulp() + except AttributeError: + pass + + try: + eps = one.real().ulp() + except AttributeError: + pass + else: + return self(eps) + + B = self._base + if B is not None and B is not self: + eps = self.base_ring().epsilon() + return self(eps) + if self.is_exact(): + return self.zero() + raise NotImplementedError + cdef class CommutativeRing(Ring): """ Generic commutative ring. diff --git a/src/sage/rings/semirings/tropical_semiring.pyx b/src/sage/rings/semirings/tropical_semiring.pyx index e2c9a9371e8..fa3e0a13679 100644 --- a/src/sage/rings/semirings/tropical_semiring.pyx +++ b/src/sage/rings/semirings/tropical_semiring.pyx @@ -46,7 +46,7 @@ cdef class TropicalSemiringElement(RingElement): Return a new tropical semiring element with parent ``self`. """ cdef TropicalSemiringElement x - x = PY_NEW(TropicalSemiringElement) + x = TropicalSemiringElement.__new__(TropicalSemiringElement) x._parent = self._parent x._val = self._val return x @@ -621,37 +621,35 @@ class TropicalSemiring(Parent, UniqueRepresentation): Element = TropicalSemiringElement @cached_method - def zero_element(self): + def zero(self): """ Return the (tropical) additive identity element `+\infty`. EXAMPLES:: sage: T = TropicalSemiring(QQ) - sage: T.zero_element() + sage: T.zero() +infinity """ return self.element_class(self, None) - zero = zero_element - infinity = zero_element - additive_identity = zero_element + infinity = zero + additive_identity = zero @cached_method - def one_element(self): + def one(self): """ Return the (tropical) multiplicative identity element `0`. EXAMPLES:: sage: T = TropicalSemiring(QQ) - sage: T.one_element() + sage: T.one() 0 """ - return self.element_class(self, self.base().zero_element()) + return self.element_class(self, self.base().zero()) - one = one_element - multiplicative_identity = one_element + multiplicative_identity = one def gens(self): """ @@ -663,7 +661,7 @@ class TropicalSemiring(Parent, UniqueRepresentation): sage: T.gens() (1, +infinity) """ - return (self.element_class(self, self.base().one_element()), self.infinity()) + return (self.element_class(self, self.base().one()), self.infinity()) cdef class TropicalToTropical(Map): """ diff --git a/src/sage/rings/tests.py b/src/sage/rings/tests.py index 5fc7ab3d1f9..29709212bfd 100644 --- a/src/sage/rings/tests.py +++ b/src/sage/rings/tests.py @@ -187,8 +187,8 @@ def rings1(): v = rings0() X = random_rings(level=0) from sage.all import PolynomialRing, ZZ - v = [(lambda : PolynomialRing(X.next(), names='x'), 'univariate polynomial ring over level 0 ring'), - (lambda : PolynomialRing(X.next(), abs(ZZ.random_element(x=2,y=10)), names='x'), + v = [(lambda : PolynomialRing(next(X), names='x'), 'univariate polynomial ring over level 0 ring'), + (lambda : PolynomialRing(next(X), abs(ZZ.random_element(x=2,y=10)), names='x'), 'multivariate polynomial ring in between 2 and 10 variables over a level 0 ring')] return v diff --git a/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field.py b/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field.py index 80919a1a99e..d79bbf46c8f 100644 --- a/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field.py +++ b/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field.py @@ -299,7 +299,7 @@ from sage.structure.element import FieldElement, Element from sage.structure.parent import Parent from sage.structure.element_wrapper import ElementWrapper -from sage.structure.sage_object import have_same_parent +from sage.structure.element import have_same_parent from sage.categories.morphism import SetMorphism from sage.categories.sets_with_partial_maps import SetsWithPartialMaps @@ -1570,7 +1570,7 @@ def __pow__(self, k): elif self.is_rational(): return self.parent()._from_dict({ (1,0) : self.value._monomial_coefficients[(1,0)]**k }, remove_zeros=False) elif len(self.value._monomial_coefficients) == 1: - mon,coeff = self.value._monomial_coefficients.iteritems().next() + mon,coeff = next(self.value._monomial_coefficients.iteritems()) n = self.field_order() return self.parent()._from_dict(push_down_cython(n,dict_linear_combination([ (ZumbroichDecomposition(n, k*mon[1] % n), coeff**k,) ])), remove_zeros=False) elif k < 0: @@ -1899,7 +1899,7 @@ def field_order(self): 3 """ if bool(self.value._monomial_coefficients): - return self.value._monomial_coefficients.iterkeys().next()[0] + return next(self.value._monomial_coefficients.iterkeys())[0] else: return 1 diff --git a/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field_c.pyx b/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field_c.pyx index ad31cd33e50..03d0977cd4a 100644 --- a/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field_c.pyx +++ b/src/sage/rings/universal_cyclotomic_field/universal_cyclotomic_field_c.pyx @@ -596,7 +596,7 @@ cdef inline as_rat(int a): Internal function, not to be used directly! """ - cdef Rational rat = PY_NEW(Rational) + cdef Rational rat = Rational.__new__(Rational) mpq_set_si(rat.value,a,1) return rat @@ -685,8 +685,8 @@ cpdef dict dict_multiplication(dict D1, dict D2, int n1, int n2, int n): # filling the pointers for the dicts with ints from the dicts multiplied with the lcm # we use positions in the Zumbroich basis with find_array cdef Rational old_val, new_val1, new_val2 - new_val1 = PY_NEW(Rational) - new_val2 = PY_NEW(Rational) + new_val1 = Rational.__new__(Rational) + new_val2 = Rational.__new__(Rational) cdef int k @@ -750,7 +750,7 @@ cpdef dict dict_multiplication(dict D1, dict D2, int n1, int n2, int n): for key from 0 <= key < Lnew_size: if linear_combination_pointer[key] != 0: old_val = as_rat(linear_combination_pointer[key]) - new_val = PY_NEW(Rational) + new_val = Rational.__new__(Rational) mpq_div(new_val.value,old_val.value,denom_rat1.value) mpq_div(new_val.value,new_val.value,denom_rat2.value) D[(n,Lnew[key])] = new_val diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index 2dca5bf5dd3..998bd9934a2 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -839,8 +839,8 @@ def _set_burning_config(self): bc = {} # burning config bs = {} # burning script for v in self._nonsink_vertices: - bc[v] = b.next() - bs[v] = s.next() + bc[v] = next(b) + bs[v] = next(s) self._burning_config = SandpileConfig(self,bc) self._burning_script = SandpileConfig(self,bs) diff --git a/src/sage/sat/boolean_polynomials.py b/src/sage/sat/boolean_polynomials.py index 9843990ca11..9392b66709e 100644 --- a/src/sage/sat/boolean_polynomials.py +++ b/src/sage/sat/boolean_polynomials.py @@ -19,12 +19,12 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.sequence import Sequence -from sage.rings.infinity import PlusInfinity - from sage.sat.solvers import SatSolver from sage.sat.converters import ANF2CNFConverter +from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + + def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): """ Solve system of Boolean polynomials ``F`` by solving the @@ -84,6 +84,8 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): This time we pass a few options through to the converter and the solver:: sage: s = solve_sat(F, s_verbosity=1, c_max_vars_sparse=4, c_cutting_number=8) # optional - cryptominisat + c Flit... + ... sage: F.subs(s[0]) # optional - cryptominisat Polynomial Sequence with 36 Polynomials in 0 Variables @@ -114,9 +116,11 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): First the normal use case:: - sage: solve_sat(F,n=infinity) # optional - cryptominisat - [{d: 0, b: 0, c: 0, a: 0}, {d: 1, b: 1, c: 0, a: 1}, - {d: 1, b: 0, c: 1, a: 0}, {d: 0, b: 1, c: 1, a: 1}] + sage: sorted(solve_sat(F,n=infinity)) # optional - cryptominisat + [{d: 0, c: 0, b: 0, a: 0}, + {d: 0, c: 1, b: 1, a: 1}, + {d: 1, c: 0, b: 1, a: 1}, + {d: 1, c: 1, b: 0, a: 0}] Now we are only interested in the solutions of the variables a and b:: @@ -132,19 +136,19 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): assert(n>0) try: - m = len(F) + len(F) except AttributeError: F = F.gens() - m = len(F) + len(F) - P = iter(F).next().parent() + P = next(iter(F)).parent() K = P.base_ring() if target_variables is None: - target_variables = Sequence(F).variables() + target_variables = PolynomialSequence(F).variables() else: - target_variables = Sequence(target_variables).variables() - assert(set(target_variables).issubset(set(P.gens()))) + target_variables = PolynomialSequence(target_variables).variables() + assert(set(target_variables).issubset(set(P.gens()))) # instantiate the SAT solver @@ -153,7 +157,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): if not isinstance(solver, SatSolver): solver_kwds = {} - for k,v in kwds.iteritems(): + for k, v in kwds.iteritems(): if k.startswith("s_"): solver_kwds[k[2:]] = v @@ -166,14 +170,14 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): if not isinstance(converter, ANF2CNFConverter): converter_kwds = {} - for k,v in kwds.iteritems(): + for k, v in kwds.iteritems(): if k.startswith("c_"): converter_kwds[k[2:]] = v converter = converter(solver, P, **converter_kwds) phi = converter(F) - rho = dict( (phi[i],i) for i in range(len(phi)) ) + rho = dict((phi[i], i) for i in range(len(phi))) S = [] @@ -181,25 +185,25 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): s = solver() if s: - S.append( dict( (x, K(s[rho[x]])) for x in target_variables ) ) + S.append(dict((x, K(s[rho[x]])) for x in target_variables)) if n is not None and len(S) == n: break - exclude_solution = tuple(-rho[x] if s[rho[x]] else rho[x] for x in target_variables) + exclude_solution = tuple(-rho[x] if s[rho[x]] else rho[x] for x in target_variables) solver.add_clause(exclude_solution) else: try: learnt = solver.learnt_clauses(unitary_only=True) if learnt: - S.append( dict((phi[abs(i)-1],K(i<0)) for i in learnt) ) + S.append(dict((phi[abs(i)-1], K(i<0)) for i in learnt)) else: - S.append( s ) + S.append(s) break except (AttributeError, NotImplementedError): # solver does not support recovering learnt clauses - S.append( s ) + S.append(s) break if len(S) == 1: @@ -211,6 +215,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): return S[0:-1] return S + def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=False, **kwds): """ Learn new polynomials by running SAT-solver ``solver`` on @@ -259,7 +264,7 @@ def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=Fa We construct a slightly larger equation system and recover some equations after 20 restarts:: - sage: set_random_seed(2300) # optional - cryptominisat + sage: set_random_seed(2303) # optional - cryptominisat sage: sr = mq.SR(1,4,4,4,gf2=True,polybori=True) # optional - cryptominisat sage: F,s = sr.polynomial_system() # optional - cryptominisat sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat @@ -276,14 +281,25 @@ def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=Fa passed, then this function behaves essentially like :func:`solve` except that this function does not support ``n>1``. + + TESTS: + + We test that :trac:`17351` is fixed, by checking that the following doctest does not raise an + error:: + + sage: P. = BooleanPolynomialRing() + sage: F = [a*c + a + b*c + c + 1, a*b + a*c + a + c + 1, a*b + a*c + a + b*c + 1] + sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat + sage: learn_sat(F, s_maxrestarts=0, interreduction=True) # optional - cryptominisat + [] """ try: - m = len(F) + len(F) except AttributeError: F = F.gens() - m = len(F) + len(F) - P = iter(F).next().parent() + P = next(iter(F)).parent() K = P.base_ring() # instantiate the SAT solver @@ -292,7 +308,7 @@ def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=Fa from sage.sat.solvers.cryptominisat import CryptoMiniSat as solver solver_kwds = {} - for k,v in kwds.iteritems(): + for k, v in kwds.iteritems(): if k.startswith("s_"): solver_kwds[k[2:]] = v @@ -304,15 +320,14 @@ def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=Fa from sage.sat.converters.polybori import CNFEncoder as converter converter_kwds = {} - for k,v in kwds.iteritems(): + for k, v in kwds.iteritems(): if k.startswith("c_"): converter_kwds[k[2:]] = v converter = converter(solver, P, **converter_kwds) - phi = converter(F) - rho = dict( (phi[i],i) for i in range(len(phi)) ) + rho = dict((phi[i], i) for i in range(len(phi))) s = solver() @@ -323,15 +338,15 @@ def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=Fa for c in solver.learnt_clauses(): if len(c) <= max_learnt_length: try: - learnt.append( converter.to_polynomial(c) ) + learnt.append(converter.to_polynomial(c)) except (ValueError, NotImplementedError, AttributeError): # the solver might have learnt clauses that contain CNF # variables which have no correspondence to variables in our # polynomial ring (XOR chaining variables for example) pass - learnt = Sequence(learnt) + + learnt = PolynomialSequence(P, learnt) if interreduction: learnt = learnt.ideal().interreduced_basis() return learnt - diff --git a/src/sage/sat/converters/polybori.py b/src/sage/sat/converters/polybori.py index ddf0828c7b4..bbc3b64ab8c 100644 --- a/src/sage/sat/converters/polybori.py +++ b/src/sage/sat/converters/polybori.py @@ -236,7 +236,7 @@ def choose(s): res = self.one_set for i in reversed(indices): res = ite(i, res, self.empty_set) - return iter(res).next() + return next(iter(res)) while not rest.empty(): l = choose(rest) diff --git a/src/sage/sat/solvers/cryptominisat/cryptominisat.pyx b/src/sage/sat/solvers/cryptominisat/cryptominisat.pyx index 8a143ca5067..4d938a7b536 100644 --- a/src/sage/sat/solvers/cryptominisat/cryptominisat.pyx +++ b/src/sage/sat/solvers/cryptominisat/cryptominisat.pyx @@ -360,7 +360,8 @@ cdef class CryptoMiniSat(SatSolver): This guess was wrong and we need to flip one of the following variables:: sage: cms.conflict_clause() # optional - cryptominisat - (-119, -118, -117, -116, -114, -113, -112, -110, -109, -100, -98, -97, -96, -94, -93, -92, -91, -76, -75, -71, -70, -69) + (-119, -118, -117, -116, -115, -114, -112, -111, -110, ...) + """ cdef Lit l r = [] diff --git a/src/sage/sat/solvers/cryptominisat/solverconf.pyx b/src/sage/sat/solvers/cryptominisat/solverconf.pyx index efaf90de45b..da4a80ca367 100644 --- a/src/sage/sat/solvers/cryptominisat/solverconf.pyx +++ b/src/sage/sat/solvers/cryptominisat/solverconf.pyx @@ -312,7 +312,7 @@ cdef class SolverConf(object): sage: s.verbosity # optional - cryptominisat 0 """ - cdef SolverConf other = PY_NEW(SolverConf) + cdef SolverConf other = SolverConf.__new__(SolverConf) other._conf = new SolverConfC() other._nopts = setup_map(other._map, other._conf[0], 100) for name in self.trait_names(): diff --git a/src/sage/sat/solvers/dimacs.py b/src/sage/sat/solvers/dimacs.py index c6a1f958c2d..56f9331a072 100644 --- a/src/sage/sat/solvers/dimacs.py +++ b/src/sage/sat/solvers/dimacs.py @@ -29,7 +29,7 @@ import os, sys, subprocess, shlex from sage.sat.solvers.satsolver import SatSolver -from sage.misc.misc import tmp_filename, get_verbose +from sage.misc.all import tmp_filename, get_verbose from time import sleep class DIMACS(SatSolver): diff --git a/src/sage/schemes/affine/affine_morphism.py b/src/sage/schemes/affine/affine_morphism.py index 3244eab3877..792843d6528 100644 --- a/src/sage/schemes/affine/affine_morphism.py +++ b/src/sage/schemes/affine/affine_morphism.py @@ -44,6 +44,7 @@ from sage.rings.fraction_field import FractionField from sage.rings.fraction_field_element import FractionFieldElement from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.real_mpfr import RealField from sage.schemes.generic.morphism import SchemeMorphism_polynomial diff --git a/src/sage/schemes/affine/affine_rational_point.py b/src/sage/schemes/affine/affine_rational_point.py index a2f73309604..55d4bf9ec02 100644 --- a/src/sage/schemes/affine/affine_rational_point.py +++ b/src/sage/schemes/affine/affine_rational_point.py @@ -118,14 +118,14 @@ def enum_affine_rational_field(X,B): pass iters = [ iter(R) for _ in range(n) ] for it in iters: - it.next() + next(it) i = 0 while i < n: try: - a = ZZ(iters[i].next()) + a = ZZ(next(iters[i])) except StopIteration: iters[i] = iter(R) # reset - P[i] = iters[i].next() # reset P[i] to 0 and increment + P[i] = next(iters[i]) # reset P[i] to 0 and increment i += 1 continue m = m.gcd(a) diff --git a/src/sage/schemes/affine/affine_space.py b/src/sage/schemes/affine/affine_space.py index 85b6354000c..f2f9b5b7afa 100644 --- a/src/sage/schemes/affine/affine_space.py +++ b/src/sage/schemes/affine/affine_space.py @@ -193,16 +193,16 @@ def __iter__(self): P = [ zero for _ in range(n) ] yield self(P) iters = [ iter(R) for _ in range(n) ] - for x in iters: x.next() # put at zero + for x in iters: next(x) # put at zero i = 0 while i < n: try: - P[i] = iters[i].next() + P[i] = next(iters[i]) yield self(P) i = 0 except StopIteration: iters[i] = iter(R) # reset - iters[i].next() # put at zero + next(iters[i]) # put at zero P[i] = zero i += 1 diff --git a/src/sage/schemes/elliptic_curves/ec_database.py b/src/sage/schemes/elliptic_curves/ec_database.py index f812b3ddce5..ded060f2a6d 100644 --- a/src/sage/schemes/elliptic_curves/ec_database.py +++ b/src/sage/schemes/elliptic_curves/ec_database.py @@ -83,7 +83,7 @@ def rank(self, rank, tors=0, n=10, labels=False): ((0, 0, 1, -23737, 960366), 457532830151317) """ - from sage.misc.misc import SAGE_SHARE + from sage.env import SAGE_SHARE db = os.path.join(SAGE_SHARE,'ellcurves') data = os.path.join(db,'rank%s'%rank) if not os.path.exists(data): diff --git a/src/sage/schemes/elliptic_curves/ell_egros.py b/src/sage/schemes/elliptic_curves/ell_egros.py index 8a4f0dda1b5..3e86c9a6a95 100644 --- a/src/sage/schemes/elliptic_curves/ell_egros.py +++ b/src/sage/schemes/elliptic_curves/ell_egros.py @@ -86,7 +86,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.misc.misc import prod +from sage.misc.all import prod from sage.misc.all import xmrange from sage.rings.all import QQ from constructor import EllipticCurve, EllipticCurve_from_j diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index b9a2de44060..25dc860f02a 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -394,7 +394,7 @@ def is_quadratic_twist(self, other): if not is_EllipticCurve(E) or not is_EllipticCurve(F): raise ValueError("arguments are not elliptic curves") K = E.base_ring() - zero = K.zero_element() + zero = K.zero() if not K == F.base_ring(): return zero j=E.j_invariant() @@ -404,7 +404,7 @@ def is_quadratic_twist(self, other): if E.is_isomorphic(F): if K is rings.QQ: return rings.ZZ(1) - return K.one_element() + return K.one() char=K.characteristic() @@ -493,7 +493,7 @@ def is_quartic_twist(self, other): if not is_EllipticCurve(E) or not is_EllipticCurve(F): raise ValueError("arguments are not elliptic curves") K = E.base_ring() - zero = K.zero_element() + zero = K.zero() if not K == F.base_ring(): return zero j=E.j_invariant() @@ -501,7 +501,7 @@ def is_quartic_twist(self, other): return zero if E.is_isomorphic(F): - return K.one_element() + return K.one() char=K.characteristic() @@ -562,7 +562,7 @@ def is_sextic_twist(self, other): if not is_EllipticCurve(E) or not is_EllipticCurve(F): raise ValueError("arguments are not elliptic curves") K = E.base_ring() - zero = K.zero_element() + zero = K.zero() if not K == F.base_ring(): return zero j=E.j_invariant() @@ -570,7 +570,7 @@ def is_sextic_twist(self, other): return zero if E.is_isomorphic(F): - return K.one_element() + return K.one() char=K.characteristic() diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index f0f2e095160..cf876c7d305 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -61,7 +61,7 @@ import sage.rings.arith as arith import sage.rings.all as rings from sage.rings.number_field.number_field_base import is_NumberField -import sage.misc.misc as misc +from sage.misc.all import prod as mul from sage.misc.cachefunc import cached_method, cached_function from sage.misc.fast_methods import WithEqualityById @@ -79,7 +79,6 @@ factor = arith.factor sqrt = math.sqrt exp = math.exp -mul = misc.mul next_prime = arith.next_prime oo = rings.infinity # infinity @@ -2779,10 +2778,10 @@ def _p_primary_torsion_basis(self,p,m=None): Epi = iter(Ep) # used to iterate through Ep # Find P1,P2 which generate the p-torsion: - P1 = Epi.next() - while P1.is_zero(): P1 = Epi.next() - P2 = Epi.next() - while generic.linear_relation(P1,P2,'+')[0] != 0: P2 = Epi.next() + P1 = next(Epi) + while P1.is_zero(): P1 = next(Epi) + P2 = next(Epi) + while generic.linear_relation(P1,P2,'+')[0] != 0: P2 = next(Epi) k = 1 log_order = 2 diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 55eb71a85ef..23270569596 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -95,7 +95,7 @@ import sage.matrix.all as matrix from sage.rings.ring import Ring from sage.rings.arith import gcd, prime_divisors -from sage.misc.misc import prod +from sage.misc.all import prod import ell_torsion from ell_generic import is_EllipticCurve @@ -2745,7 +2745,7 @@ def is_isogenous(self, other, proof=True, maxnorm=100): PI = K.primes_of_degree_one_iter() while True: - P = PI.next() + P = next(PI) if P.norm() > maxnorm: break if not P.divides(N): if E1.reduction(P).cardinality() != E2.reduction(P).cardinality(): @@ -2776,7 +2776,7 @@ def is_isogenous(self, other, proof=True, maxnorm=100): OP = K.residue_field(P) if E1.change_ring(OP).cardinality() != E2.change_ring(OP).cardinality(): return False - P = PI.next() + P = next(PI) # Finally we compute the full isogeny class of E1 and check if # E2 is isomorphic to any curve in the class: diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index c3294bcd1e8..3d51ebe7645 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -1294,7 +1294,7 @@ def _line_(self, R, Q): if self.is_zero() or R.is_zero(): if self == R: - return self.curve().base_field().one_element() + return self.curve().base_field().one() if self.is_zero(): return Q[0] - R[0] if R.is_zero(): @@ -1467,7 +1467,7 @@ def _miller_(self, Q, n): n = n.abs() n_is_negative = True - one = self.curve().base_field().one_element() + one = self.curve().base_field().one() t = one V = self S = 2*V @@ -1578,7 +1578,7 @@ def weil_pairing(self, Q, n): if not ((n*P).is_zero() and (n*Q).is_zero()): raise ValueError("points must both be n-torsion") - one = E.base_field().one_element() + one = E.base_field().one() # Case where P = Q if P == Q: diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index abe9c9304eb..abd2fff930d 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -81,7 +81,7 @@ IntegerRing, RealField, ComplexField, RationalField) -import sage.misc.misc as misc +import sage.misc.all as misc from sage.misc.all import verbose from sage.misc.functional import log @@ -1136,6 +1136,10 @@ def modular_symbol(self, sign=1, use_eclib = False, normalize = "L_ratio"): much faster if ``use_eclib=False``, though evaluation of it after computing it won't be any faster. + .. SEEALSO:: + + :meth:`modular_symbol_numerical` + EXAMPLES:: sage: E=EllipticCurve('37a1') @@ -1217,6 +1221,84 @@ def modular_symbol(self, sign=1, use_eclib = False, normalize = "L_ratio"): self.__modular_symbol[typ] = M return M + def _modsym(self, tau, prec=53): + r""" + Compute the modular symbol `\{\infty, \tau\}` analytically. + + EXAMPLES:: + + sage: E = EllipticCurve('11a1') + sage: E._modsym(0) # abs tol 1e-14 + 0.253841860855911 - 2.86184184507043e-17*I + sage: E = EllipticCurve('17a1') + sage: E._modsym(0) # abs tol 1e-14 + 0.386769938387780 - 4.26353246509333e-17*I + """ + from sage.modular.cusps import Cusps + from sage.sets.all import Primes + N = self.conductor() + # Find a prime p that is suitable, along with matrices M[i]. + for p in Primes(): + if N % p == 0: + continue + # Are the cusps tau, p*tau, and (tau+j)/p for j = 0, ..., p-1 + # all equivalent? + t = Cusps(tau) + M = [] + b, m = t.is_gamma0_equiv(p * tau, N, transformation='matrix') + if not b: + continue + M.append(m) + good = True + for j in range(p): + b, m = t.is_gamma0_equiv((tau + j) / p, N, + transformation='matrix') + if not b: + good = False + break + M.append(m) + if good: + # Found it! + break + f = self.newform() + return -sum(f.period(m, prec) for m in M) / (1 + p - self.ap(p)) + + def modular_symbol_numerical(self, sign=1, prec=53): + """ + Return the modular symbol as a numerical function. + + .. NOTE:: + + This method does not compute spaces of modular symbols, so + it is suitable for curves of larger conductor than can be + handled by :meth:`modular_symbol`. + + EXAMPLES:: + + sage: E = EllipticCurve('19a1') + sage: f = E.modular_symbol_numerical(1) # indirect doctest + sage: g = E.modular_symbol(1) + sage: f(2), g(2) # abs tol 1e-14 + (0.333333333333330, 1/3) + sage: f(oo), g(oo) + (-0.000000000000000, 0) + + sage: E = EllipticCurve('79a1') + sage: f = E.modular_symbol_numerical(-1) # indirect doctest + sage: g = E.modular_symbol(-1) + sage: f(1), g(1) # abs tol 1e-14 + (7.60908499689245e-16, 0) + sage: f(oo), g(oo) + (0.000000000000000, 0) + """ + lam = self.period_lattice().basis(prec=prec) + if sign == 1: + P = lam[0].real() + return lambda a: self._modsym(a, prec).real() / P + else: + P = lam[1].imag() + return lambda a: self._modsym(a, prec).imag() / P + padic_lseries = padics.padic_lseries def newform(self): @@ -4029,7 +4111,7 @@ def minimal_quadratic_twist(self): If the curve has square-free conductor then it is already minimal (see :trac:`14060`):: - sage: E = cremona_optimal_curves([2*3*5*7*11]).next() + sage: E = next(cremona_optimal_curves([2*3*5*7*11])) sage: (E, 1) == E.minimal_quadratic_twist() True diff --git a/src/sage/schemes/elliptic_curves/ell_tate_curve.py b/src/sage/schemes/elliptic_curves/ell_tate_curve.py index f9516fbd942..461db06ca95 100644 --- a/src/sage/schemes/elliptic_curves/ell_tate_curve.py +++ b/src/sage/schemes/elliptic_curves/ell_tate_curve.py @@ -191,7 +191,7 @@ def parameter(self,prec=20): Delta = CuspForms(weight=12).basis()[0] j = (E4.q_expansion(prec+3))**3/Delta.q_expansion(prec+3) jinv = (1/j).power_series() - q_in_terms_of_jinv = jinv.reversion() + q_in_terms_of_jinv = jinv.reverse() R = Qp(self._p,prec=prec) qE = q_in_terms_of_jinv(R(1/self._E.j_invariant())) self._q = qE diff --git a/src/sage/schemes/elliptic_curves/formal_group.py b/src/sage/schemes/elliptic_curves/formal_group.py index cd1ddc1a9a4..6da9ca47443 100644 --- a/src/sage/schemes/elliptic_curves/formal_group.py +++ b/src/sage/schemes/elliptic_curves/formal_group.py @@ -732,7 +732,7 @@ def sigma(self, prec=10): k = self.curve().base_ring() fl = self.log(prec) R = rings.PolynomialRing(k,'c'); c = R.gen() - F = fl.reversion() + F = fl.reverse() S = rings.LaurentSeriesRing(R,'z') c = S(c) diff --git a/src/sage/schemes/elliptic_curves/gal_reps.py b/src/sage/schemes/elliptic_curves/gal_reps.py index 80e74222484..73f30900edb 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps.py +++ b/src/sage/schemes/elliptic_curves/gal_reps.py @@ -127,7 +127,7 @@ from sage.structure.sage_object import SageObject import sage.rings.arith as arith -import sage.misc.misc as misc +import sage.misc.all as misc import sage.rings.all as rings from sage.rings.all import RealField, GF from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index 6b89afb315f..9b254275c70 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -731,7 +731,7 @@ def _semistable_reducible_primes(E): last_char = 0 # The residue characteristic of the most recent prime. while len(precomp) < 2: - P = deg_one_primes.next() + P = next(deg_one_primes) if not P.is_principal(): continue @@ -814,7 +814,7 @@ def _semistable_reducible_primes(E): # TODO: Is this the best value for this parameter? while True: - P = deg_one_primes.next() + P = next(deg_one_primes) if not P.is_principal(): continue @@ -899,7 +899,7 @@ def _possible_normalizers(E, SA): deg_one_primes = K.primes_of_degree_one_iter() while W.dimension() < V.dimension() - 1: - P = deg_one_primes.next() + P = next(deg_one_primes) k = P.residue_field() @@ -969,7 +969,7 @@ def _possible_normalizers(E, SA): # TODO: Is this the best value for this parameter? while True: - P = deg_one_primes.next() + P = next(deg_one_primes) k = P.residue_field() diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index 1e7c3a367db..ccb2dec2947 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -1079,11 +1079,11 @@ def ME(self): sage: E.discriminant()/E.minimal_model().discriminant() 4096 """ - from sage.misc.misc import prod + from sage.misc.all import prod if self.K is QQ: - return prod([p ** (e - self.E.local_data(p).discriminant_valuation()) for p, e in self.E.discriminant().factor()], QQ.one_element()) + return prod([p ** (e - self.E.local_data(p).discriminant_valuation()) for p, e in self.E.discriminant().factor()], QQ.one()) - ME = prod([p.norm() ** (e - self.E.local_data(p).discriminant_valuation()) for p, e in self.K.ideal(self.E.discriminant()).factor()], QQ.one_element()) + ME = prod([p.norm() ** (e - self.E.local_data(p).discriminant_valuation()) for p, e in self.K.ideal(self.E.discriminant()).factor()], QQ.one()) return ME.norm() def B(self, n, mu): diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 740ca9495d5..deabd080e3d 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -1486,7 +1486,7 @@ def bernardi_sigma_function(self, prec=20): Eh = E.formal() lo = Eh.log(prec + 5) - F = lo.reversion() + F = lo.reverse() S = LaurentSeriesRing(QQ,'z') z = S.gen() diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index 28f72fa64aa..2a41d87821c 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -112,6 +112,7 @@ from sage.schemes.elliptic_curves.constructor import EllipticCurve from sage.misc.cachefunc import cached_method + class PeriodLattice(FreeModule_generic_pid): """ The class for the period lattice of an algebraic variety. diff --git a/src/sage/schemes/generic/morphism.py b/src/sage/schemes/generic/morphism.py index 6e478efb7af..a648de431d9 100644 --- a/src/sage/schemes/generic/morphism.py +++ b/src/sage/schemes/generic/morphism.py @@ -1469,9 +1469,9 @@ def __iter__(self): sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: iter = a.__iter__() - sage: iter.next() + sage: next(iter) 1 - sage: iter.next() + sage: next(iter) 2 sage: list(a) [1, 2] diff --git a/src/sage/schemes/plane_curves/projective_curve.py b/src/sage/schemes/plane_curves/projective_curve.py index 52bf99cb7b7..f70ea35f73b 100644 --- a/src/sage/schemes/plane_curves/projective_curve.py +++ b/src/sage/schemes/plane_curves/projective_curve.py @@ -348,19 +348,19 @@ def rational_points_iterator(self): sage: P2. = ProjectiveSpace(F,2) sage: C = Curve(X*Y*Z) sage: a = C.rational_points_iterator() - sage: a.next() + sage: next(a) (1 : 0 : 0) - sage: a.next() + sage: next(a) (0 : 1 : 0) - sage: a.next() + sage: next(a) (1 : 1 : 0) - sage: a.next() + sage: next(a) (0 : 0 : 1) - sage: a.next() + sage: next(a) (1 : 0 : 1) - sage: a.next() + sage: next(a) (0 : 1 : 1) - sage: a.next() + sage: next(a) Traceback (most recent call last): ... StopIteration @@ -371,27 +371,27 @@ def rational_points_iterator(self): sage: P2. = ProjectiveSpace(F,2) sage: C = Curve(X^3+5*Y^2*Z-33*X*Y*X) sage: b = C.rational_points_iterator() - sage: b.next() + sage: next(b) (0 : 1 : 0) - sage: b.next() + sage: next(b) (0 : 0 : 1) - sage: b.next() + sage: next(b) (2*a + 2 : a : 1) - sage: b.next() + sage: next(b) (2 : a + 1 : 1) - sage: b.next() + sage: next(b) (a + 1 : 2*a + 1 : 1) - sage: b.next() + sage: next(b) (1 : 2 : 1) - sage: b.next() + sage: next(b) (2*a + 2 : 2*a : 1) - sage: b.next() + sage: next(b) (2 : 2*a + 2 : 1) - sage: b.next() + sage: next(b) (a + 1 : a + 2 : 1) - sage: b.next() + sage: next(b) (1 : 1 : 1) - sage: b.next() + sage: next(b) Traceback (most recent call last): ... StopIteration @@ -402,8 +402,8 @@ def rational_points_iterator(self): from sage.rings.polynomial.all import PolynomialRing R = PolynomialRing(K,'X') X = R.gen() - one = K.one_element() - zero = K.zero_element() + one = K.one() + zero = K.zero() # the point with Z = 0 = Y try: diff --git a/src/sage/schemes/product_projective/point.py b/src/sage/schemes/product_projective/point.py index 4cc836df21a..aab8288fb36 100644 --- a/src/sage/schemes/product_projective/point.py +++ b/src/sage/schemes/product_projective/point.py @@ -262,9 +262,9 @@ def __iter__(self): sage: T = ProductProjectiveSpaces([1,1],QQ,'x') sage: P = T([2,1,0,1]) sage: iter = P.__iter__() - sage: iter.next() + sage: next(iter) 2 - sage: iter.next() + sage: next(iter) 1 sage: list(P) [2, 1, 0, 1] diff --git a/src/sage/schemes/projective/endPN_automorphism_group.py b/src/sage/schemes/projective/endPN_automorphism_group.py new file mode 100644 index 00000000000..607fcbbbb3b --- /dev/null +++ b/src/sage/schemes/projective/endPN_automorphism_group.py @@ -0,0 +1,1805 @@ +r""" +Automorphism groups of endomorphisms of the projective line + +AUTHORS: + +- Xander Faber, Michelle Manes, Bianca Viray: algorithm and original code + "Computing Conjugating Sets and Automorphism Groups of Rational Functions" + by Xander Faber, Michelle Manes, and Bianca Viray [FMV] + +- Joao de Faria, Ben Hutz, Bianca Thompson (11-2013): adaption for inclusion in Sage + +""" + +#***************************************************************************** +# Copyright (C) 2012 +# +# 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/ +#***************************************************************************** + +from copy import copy +from sage.combinat.subset import Subsets +from sage.functions.all import sqrt +from itertools import permutations, combinations +from sage.matrix.constructor import matrix +from sage.matrix.matrix import is_Matrix +from sage.misc.functional import squarefree_part +from sage.misc.misc_c import prod +from sage.rings.arith import is_square, divisors +from sage.rings.finite_rings.constructor import GF +from sage.rings.finite_rings.integer_mod_ring import Integers +from sage.rings.fraction_field import FractionField +from sage.rings.integer_ring import ZZ +from sage.rings.number_field.number_field import NumberField +from sage.rings.arith import gcd, lcm, CRT +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.rational_field import QQ +from sage.sets.primes import Primes + +def automorphism_group_QQ_fixedpoints(rational_function, return_functions = False, iso_type=False): + r""" + + This function will compute the automorphism group for ``rational_function`` via the method of fixed points + + ALGORITHM: + + See Algorithm 3 in Faber-Manes-Viray [FMV] + + INPUT: + + - ``rational_function`` - Rational Function defined over `\mathbb{Z}` or `\mathbb{Q}` + + - ``return_functions`` - Boolean Value, True will return elements in the automorphism group + as linear fractional transformations. False will return elements as `PGL2` matrices. + + - ``iso_type`` - Boolean - True will cause the classification of the finite automorphism + group to also be returned + + OUTPUT: + + - List of automorphisms that make up the Automorphism Group + of ``rational_function``. + + EXAMPLES:: + + sage: F. = PolynomialRing(QQ) + sage: rational_function = (z^2 - 2*z - 2)/(-2*z^2 - 2*z + 1) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_QQ_fixedpoints + sage: automorphism_group_QQ_fixedpoints(rational_function, True) + [z, 2/(2*z), -z - 1, -2*z/(2*z + 2), (-z - 1)/z, -1/(z + 1)] + + :: + + sage: F. = PolynomialRing(QQ) + sage: rational_function = (z^2 + 2*z)/(-2*z - 1) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_QQ_fixedpoints + sage: automorphism_group_QQ_fixedpoints(rational_function) + [ + [1 0] [-1 -1] [-2 0] [0 2] [-1 -1] [ 0 -1] + [0 1], [ 0 1], [ 2 2], [2 0], [ 1 0], [ 1 1] + ] + + :: + + sage: F. = PolynomialRing(QQ) + sage: rational_function = (z^2 - 4*z -3)/(-3*z^2 - 2*z + 2) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_QQ_fixedpoints + sage: automorphism_group_QQ_fixedpoints(rational_function, True, True) + ([z, (-z - 1)/z, -1/(z + 1)], 'Cyclic of order 3') + """ + + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + F = R.base_ring() + + if F != QQ and F!= ZZ: + raise TypeError("Coefficient ring is not the rational numbers or the integers") + + z = R.gen(0) + phi = R.fraction_field()(rational_function) + + f = phi.numerator() + g = phi.denominator() + + #scale f,g so both have integer coefficients + N = lcm(f.denominator(),g.denominator()) + f = f*N + g = g*N + N = gcd(gcd(f.coefficients()), gcd(g.coefficients())) + f = f/N + g = g/N + + d = max(f.degree(), g.degree()) + + h = f - g*z + + if return_functions: + elements = [z] + else: + elements = [matrix(F, 2, [1,0,0,1])] + + rational_roots = h.roots(multiplicities = False) + + min_poly = 1 + + #check if infinity is a fixed point + if g.degree() < d: #then infinity is a fixed point + #find elements in W of the form (infinty, y) + #where W is the set of F-rational points (x,y) such that + #x is fixed by phi and phi(y)=x + for T in g.roots(multiplicities = False): + alpha = T + zeta = -1 + s = (zeta*z + alpha*(1 - zeta)) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(s) + else: + elements.append(matrix(F, 2, [zeta, alpha*(1-zeta), 0, 1])) + + for S in h.roots(): + min_poly = min_poly*(z - S[0])**(S[1]) + + if g.degree() < d: #then infinity is a fixed point so (infinity, S[0]) + alpha = S[0] # is in Z_(1,1)**2 + zeta = -1 + s = (zeta*z + alpha*(1 - zeta)) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(s) + else: + elements.append(matrix(F, 2, [zeta, alpha*(1-zeta), 0, 1])) + + #now compute points in W + preimage = f - g*S[0] + if preimage.degree() < d: #infinity is in W + zeta = -1 + alpha = S[0] + s = (zeta*z + alpha*(1 - zeta)) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(s) + else: + elements.append(matrix(F, 2, [zeta, alpha*(1-zeta), 0, 1])) + for T in preimage.roots(multiplicities = False): + if T != S[0]: + zeta = -1 + alpha = S[0] + beta = T + s = ( (alpha - zeta*beta)*z - (alpha*beta)*(1 - zeta))/((1 - zeta)*z + (alpha*zeta - beta)) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(s) + else: + elements.append(matrix(F, 2, + [(alpha - zeta*beta), - (alpha*beta)*(1 - zeta), + (1 - zeta), (alpha*zeta - beta)])) + + #first look at rational fixed points + #Subsets is ok since we just needed unordered pairs + for S in Subsets(rational_roots, 2): + zeta = -1 + alpha = S[0] + beta = S[1] + s = ( (alpha - zeta*beta)*z - (alpha*beta)*(1 - zeta))/((1 - zeta)*z + (alpha*zeta - beta)) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(s) + else: + elements.append(matrix(F, 2, + [(alpha - zeta*beta), - (alpha*beta)*(1 - zeta), + (1 - zeta), (alpha*zeta - beta)])) + + + #now consider 2-periodic points + psi = phi(phi(z)) + f2 = psi.numerator() + g2 = psi.denominator() + period2_points = [x for x in (f2 - z*g2).roots(multiplicities = False) if not x in rational_roots] + for S in Subsets(period2_points, 2): + zeta = -1 + alpha = S[0] + beta = S[1] + s = ( (alpha - zeta*beta)*z - (alpha*beta)*(1 - zeta))/((1 - zeta)*z + (alpha*zeta - beta)) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(s) + else: + elements.append(matrix(F, 2, + [(alpha - zeta*beta), - (alpha*beta)*(1 - zeta), + (1 - zeta), (alpha*zeta - beta)])) + if g2.degree() < f2.degree() and g.degree() == d: #infinity has period 2 + for alpha in period2_points: + zeta = -1 + s = (zeta*z + alpha*(1 - zeta)) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(s) + else: + elements.append(matrix(F, 2, [zeta, alpha*(1-zeta), 0, 1])) + factors = (f2 - z*g2).factor() + L1 = NumberField(z**2 + 1,'i') + i=L1.gen(0) + L2 = NumberField(z**2 + 3,'isqrt3') + isqrt3 = L2.gen(0) + for psi in factors: + if psi[0].degree() == 2: + a = psi[0][2] + b = psi[0][1] + c = psi[0][0] + disc = b**2 - 4*a*c + s = (-b*z - 2*c)/(2*a*z + b) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(K(s)) + else: + elements.append(matrix(F, 2, [-b,-2*c, 2*a, b])) + if is_square(-disc): #psi[0] generates Q(i) + alpha = psi[0].change_ring(L1).roots()[0][0] + beta = alpha.trace() - alpha + for zeta in [i, -i]: + a = (alpha - zeta*beta)/(1 - zeta) + d = (alpha*zeta - beta)/(1 - zeta) + if a in F and d in F: + a = F(a) + d = F(d) + b = F(-alpha*beta) + s = ( a*z + b)/(z + d) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(K(s)) + else: + elements.append(matrix(F, 2, [a,b, 1, d])) + elif is_square(-3*disc): #psi[0] generates Q(zeta_3) + alpha = psi[0].change_ring(L2).roots()[0][0] + beta = alpha.trace() - alpha + for zeta in [F(1)/F(2)*(1 + isqrt3), F(1)/F(2)*(1 - isqrt3),F(1)/F(2)*(-1 + isqrt3), F(1)/F(2)*(-1 - isqrt3)]: + a = (alpha - zeta*beta)/(1 - zeta) + d = (alpha*zeta - beta)/(1 - zeta) + if a in F and d in F: + a = F(a) + d = F(d) + b = F(-alpha*beta) + s = ( a*z + b)/(z + d) + if s(phi(z)) == phi(s(z)): + if return_functions: + elements.append(K(s)) + else: + elements.append(matrix(F, 2, [a,b, 1, d])) + + if iso_type: + return(elements, which_group(elements)) + return(elements) + +def height_bound(polynomial): + r""" + Compute the maximum height of the coefficients of an automorphism. This + sets the termination criteria for the Chinese Remainder Theorem step. + + Let `f` be a square-free polynomial with coefficients in `K` + Let `F` be an automorphism of `\mathbb{P}^1_{Frac(R)}` that permutes the roots of `f` + This function returns a bound on the height of `F`, + when viewed as an element of `\mathbb{P}^3` + + In [FMV] it is proven that `ht(F) <= 6^{[K:Q]}*M`, where `M` is the Mahler measure of `f` + M is bounded above by `H(f)`, so we return the floor of `6*H(f)` + (since `ht(F)` is an integer) + + INPUT: + + - ``polynomial`` -- a univariate polynomial + + OUTPUT: + + - a positive integer + + EXAMPLES:: + + sage: R. = PolynomialRing(QQ) + sage: f = (z^3+2*z+6) + sage: from sage.schemes.projective.endPN_automorphism_group import height_bound + sage: height_bound(f) + 413526 + """ + # first check that polynomial is over QQ or ZZ + K=polynomial.parent() + + if K.is_field(): + R = K.ring() + else: + R = K + F = R.base_ring() + + if F != QQ and F!= ZZ: + raise TypeError("coefficient ring is not the rational numbers or the integers!") + + # scale polynomial so that it has integer coefficients with gcd 1 + # this ensures that H(f) = H_infinity(f) + f = R(polynomial) + f = f*f.denominator() + f = f/(gcd(f.coefficients())) + + # compute the infinite height + L2norm_sq = sum([a**2 for a in f.coefficients()]) + + return (6*(L2norm_sq)**3) + +def PGL_repn(rational_function): + r""" + Take a linear fraction transformation and represent it as a 2x2 matrix. + + INPUT: + + - ``rational_function`` -- a linear fraction transformation + + OUTPUT: + + - a 2x2 matrix representing ``rational_function`` + + EXAMPLES:: + + sage: R. = PolynomialRing(QQ) + sage: f = ((2*z-1)/(3-z)) + sage: from sage.schemes.projective.endPN_automorphism_group import PGL_repn + sage: PGL_repn(f) + [ 2 -1] + [-1 3] + """ + if is_Matrix(rational_function): + return rational_function + K = rational_function.parent() + F = K.base_ring() + if not K.is_field(): + return matrix(F, 2, [rational_function[1], rational_function[0], 0, 1]) + else: + f = rational_function.numerator() + g = rational_function.denominator() + return matrix(F, 2, [f[1], f[0], g[1], g[0]]) + +def PGL_order(A): + r""" + Find the multiplicative order of a linear fractional transformation that + has a finite order as an element of `PGL_2(R)`. ``A`` can be represented + either as a rational function or a 2x2 matrix + + INPUT: + + - ``A`` -- a linear fractional transformation + + OUTPUT: + + - a positive integer + + EXAMPLES:: + + sage: M = matrix([[0,2],[2,0]]) + sage: from sage.schemes.projective.endPN_automorphism_group import PGL_order + sage: PGL_order(M) + 2 + + :: + + sage: R. = PolynomialRing(QQ) + sage: from sage.schemes.projective.endPN_automorphism_group import PGL_order + sage: PGL_order(-1/x) + 2 + """ + + n = 1 + AA = PGL_repn(A) + B = copy(AA) + while B[0][0] != B[1][1] or B[0][1] != 0 or B[1][0] != 0: + n = n + 1 + B = AA*B + + return n + +def CRT_helper(automorphisms, moduli): + r""" + Given a list of automorphisms over various `Zmod(p^k)` find a list + of automorphisms over `Zmod(M)` where `M=\prod p^k` that surjects + onto every tuple of automorphisms from the various `Zmod(p^k)`. + + INPUT: + + - ``automorphisms`` -- a list of lists of automorphisms over various `Zmod(p^k)` + + - ``moduli`` -- list of the various `p^k` + + OUTPUT: + + - a list of automorphisms over `Zmod(M)`. + + EXAMPLES:: + + sage: from sage.schemes.projective.endPN_automorphism_group import CRT_helper + sage: CRT_helper([[matrix([[4,0],[0,1]]), matrix([[0,1],[1,0]])]],[5]) + ([ + [4 0] [0 1] + [0 1], [1 0] + ], 5) + """ + if len(automorphisms) > 2: + temp, modulus = CRT_helper( + [automorphisms[i] for i in range(len(automorphisms)) if i != 0], + [moduli[i] for i in range(len(moduli)) if i != 0]) + elif len(automorphisms) == 2: + temp = automorphisms[1] + modulus = moduli[1] + else: + return automorphisms[0], moduli[0] + + autos = [] + for B in temp: + for C in automorphisms[0]: + A = matrix(Integers(modulus*moduli[0]), 2, + [CRT(B[0][0].lift(), C[0][0].lift(), modulus, moduli[0]), + CRT(B[0][1].lift(), C[0][1].lift(), modulus, moduli[0]), + CRT(B[1][0].lift(), C[1][0].lift(), modulus, moduli[0]), + CRT(B[1][1].lift(), C[1][1].lift(), modulus, moduli[0])]) + autos.append(A) + + return autos, modulus*moduli[0] + +def CRT_automorphisms(automorphisms, order_elts, degree, moduli): + r""" + Given a list of automorphisms over various `Zmod(p^k)`, a list of the + elements orders, an integer degree, and a list of the `p^k` values compute + a maximal list of automorphisms over `Zmod(M)`, such that for every `j` in `len(moduli)`, + each element reduces mod ``moduli[j]`` to one of the elements in `automorphisms[j]` that + has order = ``degree`` + + INPUT: + + - ``automorphisms`` -- a list of lists of automorphisms over various `Zmod(p^k)` + + - ``order_elts`` -- a list of lists of the orders of the elements of ``automorphisms`` + + - ``degree`` - a positive integer + + - ``moduli`` -- list of prime powers, i.e., `p^k` + + OUTPUT: + + - a list containing a list of automorphisms over `Zmod(M)` and the product of the moduli + + EXAMPLES:: + + sage: aut = [[matrix([[1,0],[0,1]]),matrix([[0,1],[1,0]])]] + sage: ords = [[1,2]] + sage: degree = 2 + sage: mods = [5] + sage: from sage.schemes.projective.endPN_automorphism_group import CRT_automorphisms + sage: CRT_automorphisms(aut,ords,degree,mods) + ([ + [0 1] + [1 0] + ], 5) + """ + # restrict to automorphisms of degree `degree` + degree_d_autos = [] + for j in range(len(automorphisms)): + L = automorphisms[j] + degree_d_autos.append( + [L[i] for i in range(len(L)) if order_elts[j][i] == degree]) + + # get list of CRT'ed automorphisms + return CRT_helper(degree_d_autos, moduli) + +def valid_automorphisms(automorphisms_CRT, rational_function, ht_bound, M, + return_functions = False): + r""" + Checks whether an element that is an automorphism of ``rational_function`` modulo `p^k` for various + `p` s and `k` s can be lifted to an automorphism over `ZZ`. It uses the fact that every + automorphism has height at most ``ht_bound`` + + INPUT: + + - ``automorphisms`` -- a list of lists of automorphisms over various `Zmod(p^k)` + + - ``rational_function`` -- A one variable rational function + + - ``ht_bound`` - a positive integer + + - ``M`` -- a positive integer, a product of prime powers + + - ``return_functions`` -- Boolean. default: False (optional) + + OUTPUT: + + - a list of automorphisms over `ZZ`. + + EXAMPLES:: + + sage: R. = PolynomialRing(QQ) + sage: F = z^2 + sage: from sage.schemes.projective.endPN_automorphism_group import valid_automorphisms + sage: valid_automorphisms([matrix(GF(5),[[0,1],[1,0]])], F, 48, 5, True) + [1/z] + """ + z = rational_function.parent().gen(0) + valid_auto = [] + + for A in automorphisms_CRT: + init_lift = [x.lift() for x in A.list()] # lift coefficients of A + # multiply lift by appropriate scalar matrices and adjust (mod M) + # to find an element of minimal height. These will have + # coefficients in [-M/2, M/2) + for scalar in [y for y in xrange(1, M) if gcd(y,M) == 1]: + new_lift = [scalar*x - (scalar*x/M).round()*M for x in init_lift] + g = gcd(new_lift) + new_lift = [x // g for x in new_lift] + if all([abs(x) <= ht_bound for x in new_lift]): + a,b,c,d = new_lift + f = (a*z + b) / (c*z + d) + if rational_function(f(z)) == f(rational_function(z)): + if return_functions: + valid_auto.append(f) + else: + valid_auto.append(matrix(ZZ,2,2,new_lift)) + break + + return valid_auto + +def remove_redundant_automorphisms(automorphisms, order_elts, moduli,integral_autos): + r""" + If an element of Aut_{F_p} has been lifted to `QQ` + remove that element from `Aut_{F_p}` so we don't + attempt to lift that element again unnecessarily + + INPUT: + + - ``automorphisms`` -- a list of lists of automorphisms + + - ``order_elts`` -- a list of lists of the orders of the elements of ``automorphisms`` + + - ``moduli`` -- a list of prime powers + + - ``integral_autos`` -- list of known automorphisms + + OUTPUT: + + - a list of automorphisms. + + EXAMPLES:: + + sage: auts = [[matrix([[1,0],[0,1]]), matrix([[6,0],[0,1]]), matrix([[0,1],[1,0]]), + ....: matrix([[6,1],[1,1]]), matrix([[1,1],[1,6]]), matrix([[0,6],[1,0]]), + ....: matrix([[1,6],[1,1]]), matrix([[6,6],[1,6]])]] + sage: ord_elts = [[1, 2, 2, 2, 2, 2, 4, 4]] + sage: mods = [7] + sage: R. = PolynomialRing(QQ) + sage: int_auts = [-1/x] + sage: from sage.schemes.projective.endPN_automorphism_group import remove_redundant_automorphisms + sage: remove_redundant_automorphisms(auts, ord_elts, mods, int_auts) + [[ + [1 0] [6 0] [0 1] [6 1] [1 1] [1 6] [6 6] + [0 1], [0 1], [1 0], [1 1], [1 6], [1 1], [1 6] + ]] + """ + to_del = [] + + for i in range(len(automorphisms)): + p = moduli[i] + to_del_temp = [] + for psi in integral_autos: + #The return_functions boolean determines if the automorphisms + #are matricies or linear fractional transformations + if is_Matrix(psi): + ppsi=psi.change_ring(GF(p)) + B=[ppsi[0,0],ppsi[0,1],ppsi[1,0],psi[1,1]] + else: + ff = psi.numerator().change_ring(GF(p)) + gg = psi.denominator().change_ring(GF(p)) + B = [ff[1],ff[0],gg[1],gg[0]] + for j in range(len(automorphisms[i])): + A = automorphisms[i][j] + M = matrix(GF(p), [B, [A[0][0], A[0][1], A[1][0], A[1][1]]]) + if M.rank() == 1: + to_del_temp.append(j) + break + to_del.append(to_del_temp) + + for i in range(len(to_del)): + to_del[i].sort() + to_del[i].reverse() + for j in to_del[i]: + del automorphisms[i][j] + del order_elts[i][j] + + return(automorphisms) + +def automorphism_group_QQ_CRT(rational_function, prime_lower_bound = 4, return_functions = True, iso_type=False): + r""" + Determines the complete group of rational automorphisms (under the conjugation action + of `PGL(2,QQ)`) for a rational function of one variable, see [FMV] for details. + + INPUT: + + - ``rational_function`` - a rational function of a univariate polynomial ring over `QQ` + + - prime_lower_bound`` -- a positive integer - a lower bound for the primes to use for + the Chinese Remainder Theorem step. default: 4 (optional) + + - ``return_functions`` -- Boolean - True returns linear fractional transformations + False returns elements of `PGL(2,QQ)` default: True (optional). + + - ``iso_type`` -- Boolean - True returns the isomorphism type of the automorphism group. + default: False (optional) + + OUTPUT: + + - a complete list of automorphisms of `rational_function` + + EXAMPLES:: + + sage: R. = PolynomialRing(QQ) + sage: f = (3*z^2 - 1)/(z^3 - 3*z) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_QQ_CRT + sage: automorphism_group_QQ_CRT(f, 4,True) + [z, -z, 1/z, -1/z, (-z + 1)/(z + 1), (z + 1)/(z - 1), (z - 1)/(z + 1), + (-z - 1)/(z - 1)] + + :: + + sage: R. = PolynomialRing(QQ) + sage: f = (3*z^2 - 1)/(z^3 - 3*z) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_QQ_CRT + sage: automorphism_group_QQ_CRT(f, 4,False) + [ + [1 0] [-1 0] [0 1] [ 0 -1] [-1 1] [ 1 1] [ 1 -1] [-1 -1] + [0 1], [ 0 1], [1 0], [ 1 0], [ 1 1], [ 1 -1], [ 1 1], [ 1 -1] + ] + """ + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + F = R.base_ring() + + if F != QQ and F!= ZZ: + raise TypeError("coefficient ring is not the rational numbers or the integers!") + + z = R.gen(0) + phi = K(rational_function) + + f = phi.numerator() + g = phi.denominator() + + #scale f,g so both have integer coefficients + N = lcm(f.denominator(),g.denominator()) + f = f*N + g = g*N + N = gcd(gcd(f.coefficients()), gcd(g.coefficients())) + f = f/N + g = g/N + + d = max(f.degree(), g.degree()) + + if d == 1: + raise ValueError("rational function has degree 1") + + #badprimes is an integer divisible by every prime p such that either + # 1) phi has bad reduction at p or + # 2) the reduction map fails to be injective + badprimes = (gcd(f[d],g[d])*f.resultant(g)*6) + #6 is because over Q, Aut(phi) has order dividing 12 + #when generalizing to a number field K, 6 should be replaced with + # 2*gcd(2*[K:Q] + 1, d^3 - d) + + #Determining the set that is used to obtain the height bound + h = R(prod(x[0] for x in (R(f - g*z)).factor()))# take minimal polynomial of fixed points + if h.degree() == 2: #if there are only 2 finite fixed points, take preimage of fixed points + h = h[2]*f**2 + h[1]*f*g + h[0]*g**2 + elif h.degree() == 1: #if there is just 1 finite fixed point, take preimages under phi^2 + psi = phi(phi(z)) + f2 = psi.numerator() + g2 = psi.denominator() + N = lcm(f2.denominator(),g2.denominator()) + f2 = f2*N + g2 = g2*N + N = gcd(gcd(f2.coefficients()), gcd(g2.coefficients())) + f2 = f2/N + g2 = g2/N + h = h[1]*f2 + h[0]*g2 + + MaxH = height_bound(h) + congruence = 1 + primes = Primes(); + p = primes.next(ZZ(prime_lower_bound)) + primepowers = [] + automorphisms = [] + orderaut = [] + orderelts = [] + + if return_functions: + elements = [z] + else: + elements = [matrix(ZZ, 2, [1,0,0,1])] + + badorders = [1, 12]# order 12 not possible over Q, even though 4 and 6 are + + #over QQ, elts of PGL_2 of finite order can only have order dividing 6 or 4, + # and the finite subgroups can only be cyclic or dihedral (Beauville) so + # the only possible groups are C_n, D_2n for n|6 or n|4 + # all of these groups have order dividing 24 + while (congruence < (2*MaxH**2)) and len(elements) < gcd(orderaut + [24]): + if badprimes%p != 0: #prime of good reduction + # compute automorphisms mod p + phi_p = f.change_ring(GF(p))/g.change_ring(GF(p)) + sorted_automorphisms = automorphism_group_FF(phi_p) + sorted_automorphisms.sort(key = PGL_order) + orders = [PGL_order(A) for A in sorted_automorphisms] + + automorphisms.append(sorted_automorphisms) + orderaut.append(len(automorphisms[-1])) + orderelts.append(orders) + primepowers.append(p) + + # check if we already found 8 or 12 automorphisms + # and the gcd of orders over Fp and 24 is 24 + # or if the gcd is equal to the the number of automorphisms we have + if (len(elements) == gcd(orderaut + [24])) or \ + (gcd(orderaut + [24]) == 24 and \ + (len(elements) == 12 or len(elements) == 8)): + if iso_type: + return(elements, which_group(elements)) + return elements + else: + N = gcd(orderaut + [12]) #all orders of elements divide N + for order in [O for O in divisors(N) \ + if not O in badorders]: #range over all orders + # that are possible over QQ such that we haven't already + # found all elements of that order + + # First count number of elements of particular order + numeltsoffixedorder = [] + for L in orderelts: + numeltsoffixedorder.append(L.count(order)) + numelts = min(numeltsoffixedorder) + # Have some elts of fixed order mod p for each p + if numelts != 0: + #CRT order d elements together and check if + # they are an automorphism + autos, M = CRT_automorphisms(automorphisms, + orderelts, order, primepowers) + temp = valid_automorphisms(autos, phi, MaxH, M, + return_functions) + elements.extend(temp) + + if (len(elements) == gcd(orderaut + [24])): + #found enough automorphisms + if iso_type: + return(elements, which_group(elements)) + return elements + elif numelts <= (len(temp)): + badorders.append(order) + # found all elements of order 'order; + elif len(temp) != 0: + # found some elements of order 'order' + # if an element of Aut_{F_p} has been lifted to QQ + # remove that element from Aut_{F_p} so we don't + # attempt to lift that element again unecessarily + automorphisms=remove_redundant_automorphisms(automorphisms, + orderelts, primepowers, temp) + if order == 4: #have some elements of order 4 + # so possible aut group is Z/4 or D_4 + badorders.extend([3, 6]) + elif order == 3 or order == 6:#have some elements of + # order 3 or 6 so possible aut groups are Z/3, + # D_3, Z/6, or D_6 + badorders.append(4) + else: #no elements of order d in some F_v + for m in divisors(N): + if m%order == 0: + badorders.append(m) + #no elements of that order or any order that + # is a multiple of it + if len([order for order in divisors(N) \ + if not order in badorders]) == 0: + #found all elements of every possible order + if iso_type: + return(elements, which_group(elements)) + return elements + congruence = congruence*p + + p = primes.next(p) + + if iso_type: + return(elements, which_group(elements)) + return(elements) + +def automorphism_group_FF(rational_function, absolute=False, iso_type=False, return_functions=False): + r""" + This function computes automorphism groups over finite fields. + + ALGORITHM: + + See Algorithm 4 in Faber-Manes-Viray [FMV] + + INPUT: + + - ``rational_function`` -- a rational function defined over the fraction field + of a polynomial ring in one variable with finite field coefficients. + + - ``absolute``-- Boolean - True returns the absolute automorphism group and a field of definition. + default: False (optional) + + - ``iso_type`` -- Boolean - True returns the isomorphism type of the automorphism group. + default: False (optional) + + - ``return_functions`` -- Boolean, True returns linear fractional transformations + False returns elements of `PGL(2)`. default: False (optional) + + OUTPUT: + + - List of automorphisms of ``rational_function`` + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(5^2, 't')) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_FF + sage: automorphism_group_FF((x^2+x+1)/(x+1)) + [ + [1 0] [4 3] + [0 1], [0 1] + ] + + :: + + sage: R. = PolynomialRing(GF(2^5, 't')) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_FF + sage: automorphism_group_FF(x^(5), True, False, True) + [Univariate Polynomial Ring in w over Finite Field in b of size 2^5, [w, 1/w]] + + :: + + sage: R. = PolynomialRing(GF(2^5, 't')) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_FF + sage: automorphism_group_FF(x^(5), False, False, True) + [x, 1/x] + """ + + if absolute==False: + G = automorphism_group_FF_alg3(rational_function) + else: + G = automorphism_group_FF_alg2(rational_function) + + if not return_functions: + if absolute: + R=G[1][0].parent() + if R.is_field(): + R = R.ring() + G[1] = [matrix(R.base_ring(),[[R(g.numerator())[1],R(g.numerator())[0]],[R(g.denominator())[1],R(g.denominator())[0]]]) for g in G[1]] + else: + R=G[0].parent() + if R.is_field(): + R = R.ring() + G = [matrix(R.base_ring(),[[R(g.numerator())[1],R(g.numerator())[0]],[R(g.denominator())[1],R(g.denominator())[0]]]) for g in G] + + if iso_type == False: + return G + elif absolute == False: + return G, which_group(G) + else: + return G, which_group(G[1]) + +def field_descent(sigma, y): + r""" + Function for descending an element in a field E to a subfield F. + Here F, E must be finite fields or number fields. This function determines + the unique image of subfield which is ``y`` by the embedding ``sigma`` if it exists. + Otherwise returns ``None``. + This functionality is necessary because Sage does not keep track of subfields. + + INPUT: + + - ``sigma``-- an embedding sigma: `F` -> `E` of fields. + + - ``y`` --an element of the field `E` + + OUTPUT: + + - the unique element of the subfield if it exists, otherwise ``None`` + + EXAMPLE:: + + sage: R = GF(11^2,'b') + sage: RR = GF(11) + sage: s = RR.Hom(R)[0] + sage: from sage.schemes.projective.endPN_automorphism_group import field_descent + sage: field_descent(s, R(1)) + 1 + """ + F = sigma.domain() + a = F.gen() + + p = F.characteristic() + r = F.degree() + if p != 0 and y**(p**r) != y: + return + + K = F.prime_subfield() + R = PolynomialRing(K,'X') + f = R(sigma(a).polynomial().coefficients(sparse=False)) + g = R(y.polynomial().coefficients(sparse=False)) + + x = F(0) + quotient, remainder = g.quo_rem(f) + if not remainder.is_constant(): + return + else: + x = x+ F(remainder) + + steps = 1 + while not quotient.is_constant(): + quotient, remainder = quotient.quo_rem(f) + if not remainder.is_constant(): + return + else: + x = x+ F(remainder)*a**(steps) + steps += 1 + + return x + F(quotient)*a**(steps) + +def rational_function_coefficient_descent(rational_function, sigma, poly_ring): + r""" + Function for descending the coefficients of a rational function from field `E` + to a subfield `F`. Here `F`, `E` must be finite fields or number fields. + It determines the unique rational function in fraction field of + ``poly_ring`` which is the image of ``rational_function`` by ``ssigma``, + if it exists, and otherwise returns ``None``. + + INPUT: + + - ``rational_function``--a rational function with coefficients in a field `E`, + + - ``sigma``-- a field embedding sigma: `F` -> `E`. + + - ``poly_ring``-- a polynomial ring `R` with coefficients in `F`. + + OUTPUT: + + - a rational function with coefficients in the fraction field of ``poly_ring`` + if it exists, and otherwise ``None``. + + EXAMPLES:: + + sage: T. = PolynomialRing(GF(11^2,'b')) + sage: S. = PolynomialRing(GF(11)) + sage: s = S.base_ring().hom(T.base_ring()) + sage: f = (3*z^3 - z^2)/(z-1) + sage: from sage.schemes.projective.endPN_automorphism_group import rational_function_coefficient_descent + sage: rational_function_coefficient_descent(f,s,S) + (3*y^3 + 10*y^2)/(y + 10) + """ + + if rational_function.parent().is_field(): + S = rational_function.parent().ring() + else: + S = rational_function.parent() + + if rational_function == S(0): + return poly_ring(0) + + num=S(rational_function.numerator()) + denom=S(rational_function.denominator()) + f = num.coefficients() + fe = num.exponents() + g = denom.coefficients() + ge = denom.exponents() + #force the cancellation of common coefficient factors by scaling by f[-1] + ff = [ field_descent(sigma, x/f[-1]) for x in f] + gg = [ field_descent(sigma, x/f[-1]) for x in g] + if None in ff or None in gg: + return + + z = poly_ring.gen(0) + numer = sum( poly_ring(ff[i])*z**fe[i] for i in range(len(ff)) ) + denom = sum( poly_ring(gg[i])*z**ge[i] for i in range(len(gg)) ) + return numer / denom + +def rational_function_coerce(rational_function, sigma, S_polys): + r""" + Function for coercing a rational function defined over a ring `R` to have + coefficients in a second ring ``S_polys``. The fraction field of polynomial ring + ``S_polys`` will contain the new rational function. + + INPUT: + + - ``rational_funtion``-- rational function with coefficients in `R`. + + - ``sigma`` -- a ring homomorphism sigma: `R` -> ``S_polys``. + + - ``S_polys`` -- a polynomial ring. + + OUTPUT: + + - a rational function with coefficients in ``S_polys``. + + EXAMPLES:: + + sage: R. = PolynomialRing(QQ) + sage: S. = PolynomialRing(ZZ) + sage: s = S.hom([z],R) + sage: f = (3*z^2 + 1)/(z^3-1) + sage: from sage.schemes.projective.endPN_automorphism_group import rational_function_coerce + sage: rational_function_coerce(f,s,R) + (3*y^2 + 1)/(y^3 - 1) + """ + if rational_function.parent().is_field(): + R = rational_function.parent().ring() + else: + R = rational_function.parent() + + f = R(rational_function.numerator()).coefficients(sparse=False) + g = R(rational_function.denominator()).coefficients(sparse=False) + + if g == [R(1)]: + return S_polys([sigma(a) for a in f]) # allows for coercion of polynomials + else: + return S_polys([sigma(a) for a in f]) / S_polys([sigma(b) for b in g]) + +def rational_function_reduce(rational_function): + r""" + Force Sage to divide out common factors in numerator and denominator + of rational function. + + INPUT: + + - ``rational_function`` -- rational function `= F/G` in univariate polynomial ring. + + OUTPUT: + + - rational function -- `(F/gcd(F,G) ) / (G/gcd(F,G))`. + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(7)) + sage: f = ((z-1)*(z^2+z+1))/((z-1)*(z^3+1)) + sage: from sage.schemes.projective.endPN_automorphism_group import rational_function_reduce + sage: rational_function_reduce(f) + (z^2 + z + 1)/(z^3 + 1) + """ + phi = rational_function + F = phi.numerator() + G = phi.denominator() + comm_factor = gcd(F,G) + return (F.quo_rem(comm_factor)[0]) / (G.quo_rem(comm_factor)[0]) + +def three_stable_points(rational_function, invariant_list): + r""" + Implementation of Algorithm 1 for automorphism groups from + Faber-Manes-Viray [FMV]. + + INPUT: + + - ``rational_function``--rational function `phi` defined over finite + field `E`. + + - ``invariant_list``-- a list of at least `3` points of `\mathbb{P}^1(E)` that + is stable under `Aut_{phi}(E)`. + + OUTPUT: + + - list of automorphisms + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(5^2,'t')) + sage: f = z^3 + sage: L = [[0,1],[4,1],[1,1],[1,0]] + sage: from sage.schemes.projective.endPN_automorphism_group import three_stable_points + sage: three_stable_points(f,L) + [z, 4*z, 2/(2*z), 3/(2*z)] + """ + # define ground field and ambient function field + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + z = R.gen(0) + phi = K(rational_function) + + T = invariant_list + + automorphisms = [] + for t in permutations(range(len(T)),3): + a = (T[0][0]*T[1][1]*T[2][1]*T[t[0]][0]*T[t[1]][0]*T[t[2]][1] - + T[0][0]*T[1][1]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0] - + T[0][1]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][0]*T[t[2]][1] + + T[0][1]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0] + + T[0][1]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0] - + T[0][1]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0]) + + b = (T[0][0]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0] - + T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0] - + T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][0] *T[t[2]][1] + + T[0][0]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0] + + T[0][1]*T[1][0]*T[2][0]*T[t[0]][0]*T[t[1]][0]*T[t[2]][1] - + T[0][1]*T[1][0]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0]) + + c = (T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] - + T[0][1]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] + + T[0][1]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] + + T[0][1]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] - + T[0][1]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][0]*T[t[2]][1]) + + d = (T[0][0]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] - + T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] + + T[0][0]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] + + T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0]) + + if a*d - b*c != 0: + s = K(a*z + b) / K(c*z + d) + if s(phi(z)) == phi(s(z)) and s not in automorphisms: + automorphisms.append(s) + return automorphisms + +def automorphism_group_FF_alg2(rational_function): + r""" + Implementation of algorithm for determining the absolute automorphism + group over a finite field, given an invariant set., see [FMV]. + + INPUT: + + - ``rational_function``--a rational function defined over a finite field. + + OUTPUT: + + - absolute automorphism group of ``rational_function`` and a ring of definition. + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(7^2,'t')) + sage: f = (3*z^3 - z^2)/(z-1) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_FF_alg2 + sage: automorphism_group_FF_alg2(f) + [Univariate Polynomial Ring in w over Finite Field in b of size 7^2, [w, (3*b + 2)/((2*b + 6)*w)]] + + :: + + sage: R. = PolynomialRing(GF(5^3,'t')) + sage: f = (3456*z^(4)) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_FF_alg2 + sage: automorphism_group_FF_alg2(f) + [Univariate Polynomial Ring in w over Finite Field in b of size 5^6, [w, + (3*b^5 + 4*b^4 + 3*b^2 + 2*b + 1)*w, (2*b^5 + b^4 + 2*b^2 + 3*b + 3)*w, + (3*b^5 + 4*b^4 + 3*b^2 + 2*b)/((3*b^5 + 4*b^4 + 3*b^2 + 2*b)*w), (4*b^5 + + 2*b^4 + 4*b^2 + b + 2)/((3*b^5 + 4*b^4 + 3*b^2 + 2*b)*w), (3*b^5 + + 4*b^4 + 3*b^2 + 2*b + 3)/((3*b^5 + 4*b^4 + 3*b^2 + 2*b)*w)]] + """ + # define ground field and ambient function field + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + F = R.base_ring() + if not F.is_finite() or not F.is_field(): + raise TypeError("Coefficient ring is not a finite field.") + p = F.characteristic() + z = R.gen(0) + phi = K(rational_function) + f = phi.numerator() + g = phi.denominator() + D = max(f.degree(), g.degree()) + + # Build an invariant set for phi + fix = f(z) - z*g(z) + factor_list = fix.factor() + minimal_fix_poly = R(prod(x[0] for x in factor_list)) + n = sum(x[0].degree() for x in factor_list) + bool(fix.degree() < D+1) + + if n >= 3: + T_poly = minimal_fix_poly + infinity_check = bool(fix.degree() < D+1) + elif n == 2: + # Infinity is a fixed point + if bool(fix.degree() < D+1): + y = fix.roots(multiplicities=False)[0] + preimage = g*(f(z) - y*g(z)) + infinity_check = 1 + # Infinity is not a fixed point + else: + C = minimal_fix_poly.coefficients(sparse=False) + preimage = C[2]*f(z)**2 + C[1]*f(z)*g(z) + C[0]*g(z)**2 + infinity_check = bool(preimage.degree() < 2*D) + + T_poly = R(prod(x[0] for x in preimage.factor())) + + else: #case n=1 + # Infinity is the fixed point + if bool(fix.degree() < D+1): + minimal_preimage = R(prod(x[0] for x in g.factor())) + if minimal_preimage.degree() + 1 >= 3: + T_poly = minimal_preimage + infinity_check = 1 + else: + T_poly = R(prod(x[0] for x in phi(phi(z)).denominator().factor() ) ) + infinity_check = 1 + + # Infinity is not a fixed point + else: + y = fix.roots(multiplicities=False)[0] + preimage = R(f(z) - y*g(z)) + minimal_preimage = R(prod(x[0] for x in preimage.factor())) + if minimal_preimage.degree() + bool(preimage.degree()= 3: + T_poly = minimal_preimage + infinity_check = bool(preimage.degree() = PolynomialRing(GF(11)) + sage: f = x^11 + sage: L = [[[0, 1], [], 1], [[10, 1], [], 1], [[9, 1], [], 1], + ....: [[8, 1], [],1], [[7, 1], [], 1], [[6, 1], [], 1], [[5, 1], [], 1], + ....: [[4, 1], [], 1],[[3, 1], [], 1], [[2, 1], [], 1], [[1, 1], [], 1], + ....: [[1, 0], [], 1]] + sage: from sage.schemes.projective.endPN_automorphism_group import order_p_automorphisms + sage: order_p_automorphisms(f,L) + [x/(x + 1), 6*x/(x + 6), 3*x/(x + 3), 7*x/(x + 7), 9*x/(x + 9), 10*x/(x + + 10), 5*x/(x + 5), 8*x/(x + 8), 4*x/(x + 4), 2*x/(x + 2), 10/(x + 2), + (5*x + 10)/(x + 7), (2*x + 10)/(x + 4), (6*x + 10)/(x + 8), (8*x + + 10)/(x + 10), (9*x + 10)/x, (4*x + 10)/(x + 6), (7*x + 10)/(x + 9), (3*x + + 10)/(x + 5), (x + 10)/(x + 3), (10*x + 7)/(x + 3), (4*x + 7)/(x + 8), + (x + 7)/(x + 5), (5*x + 7)/(x + 9), (7*x + 7)/x, (8*x + 7)/(x + 1), (3*x + + 7)/(x + 7), (6*x + 7)/(x + 10), (2*x + 7)/(x + 6), 7/(x + 4), (9*x + + 2)/(x + 4), (3*x + 2)/(x + 9), 2/(x + 6), (4*x + 2)/(x + 10), (6*x + + 2)/(x + 1), (7*x + 2)/(x + 2), (2*x + 2)/(x + 8), (5*x + 2)/x, (x + + 2)/(x + 7), (10*x + 2)/(x + 5), (8*x + 6)/(x + 5), (2*x + 6)/(x + 10), + (10*x + 6)/(x + 7), (3*x + 6)/x, (5*x + 6)/(x + 2), (6*x + 6)/(x + 3), + (x + 6)/(x + 9), (4*x + 6)/(x + 1), 6/(x + 8), (9*x + 6)/(x + 6), (7*x + + 8)/(x + 6), (x + 8)/x, (9*x + 8)/(x + 8), (2*x + 8)/(x + 1), (4*x + + 8)/(x + 3), (5*x + 8)/(x + 4), 8/(x + 10), (3*x + 8)/(x + 2), (10*x + + 8)/(x + 9), (8*x + 8)/(x + 7), (6*x + 8)/(x + 7), 8/(x + 1), (8*x + + 8)/(x + 9), (x + 8)/(x + 2), (3*x + 8)/(x + 4), (4*x + 8)/(x + 5), (10*x + + 8)/x, (2*x + 8)/(x + 3), (9*x + 8)/(x + 10), (7*x + 8)/(x + 8), (5*x + + 6)/(x + 8), (10*x + 6)/(x + 2), (7*x + 6)/(x + 10), 6/(x + 3), (2*x + + 6)/(x + 5), (3*x + 6)/(x + 6), (9*x + 6)/(x + 1), (x + 6)/(x + 4), (8*x + + 6)/x, (6*x + 6)/(x + 9), (4*x + 2)/(x + 9), (9*x + 2)/(x + 3), (6*x + + 2)/x, (10*x + 2)/(x + 4), (x + 2)/(x + 6), (2*x + 2)/(x + 7), (8*x + + 2)/(x + 2), 2/(x + 5), (7*x + 2)/(x + 1), (5*x + 2)/(x + 10), (3*x + + 7)/(x + 10), (8*x + 7)/(x + 4), (5*x + 7)/(x + 1), (9*x + 7)/(x + 5), + 7/(x + 7), (x + 7)/(x + 8), (7*x + 7)/(x + 3), (10*x + 7)/(x + 6), (6*x + + 7)/(x + 2), (4*x + 7)/x, (2*x + 10)/x, (7*x + 10)/(x + 5), (4*x + + 10)/(x + 2), (8*x + 10)/(x + 6), (10*x + 10)/(x + 8), 10/(x + 9), (6*x + + 10)/(x + 4), (9*x + 10)/(x + 7), (5*x + 10)/(x + 3), (3*x + 10)/(x + 1), + x + 1, x + 2, x + 4, x + 8, x + 5, x + 10, x + 9, x + 7, x + 3, x + 6] + """ + # define ground field and ambient function field + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + z = R.gen(0) + phi = K(rational_function) + F = R.base_ring() + q = F.cardinality() + p = F.characteristic() + r = (q-1) / (p-1) # index of F_p^\times inside F^\times + + # Compute the threshold r2 for determining which algorithm to use + if len(pre_image) > 1: + r2 = len(pre_image) + case = 'fix' + elif len(pre_image[0][1]) > 0: + r2 = len(pre_image[0][1]) + case = 'F-pre_images' + else: + factor_list = pre_image[0][2].factor() + minimal_fix_poly = R(prod(x[0] for x in factor_list)) + r2 = sum(x[0].degree() for x in factor_list) + # Note that infinity is F-rational, so covered by preceding case + case = 'all pre_images' + + automorphisms_p = [] + + if r2 >= r or r2 == 0: + # Note that r2 == 0 corresponds to having a unique F-rational fixed point + # that is totally ramified + + for guy in pre_image: + pt = guy[0] + zeta = F.multiplicative_generator() + alpha = zeta**r + + if pt == [F(1),F(0)]: + for j in range(r): + s = z + zeta**j + if s(phi(z)) == phi(s(z)): + for i in range(p-1): + automorphisms_p.append(z+alpha**i*zeta**j) + + else: + u = F(1) / (z - pt[0]) + u_inv = pt[0] + F(1)/z + for j in range(r): + s = u_inv( u(z) + zeta**j ) + if s(phi(z)) == phi(s(z)): + for i in range(p-1): + automorphisms_p.append(u_inv( u(z) + alpha**i*zeta**j) ) + + elif r2 < r: + + if case=='fix': + T = [x[0] for x in pre_image] + elif case == 'F-pre_images': + T = [x for x in pre_image[0][1]] + else: + T = [] + + # loop over all F-rational pre-images + for guy in pre_image: + pt = guy[0] + # treat case of multiple F-rational fixed points or + # 1 F-rational fixed point with F-rational pre-images + if T != []: + M = [t for t in T if t != pt] + m = len(M) + if pt == [F(1),F(0)]: + for i in range(1, m): + s = z + M[i][0] - M[0][0] + if s(phi(z)) == phi(s(z)): + automorphisms_p.append(s) + else: + u = F(1) / (z - pt[0]) + u_inv = pt[0] + F(1)/z + for i in range(1,m): + if M[0] == [F(1),F(0)]: uy1 = 0 + else: uy1 = u(M[0][0]) + if M[i] == [F(1),F(0)]: uy2 = 0 + else: uy2 = u(M[i][0]) + s = u_inv( u(z) + uy2 - uy1 ) + if s(phi(z)) == phi(s(z)): + automorphisms_p.append(s) + elif T==[]: + # create the extension field generated by pre-images of the unique fixed point + T_poly = pre_image[0][2] + e = lcm([x[0].degree() for x in T_poly.factor()])*F.degree() + E = GF(p**e, 'b') + b = E.gen(0) + sigma = F.Hom(E)[0] + S = PolynomialRing(E,'w') + w = S.gen(0) + E_poly = rational_function_coerce(T_poly, sigma, S) + # List of roots permuted by elements of order p + # Since infinity is F-rational, it won't appear in this list + T = [ [alpha, E(1)] for alpha in E_poly.roots(ring=E, multiplicities=False)] + + # coerce the rational function and fixed point into E + Phi = rational_function_coerce(phi, sigma, S) + Pt = [sigma(pt[0]), sigma(pt[1])] + + m = len(T) + if Pt == [E(1),E(0)]: + for i in range(1, m): + s = w + T[i][0] - T[0][0] + if s(Phi(w)) == Phi(s(w)): + automorphisms_p.append(rational_function_coefficient_descent(s, sigma, R)) + else: + u = E(1) / (w - Pt[0]) + u_inv = Pt[0] + E(1)/w + for i in range(1,m): + uy1 = u(T[0][0]) + uy2 = u(T[i][0]) + s = u_inv( u(w) + uy2 - uy1 ) + if s(Phi(w)) == Phi(s(w)): + s = rational_function_reduce(s) + automorphisms_p.append(rational_function_coefficient_descent(s,sigma,R)) + + return automorphisms_p + +def automorphisms_fixing_pair(rational_function, pair, quad): + r""" + INPUT: + + - ``rational_function``-- rational function defined over finite field `E`. + + - ``pair``-- a pair of points of `\mathbb{P}^1(E)`. + + - ``quad``-- Boolean: an indicator if this is a quadratic pair of points + + OUTPUT: + + - set of automorphisms with order prime to characteristic defined over `E` that fix + the pair, excluding the identity. + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(7^2,'t')) + sage: f = (z^2 + 5*z + 5)/(5*z^2 + 5*z + 1) + sage: L = [[4, 1], [2, 1]] + sage: from sage.schemes.projective.endPN_automorphism_group import automorphisms_fixing_pair + sage: automorphisms_fixing_pair(f,L,False) + [(6*z + 6)/z, 4/(3*z + 3)] + """ + # define ground field and ambient function field + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + z = R.gen(0) + phi = K(rational_function) + E = R.base_ring() + f = phi.numerator() + g = phi.denominator() + D = max(f.degree(), g.degree()) + + #assumes the second coordiante of the point is 1 + if pair[0] == [1,0]: + u = K(z - pair[1][0]) + u_inv = K(z + pair[1][0]) + elif pair[1] == [1,0]: + u = K(E(1) / (z - pair[0][0])) + u_inv = K( (pair[0][0]*z + 1) / z ) + else: + u = K( (z - pair[1][0]) / (z - pair[0][0]) ) + u_inv = K( (pair[0][0]*z - pair[1][0] ) / (z - 1) ) + + automorphisms_prime_to_p = [] + # Quadratic automorphisms have order dividing q+1 and D, D-1, or D+1 + if quad==True: + #need sqrt to get the cardinality of the base field and not the + #degree 2 extension + q = sqrt(E.cardinality()) + zeta = (E.multiplicative_generator())**(q-1) + for j in [-1,0,1]: + g = gcd(q+1, D + j) + xi = zeta**( (q+1) / g ) + for i in range(1,g): + s = u_inv(xi**i*u(z)) + if s(phi(z)) == phi(s(z)): + automorphisms_prime_to_p.append(rational_function_reduce(s)) + + # rational automorphisms have order dividing q-1 and D, D-1, or D+1 + else: + q = E.cardinality() + zeta = E.multiplicative_generator() + for j in [-1,0,1]: + g = gcd(q-1, D + j) + xi = zeta**( (q-1) / g ) + for i in range(1,g): + s = u_inv(xi**i*u(z)) + if s(phi(z)) == phi(s(z)): + automorphisms_prime_to_p.append(rational_function_reduce(s)) + + return list(set(automorphisms_prime_to_p)) + +def automorphism_group_FF_alg3(rational_function): + r""" + Implementation of Algorithm 3 in the paper by Faber/Manes/Viray [FMV] + for computing the automorphism group over a finite field. + + INPUT: + + - ``rational_function``--a rational function defined over a finite field `F`. + + OUTPUT: + + - list of `F`-rational automorphisms of ``rational_function``. + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(5^3,'t')) + sage: f = (3456*z^4) + sage: from sage.schemes.projective.endPN_automorphism_group import automorphism_group_FF_alg3 + sage: automorphism_group_FF_alg3(f) + [z, 3/(3*z)] + """ + # define ground field and ambient function field + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + F = R.base_ring() + if not F.is_finite() or not F.is_field(): + raise TypeError("Coefficient ring is not a finite field.") + p = F.characteristic() + q = F.cardinality() + z = R.gen(0) + phi = K(rational_function) + f = phi.numerator() + g = phi.denominator() + D = max(f.degree(), g.degree()) + + # For use in the quadratic extension parts of the algorithm + E = GF(p**(2*F.degree()),'b') + b = E.gen(0) + sigma = F.Hom(E)[0] + S = PolynomialRing(E, 'w') + w = S.gen(0) + Phi = rational_function_coerce(phi, sigma, S) + + # Compute the set of distinct F-rational and F-quadratic + # factors of the fixed point polynomial + fix = R(f(z) - z*g(z)) + linear_fix = gcd(fix, z**q - z); + quad_temp = fix.quo_rem(linear_fix)[0] + residual = gcd(quad_temp, z**q - z) + while residual.degree() > 0: + quad_temp = quad_temp.quo_rem(residual)[0] + residual = gcd(quad_temp, z**q - z) + quadratic_fix = gcd(quad_temp, z**(q**2) - z).factor() + + # Compute the set of distinct F-rational fixed points + linear_fix_pts = [[ x, F(1)] for x in linear_fix.roots(multiplicities=False)] + if bool(fix.degree() < D+1): + linear_fix_pts.append( [F(1),F(0)] ) + n1 = len(linear_fix_pts) + + # Coerce quadratic factors into a quadratic extension + quad_fix_factors = [ rational_function_coerce(poly[0], sigma, S) for poly in quadratic_fix] + n2 = 2*len(quad_fix_factors) + + # Collect pre-image data as a list L with entries in the form + # [fixed point y, F-rational pre-images z != y, polynomial defining the pre-images] + # Note that we remove the fixed point from its pre-image set and its polynomial + pre_images = [] + for y in linear_fix_pts: + if y == [F(1),F(0)]: + Fpre = [ [x,F(1)] for x in g.roots(multiplicities=False) ] + pre_images.append([y, Fpre, g]) + else: + Fpre = [ [x,F(1)] for x in (f - y[0]*g).roots(multiplicities=False) if x != y[0]] + if y[0] == 0 and f.degree() < g.degree(): + Fpre.append([F(1), F(0)]) # infinity is a pre-image of 0 + elif f.degree() == g.degree() and f.leading_coefficient() == y[0]*g.leading_coefficient(): + Fpre.append([F(1), F(0)]) # infinity is a pre-image of y[0] + # remove y[0] as a root of pre-image polynomial + h = (f - y[0]*g).quo_rem(z-y[0])[0] + h_common = gcd(h, z-y[0]) + while h_common.degree() > 0: + h = h.quo_rem(z-y[0])[0] + h_common = gcd(h,z-y[0]) + pre_images.append([y, Fpre, h]) + + # Initialize the set of automorphisms to contain the identity + automorphisms = [R(z)] + automorphisms_quad = [] + + # order p elements + # An F-rational fixed point has orbit length 1 or p under the action of an element of + # order p. An F-quadratic fixed point has orbit length p. The set of F-rational + # pre-images of fixed points decomposes as a union of orbits of length p. + if n1%p == 1 and n2%p == 0 and sum(len(x[1]) for x in pre_images)%p == 0: + # Compute total number of distinct fixed points as a final check for order p auts + factor_list = fix.factor() + minimal_fix_poly = R(prod(x[0] for x in factor_list)) + n = sum(x[0].degree() for x in factor_list) + bool(fix.degree() < D+1) + if n%p == 1: + automorphisms = automorphisms + order_p_automorphisms(phi, pre_images) + + ## nontrivial elements with order prime to p ## + # case of 2 F-rational fixed points + for pt_pair in combinations(linear_fix_pts, 2): + x = pt_pair[0] + y = pt_pair[1] + automorphisms = automorphisms + automorphisms_fixing_pair(phi, [x,y], False) + + # case of 1 F-rational fixed point and an F-rational pre-image + for y in pre_images: + for x in y[1]: + automorphisms = automorphisms + automorphisms_fixing_pair(phi, [x,y[0]], False) + + # case of a pair of quadratic fixed points + for h in quad_fix_factors: + quad_fix_pts = [ [x,E(1)] for x in h.roots(multiplicities=False)] + automorphisms_quad = automorphisms_quad + automorphisms_fixing_pair(Phi, quad_fix_pts, True) + + phi_2 = phi(phi(z)) + f_2 = phi_2.numerator() + g_2 = phi_2.denominator() + + period_2 = (f_2(z) - z*g_2(z)).quo_rem(fix)[0] + factor_list_2 = period_2.factor() + linear_period_2_pts = [[ x, F(1)] for x in period_2.roots(multiplicities=False)] + if bool(period_2.degree() < D**2-D): + linear_period_2_pts.append( [F(1),F(0)] ) + quad_period_2_factors = [rational_function_coerce(poly[0], sigma, S) for poly in factor_list_2 if poly[0].degree() == 2] + # n2 = n1 + 2*len(quad_fix_factors) + + # case of a pair of F-rational period 2 points + linear_period_2_pairs = [] + while len(linear_period_2_pts) > 0: + x = linear_period_2_pts.pop(-1) + if x[1] == 1 and g(x[0]) != 0: + y = [phi(x[0]), F(1)] + elif x[1] == 1 or f.degree() > g.degree(): + y = [F(1), F(0)] + elif f.degree() == g.degree(): + y = [f.leading_coefficient() / g.leading_coefficient(), F(1)] + else: + y = [F(0), F(1)] + + if x != y: + linear_period_2_pts.remove(y) + linear_period_2_pairs.append([x,y]) + + for pt_pair in linear_period_2_pairs: + automorphisms = automorphisms + automorphisms_fixing_pair(phi, pt_pair, False) + + # case of a pair of quadratic period 2 points + for h in quad_period_2_factors: + pt_pair = [ [x,E(1)] for x in h.roots(multiplicities=False)] + if Phi(pt_pair[0][0]) == pt_pair[1][0]: + automorphisms_quad = automorphisms_quad + automorphisms_fixing_pair(Phi, pt_pair, True) + + # Descend coefficients of the quadratic guys back to the base field + for s in automorphisms_quad: + automorphisms.append(rational_function_coefficient_descent(s, sigma, R)) + + return automorphisms + + +def which_group(list_of_elements): + r""" + Given a finite subgroup of `PGL2` determine its isomorphism class. + This function makes heavy use of the classification of finite subgroups of `PGL(2,K)` + + INPUT: + + - ``list_of_elements``-- a finite list of elements of `PGL(2,K)` + that we know a priori form a group + + OUTPUT: + + - String -- the isomorphism type of the group. + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(7,'t')) + sage: G = [x, 6*x/(x + 1), 6*x + 6, 1/x, (6*x + 6)/x, 6/(x + 1)] + sage: from sage.schemes.projective.endPN_automorphism_group import which_group + sage: which_group(G) + 'Dihedral of order 6' + """ + if is_Matrix(list_of_elements[-1]): + R = PolynomialRing(list_of_elements[-1].base_ring(),'z') + z = R.gen(0) + G=[(t[0,0]*z+t[0,1])/(t[1,0]*z+t[1,1]) for t in list_of_elements] + else: + G = list_of_elements + + n = ZZ(len(G)) + + # invalid input + if n == 0: + raise(ValueError, "Group must have at least one element") + + # define ground field and ambient function field + rational_function = G[-1] + + if rational_function.parent().is_field(): + K = rational_function.parent() + R = K.ring() + else: + R = rational_function.parent() + K = R.fraction_field() + + z = R.gen(0) + p = K.characteristic() + + # factor n = mp^e; set e = 0 and m = n if p = 0 (Sage sets 0^0 = 1) + if p > 0: + m = n.prime_to_m_part(p) + e = ZZ(n/m).exact_log(p) + else: + m = n + e = 0 + + # Determine if G is cyclic or dihedral. + # This determines the maximal cyclic subgroup and the maximal cyclic + # p-regular subgroup. Algorithm terminates if the order of this subgroup agrees with + # the order of the group. + max_reg_cyclic = [1, z, [z]] # initialize order of cyclic p-regular subgroup and generator + discard = [] # list of elements already considered + + for g in G: + if g not in discard: + H = [g] + for i in range(n-1): + h = g(H[-1]) + H.append(h) + H = list(set(H)) + if len(H) == n: + return 'Cyclic of order {0}'.format(n) + if len(H) > max_reg_cyclic[0] and gcd(len(H), p) != p: + max_reg_cyclic = [len(H), g, H] + discard = list(set(discard +H)) # adjoin all new elements to discard + + n_reg = max_reg_cyclic[0] + # Test for dihedral subgroup. A subgroup of index 2 is always normal, so the + # presence of a cyclic subgroup H of index 2 indicates the group is either + # H x Z/2Z or dihedral. The former occurs only if H has order 1 or 2, both of + # which are dihedral. + if 2*n_reg == n: + for g in G: + if g not in max_reg_cyclic[2]: + return 'Dihedral of order {0}'.format(n) + # Check the p-irregular cases. There is overlap in these cases when p^e = 2, + # which is dihedral and so already dealt with above. By the classification theorem, + # these are either p-semi-elementary, PGL(2,q), PSL(2,q), or A_5 when p=3. The latter + # case is already covered by the remaining sporadic cases below. + if e > 0: + if n_reg == m: # p-semi-elementary + return '{0}-semi-elementary of order {1}'.format(p, n) + if n_reg == m / (p**e - 1) and m == p**(2*e) - 1: # PGL(2) + return 'PGL(2,{0})'.format(p**e) + if n_reg == m / (p**e - 1) and m == (1/2)*(p**(2*e) - 1): # PSL(2) + return 'PSL(2,{0})'.format(p**e) + + # Treat sporadic cases + if n == 12: + return ['A_4'] + elif n == 24: + return ['S_4'] + else: + return ['A_5'] \ No newline at end of file diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 967064cbc95..b1359cec3ff 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -42,7 +42,7 @@ from sage.categories.number_fields import NumberFields from sage.categories.homset import Hom from sage.functions.all import sqrt -from sage.libs.pari.gen import PariError +from sage.libs.pari.all import PariError from sage.matrix.constructor import matrix, identity_matrix from sage.misc.cachefunc import cached_method from sage.misc.misc import subsets @@ -56,7 +56,9 @@ from sage.rings.finite_rings.constructor import GF, is_PrimeFiniteField from sage.rings.finite_rings.integer_mod_ring import Zmod from sage.rings.fraction_field import FractionField +from sage.rings.fraction_field_element import is_FractionFieldElement from sage.rings.integer_ring import ZZ +from sage.rings.number_field.order import is_NumberFieldOrder from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ @@ -71,6 +73,8 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.schemes.projective.projective_morphism_helper import _fast_possible_periods import sys +from sage.categories.number_fields import NumberFields +_NumberFields = NumberFields() class SchemeMorphism_polynomial_projective_space(SchemeMorphism_polynomial): """ @@ -1175,17 +1179,25 @@ def is_morphism(self): sage: f = H([x*z-t*y^2,x^2-y^2,t*z^2]) sage: f.is_morphism() True + + Map that is not morphism on projective space, but is over a subscheme:: + + sage: P. = ProjectiveSpace(RR,2) + sage: X = P.subscheme([x*y + y*z]) + sage: H = Hom(X,X) + sage: f = H([x*z-y*z,x^2-y^2,z^2]) + sage: f.is_morphism() + True """ - from sage.schemes.projective.projective_space import is_ProjectiveSpace - if is_ProjectiveSpace(self.domain()) is False or is_ProjectiveSpace(self.codomain()) is False: - raise NotImplementedError + R = self.coordinate_ring() F = self._polys + defpolys = list(self.domain().defining_polynomials()) if R.base_ring().is_field(): - J = R.ideal(F) + J = R.ideal(F + defpolys) else: S = PolynomialRing(R.base_ring().fraction_field(), R.gens(), R.ngens()) - J = S.ideal([S.coerce(F[i]) for i in range(R.ngens())]) + J = S.ideal([S(f) for f in F] + [S(f) for f in defpolys]) if J.dimension() > 0: return False else: @@ -1479,9 +1491,12 @@ def conjugate(self, M): def green_function(self, P, v, **kwds): r""" Evaluates the local Green's function at the place ``v`` for ``P`` with ``N`` terms of the - series or, in dimension 1, to within a given error bound. + series or to within a given error bound. Must be over a number field + or order of a number field. Note that this is absolute local greens function + so is scaled by the degree of the base field. - Use ``v=0`` for the archimedean place. Must be over `\ZZ` or `\QQ`. + Use ``v=0`` for the archimedean place over `\QQ` or field embedding. Non-archimedean + places are prime ideals for number fields or primes over `\QQ`. ALGORITHM: @@ -1495,7 +1510,7 @@ def green_function(self, P, v, **kwds): kwds: - - ``N`` - positive integer. number of terms of the series to use + - ``N`` - positive integer. number of terms of the series to use, default: 10 - ``prec`` - positive integer, float point or p-adic precision, default: 100 @@ -1517,20 +1532,17 @@ def green_function(self, P, v, **kwds): sage: f.green_function(P.point([1,1],False),0,N=30) 0.43288629610862338612700146098 """ - if self.base_ring() != ZZ and self.base_ring() != QQ: - raise TypeError("Must be ZZ or QQ") return(P.green_function(self, v, **kwds)) def canonical_height(self, P, **kwds): r""" - Evaluates the canonical height of ``P`` with respect to ``self``. Must be over `\ZZ` or `\QQ`. - - Specify either the number of terms of the series to evaluate - or, in dimension 1, the error bound required. + Evaluates the (absolute) canonical height of ``P`` with respect to ``self``. Must be over number field + or order of a number field. Specify either the number of terms of the series to evaluate or + the error bound required. ALGORITHM: - The sum of the Green's function at the archimedean place and the places of bad reduction. + The sum of the Green's function at the archimedean places and the places of bad reduction. INPUT: @@ -1555,18 +1567,18 @@ def canonical_height(self, P, **kwds): sage: P. = ProjectiveSpace(ZZ,1) sage: H = Hom(P,P) sage: f = H([x^2+y^2,2*x*y]); - sage: f.canonical_height(P.point([5,4]),error_bound=0.001) - 2.1970553519503404898926835324 - sage: f.canonical_height(P.point([2,1]),error_bound=0.001) - 1.0984430632822307984974382955 + sage: f.canonical_height(P.point([5,4]), error_bound=0.001) + 2.1968861265644615969948765910 + sage: f.canonical_height(P.point([2,1]), error_bound=0.001) + 1.0982738378963519055996313540 Notice that preperiodic points may not be exactly 0:: sage: P. = ProjectiveSpace(QQ,1) sage: H = Hom(P,P) sage: f = H([x^2-29/16*y^2,y^2]); - sage: f.canonical_height(P.point([1,4]),N=60) - 1.2024186864216154694752186858e-18 + sage: f.canonical_height(P.point([1,4]), error_bound=0.000001) + 4.6394113279707749011644196028e-7 :: @@ -1575,11 +1587,9 @@ def canonical_height(self, P, **kwds): sage: H = Hom(X,X) sage: f = H([x^2,y^2,4*z^2]); sage: Q = X([4,4,1]) - sage: f.canonical_height(Q,badprimes=[2]) + sage: f.canonical_height(Q, badprimes=[2]) 0.0013538030870311431824555314882 """ - if self.base_ring() != ZZ and self.base_ring() != QQ: - raise TypeError("Must be ZZ or QQ") return(P.canonical_height(self, **kwds)) def global_height(self, prec=None): @@ -1627,6 +1637,8 @@ def global_height(self, prec=None): .. TODO:: add heights to integer.pyx and remove special case """ + if self.domain().base_ring() not in _NumberFields and not is_NumberFieldOrder(self.domain().base_ring()): + raise TypeError("Must be over a Numberfield or a Numberfield Order") if self.domain().base_ring() == ZZ: if prec is None: R = RealField() @@ -1645,6 +1657,99 @@ def global_height(self, prec=None): H = max(H, h) return(H) + def local_height(self, v, prec=None): + r""" + Returns the maximum of the local height of the coefficients in any + of the coordinate functions of ``self``. + + INPUT: + + - ``v`` -- a prime or prime ideal of the base ring + + - ``prec`` -- desired floating point precision (default: + default RealField precision). + + OUTPUT: + + - a real number + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ,1) + sage: H = Hom(P,P) + sage: f = H([1/1331*x^2+1/4000*y^2,210*x*y]); + sage: f.local_height(1331) + 7.19368581839511 + + This function does not automatically normalize:: + + sage: P. = ProjectiveSpace(QQ,2) + sage: H = Hom(P,P) + sage: f = H([4*x^2+3/100*y^2,8/210*x*y,1/10000*z^2]); + sage: f.local_height(2) + 2.77258872223978 + sage: f.normalize_coordinates() + sage: f.local_height(2) + 0.000000000000000 + + :: + + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(z^2-2) + sage: P. = ProjectiveSpace(K,1) + sage: H = Hom(P,P) + sage: f = H([2*x^2 + w/3*y^2,1/w*y^2]) + sage: f.local_height(K.ideal(3)) + 1.09861228866811 + """ + K = FractionField(self.domain().base_ring()) + if K not in _NumberFields: + raise TypeError("Must be over a Numberfield or a Numberfield Order") + return max([K(c).local_height(v, prec) for f in self for c in f.coefficients()]) + + def local_height_arch(self, i, prec=None): + r""" + Returns the maximum of the local height at the ``i``-th infinite place of the coefficients in any + of the coordinate functions of ``self``. + + INPUT: + + - ``i`` -- an integer + + - ``prec`` -- desired floating point precision (default: + default RealField precision). + + OUTPUT: + + - a real number + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ,1) + sage: H = Hom(P,P) + sage: f = H([1/1331*x^2+1/4000*y^2,210*x*y]); + sage: f.local_height_arch(0) + 5.34710753071747 + + :: + + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(z^2-2) + sage: P. = ProjectiveSpace(K,1) + sage: H = Hom(P,P) + sage: f = H([2*x^2 + w/3*y^2,1/w*y^2]) + sage: f.local_height_arch(1) + 0.6931471805599453094172321214582 + """ + K = FractionField(self.domain().base_ring()) + if K not in _NumberFields: + raise TypeError("Must be over a Numberfield or a Numberfield Order") + if K == QQ: + return max([K(c).local_height_arch(prec=prec) for f in self for c in f.coefficients()]) + else: + return max([K(c).local_height_arch(i, prec=prec) for f in self for c in f.coefficients()]) + + def height_difference_bound(self, prec=None): r""" Returns an upper bound on the different bewtween the canonical height of a point with @@ -2210,6 +2315,101 @@ def minimal_model(self, return_transformation=False, prime_list=None): from endPN_minimal_model import affine_minimal return(affine_minimal(self, return_transformation, prime_list, False)) + def automorphism_group(self, **kwds): + r""" + Given a homogenous rational function, this calculates the subsgroup of `PGL2` that is + the automorphism group of ``self``. + + INPUT: + + keywords: + + - ``starting_prime`` -- The first prime to use for CRT. default: 5.(optional) + + - ``algorithm``-- Choose ``CRT``-Chinese Remainder Theorem- or ``fixed_points`` algorithm. + default: depends on ``self``. (optional) + + - ``return_functions``-- Boolean - True returns elements as linear fractional transformations. + False returns elements as `PGL2` matrices. default: False. (optional) + + - ``iso_type`` -- Boolean - True returns the isomorphism type of the automorphism group. + default: False (optional) + + OUTPUT: + + - list - elements of automorphism group. + + AUTHORS: + + - Original algorithm written by Xander Faber, Michelle Manes, Bianca Viray + + - Modified by Joao Alberto de Faria, Ben Hutz, Bianca Thompson + + REFERENCES: + + .. [FMV] Computing Conjugating Sets and Automorphism Groups of Rational Functions + by Xander Faber, Michelle Manes, and Bianca Viray + + EXAMPLES:: + + sage: R. = ProjectiveSpace(QQ,1) + sage: H = End(R) + sage: f = H([x^2-y^2,x*y]) + sage: f.automorphism_group(return_functions=True) + [x, -x] + + :: + + sage: R. = ProjectiveSpace(QQ,1) + sage: H = End(R) + sage: f = H([x^2 + 5*x*y + 5*y^2,5*x^2 + 5*x*y + y^2]) + sage: f.automorphism_group() + [ + [1 0] [0 2] + [0 1], [2 0] + ] + + :: + + sage: R. = ProjectiveSpace(QQ,1) + sage: H = End(R) + sage: f=H([x^2-2*x*y-2*y^2,-2*x^2-2*x*y+y^2]) + sage: f.automorphism_group(return_functions=True) + [x, 2/(2*x), -x - 1, -2*x/(2*x + 2), (-x - 1)/x, -1/(x + 1)] + + :: + + sage: R. = ProjectiveSpace(QQ,1) + sage: H = End(R) + sage: f = H([3*x^2*y - y^3,x^3 - 3*x*y^2]) + sage: f.automorphism_group(algorithm='CRT',return_functions=True,iso_type=True) + ([x, (x + 1)/(x - 1), (-x + 1)/(x + 1), -x, 1/x, -1/x, (x - 1)/(x + 1), (-x - 1)/(x - 1)], 'Dihedral of order 8') + """ + + alg = kwds.get('algorithm',None) + p = kwds.get('starting_prime', 5) + return_functions = kwds.get('return_functions', False) + iso_type = kwds.get('iso_type',False) + + if self.domain().dimension_relative() != 1: + raise NotImplementedError("Must be dimension 1") + else: + f = self.dehomogenize(1) + z = f[0].parent().gen() + if is_FractionFieldElement(f[0]): + F = (f[0].numerator().polynomial(z))/f[0].denominator().polynomial(z) + else: + F = f[0].polynomial(z) + from endPN_automorphism_group import automorphism_group_QQ_CRT, automorphism_group_QQ_fixedpoints + if alg is None: + if self.degree() <= 12: + return(automorphism_group_QQ_fixedpoints(F, return_functions, iso_type)) + return(automorphism_group_QQ_CRT(F, p, return_functions, iso_type)) + elif alg == 'CRT': + return(automorphism_group_QQ_CRT(F, p, return_functions, iso_type)) + + return(automorphism_group_QQ_fixedpoints(F, return_functions, iso_type)) + class SchemeMorphism_polynomial_projective_space_field(SchemeMorphism_polynomial_projective_space): def lift_to_rational_periodic(self, points_modp, B=None): @@ -3086,3 +3286,88 @@ def possible_periods(self, return_points=False): """ return _fast_possible_periods(self,return_points) + def automorphism_group(self, **kwds): + r""" + Given a homogenous rational function, this calculates the subsgroup of `PGL2` that is + the automorphism group of ``self``, see [FMV] fir algorithm. + + INPUT: + + keywords: + + - ``absolute``-- Boolean - True returns the absolute automorphism group and a field of definition. default: False (optional) + + - ``iso_type`` -- Boolean - True returns the isomorphism type of the automorphism group. default: False (optional) + + - ``return_functions``-- Boolean - True returns elements as linear fractional transformations. + False returns elements as `PGL2` matrices. default: False. (optional) + + OUTPUT: + + - list - elements of automorphism group. + + AUTHORS: + + - Original algorithm written by Xander Faber, Michelle Manes, Bianca Viray\ + + - Modified by Joao Alberto de Faria, Ben Hutz, Bianca Thompson + + EXAMPLES:: + + sage: R. = ProjectiveSpace(GF(7^3,'t'),1) + sage: H = End(R) + sage: f = H([x^2-y^2,x*y]) + sage: f.automorphism_group() + [ + [1 0] [6 0] + [0 1], [0 1] + ] + + :: + + sage: R. = ProjectiveSpace(GF(3^2,'t'),1) + sage: H = End(R) + sage: f = H([x^3,y^3]) + sage: f.automorphism_group(return_functions=True,iso_type=True) # long time + ([x, x/(x + 1), x/(2*x + 1), 2/(x + 2), (2*x + 1)/(2*x), (2*x + 2)/x, + 1/(2*x + 2), x + 1, x + 2, x/(x + 2), 2*x/(x + 1), 2*x, 1/x, 2*x + 1, + 2*x + 2, ((t + 2)*x + t + 2)/((2*t + 1)*x + t + 2), (t*x + 2*t)/(t*x + + t), 2/x, (x + 1)/(x + 2), (2*t*x + t)/(t*x), (2*t + 1)/((2*t + 1)*x + + 2*t + 1), ((2*t + 1)*x + 2*t + 1)/((2*t + 1)*x), t/(t*x + 2*t), (2*x + + 1)/(x + 1)], 'PGL(2,3)') + + :: + + sage: R. = ProjectiveSpace(GF(2^5,'t'),1) + sage: H = End(R) + sage: f=H([x^5,y^5]) + sage: f.automorphism_group(return_functions=True,iso_type=True) + ([x, 1/x], 'Cyclic of order 2') + + :: + + sage: R. = ProjectiveSpace(GF(3^4,'t'),1) + sage: H = End(R) + sage: f=H([x^2+25*x*y+y^2,x*y+3*y^2]) + sage: f.automorphism_group(absolute=True) + [Univariate Polynomial Ring in w over Finite Field in b of size 3^4, + [ + [1 0] + [0 1] + ]] + """ + absolute=kwds.get('absolute',False) + iso_type=kwds.get('iso_type',False) + return_functions=kwds.get('return_functions',False) + + if self.domain().dimension_relative()!=1: + raise NotImplementedError, "Must be dimension 1" + else: + f=self.dehomogenize(1) + z=f[0].parent().gen() + if f[0].denominator()!=1: + F=(f[0].numerator().polynomial(z))/f[0].denominator().polynomial(z) + else: + F=f[0].numerator().polynomial(z) + from endPN_automorphism_group import automorphism_group_FF + return(automorphism_group_FF(F, absolute, iso_type, return_functions)) diff --git a/src/sage/schemes/projective/projective_point.py b/src/sage/schemes/projective/projective_point.py index 2b0326d8988..b67e505bf20 100644 --- a/src/sage/schemes/projective/projective_point.py +++ b/src/sage/schemes/projective/projective_point.py @@ -39,14 +39,18 @@ from sage.categories.number_fields import NumberFields _NumberFields = NumberFields() from sage.rings.infinity import infinity -from sage.rings.arith import gcd, lcm, is_prime -from sage.rings.fraction_field import FractionField +from sage.rings.arith import gcd, lcm, is_prime, binomial from sage.rings.integer_ring import ZZ +from sage.rings.fraction_field import FractionField +from sage.rings.morphism import RingHomomorphism_im_gens from sage.rings.number_field.order import is_NumberFieldOrder +from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal from sage.rings.padics.all import Qp from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ -from sage.rings.real_mpfr import RealField, RR +from sage.rings.real_double import RDF +from sage.rings.real_mpfr import RealField, RR, is_RealField + from copy import copy from sage.schemes.generic.morphism import (SchemeMorphism, is_SchemeMorphism, @@ -768,12 +772,16 @@ def orbit(self,f,N,**kwds): Orb.append(Q) return(Orb) - def green_function(self, G,v, **kwds): + def green_function(self, G, v, **kwds): r""" - Evaluates the local Green's function at the place ``v`` for ``self`` with ``N`` terms of the series - or, in dimension 1, to within the specified error bound. Defaults to ``N=10`` if no kwds provided + Evaluates the local Green's function with respect to the morphism ``G`` + at the place ``v`` for ``self`` with ``N`` terms of the + series or to within a given error bound. Must be over a number field + or order of a number field. Note that this is the absolute local Green's function + so is scaled by the degree of the base field. - Use ``v=0`` for the archimedean place. Must be over `\ZZ` or `\QQ`. + Use ``v=0`` for the archimedean place over `\QQ` or field embedding. Non-archimedean + places are prime ideals for number fields or primes over `\QQ`. ALGORITHM: @@ -781,13 +789,13 @@ def green_function(self, G,v, **kwds): INPUT: - - ``G`` - an endomorphism of self.codomain() + - ``G`` - a projective morphism whose local Green's function we are computing - ``v`` - non-negative integer. a place, use v=0 for the archimedean place kwds: - - ``N`` - positive integer. number of terms of the series to use + - ``N`` - positive integer. number of terms of the series to use, default: 10 - ``prec`` - positive integer, float point or p-adic precision, default: 100 @@ -797,7 +805,7 @@ def green_function(self, G,v, **kwds): - a real number - Examples:: + EXAMPLES:: sage: P.=ProjectiveSpace(QQ,1) sage: H=Hom(P,P) @@ -815,94 +823,150 @@ def green_function(self, G,v, **kwds): sage: Q.green_function(f,0,N=200,prec=200) 1.6460930160038721802875250367738355497198064992657997569827 - .. TODO:: + :: - error bounds for dimension > 1 + sage: K. = QuadraticField(3) + sage: P. = ProjectiveSpace(K,1) + sage: H = Hom(P,P) + sage: f = H([17*x^2+1/7*y^2,17*w*x*y]) + sage: f.green_function(P.point([w,2],False), K.places()[1]) + 1.7236334013785676107373093775 + sage: print f.green_function(P([2,1]), K.ideal(7), N=7) + 0.48647753726382832627633818586 + sage: print f.green_function(P([w,1]), K.ideal(17), error_bound=0.001) + -0.70761163353747779889947530309 + + .. TODO:: Implement general p-adic extensions so that the flip trick can be used + for number fields. """ - N = kwds.get('N', None) #Get number of iterates (if entered) + N = kwds.get('N', 10) #Get number of iterates (if entered) err = kwds.get('error_bound', None) #Get error bound (if entered) prec = kwds.get('prec', 100) #Get precision (if entered) - R=RealField(prec) - - if not (v == 0 or is_prime(v)): - raise ValueError("Invalid valuation (=%s) entered."%v) - if v == 0: + R = RealField(prec) + localht = R(0) + BR = FractionField(self.codomain().base_ring()) + GBR = G.change_ring(BR) #so the heights work + + if not BR in NumberFields(): + raise NotImplementedError("Must be over a NumberField or a NumberField Order") + + #For QQ the 'flip-trick' works better over RR or Qp + if isinstance(v, (NumberFieldFractionalIdeal, RingHomomorphism_im_gens)): + K = BR + elif is_prime(v): + K = Qp(v, prec) + elif v == 0: K = R + v = BR.places(prec=prec)[0] else: - K = Qp(v, prec) + raise ValueError("Invalid valuation (=%s) entered."%v) #Coerce all polynomials in F into polynomials with coefficients in K - F=G.change_ring(K,False) + F = G.change_ring(K, False) d = F.degree() - D=F.codomain().ambient_space().dimension_relative() + dim = F.codomain().ambient_space().dimension_relative() + P = self.change_ring(K, False) if err is not None: - if D!=1: - raise NotImplementedError("error bounds only for dimension 1") err = R(err) if not err>0: raise ValueError("Error bound (=%s) must be positive."%err) + if G.is_endomorphism() == False: + raise NotImplementedError("Error bounds only for endomorphisms") #if doing error estimates, compute needed number of iterates - res = F.resultant() - - #compute maximum coefficient of polynomials of F - C = R(G.global_height(prec)) - - if v == 0: - log_fact = R(0) - for i in range(2*d+1): - log_fact += R(i+1).log() - B = max((R(res.abs()) - R(2*d).log() - (2*d-1)*C - log_fact).log().abs(), (C + R(d+1).log()).abs()) - else: - B = max(R(res.abs()).log() - ((2*d-1)*C).abs(), C.abs()) - N = R(B/(err*(d-1))).log(d).abs().ceil() - - elif N is None: - N=10 #default is to do 10 iterations - - #Coerce the coordinates into Q_v - self.normalize_coordinates() - if self.codomain().base_ring()==QQ: - self.clear_denominators() - P=self.change_ring(K,False) + D = (dim + 1) * (d - 1) + 1 + #compute upper bound + if isinstance(v, RingHomomorphism_im_gens): #archimedean + vindex = BR.places(prec=prec).index(v) + U = GBR.local_height_arch(vindex, prec=prec) + R(binomial(dim + d, d)).log() + else: #non-archimedean + U = GBR.local_height(v, prec=prec) + + #compute lower bound - from explicit polynomials of Nullstellensatz + CR = GBR.codomain().ambient_space().coordinate_ring() #.lift() only works over fields + I = CR.ideal(GBR.defining_polynomials()) + maxh = 0 + for k in range(dim + 1): + CoeffPolys = (CR.gen(k) ** D).lift(I) + Res = 1 + h = 1 + for poly in CoeffPolys: + if poly != 0: + for c in poly.coefficients(): + Res = lcm(Res, c.denominator()) + for poly in CoeffPolys: + if poly != 0: + if isinstance(v, RingHomomorphism_im_gens): #archimedean + if BR == QQ: + h = max([(Res*c).local_height_arch(prec=prec) for c in poly.coefficients()]) + else: + h = max([(Res*c).local_height_arch(vindex, prec=prec) for c in poly.coefficients()]) + else: #non-archimedean + h = max([c.local_height(v, prec=prec) for c in poly.coefficients()]) + if h > maxh: + maxh=h + if isinstance(v, RingHomomorphism_im_gens): #archimedean + L = R(Res / ((dim + 1) * binomial(dim + D - d, D - d) * maxh)).log().abs() + else: #non-archimedean + L = R(1 / maxh).log().abs() + C = max([U, L]) + if C != 0: + N = R(C/(err)).log(d).abs().ceil() + else: #we just need log||P||_v + N=1 #START GREEN FUNCTION CALCULATION - - g = R(0) - - for i in range(N+1): + if isinstance(v, RingHomomorphism_im_gens): #embedding for archimedean local height + for i in range(N+1): + Pv = [ (v(t).abs()) for t in P ] + m = -1 + #compute the maximum absolute value of entries of a, and where it occurs + for n in range(dim + 1): + if Pv[n] > m: + j = n + m = Pv[n] + # add to sum for the Green's function + localht += ((1/R(d))**R(i)) * (R(m).log()) + #get the next iterate + if i < N: + P.scale_by(1/P[j]) + P = F(P, False) + return (1/BR.absolute_degree()) * localht + + #else - prime or prime ideal for non-archimedean + for i in range(N + 1): + if BR == QQ: + Pv = [ R(K(t).abs()) for t in P ] + else: + Pv = [ R(t.abs_non_arch(v)) for t in P ] m = -1 - #compute the maximum absolute value of entries of a, and where it occurs - for n in range(D+1): - a_v = R(P[n].abs()) - if a_v > m: + for n in range(dim + 1): + if Pv[n] > m: j = n - m = a_v - - #add to Greens function - g += (1/R(d))**(i)*R(m).log() - - #normalize coordinates and evaluate - P.scale_by(1/P[j]) - P = F(P, check=False) - - return g - - def canonical_height(self,F, **kwds): + m = Pv[n] + # add to sum for the Green's function + localht += ((1/R(d))**R(i)) * (R(m).log()) + #get the next iterate + if i < N: + P.scale_by(1/P[j]) + P = F(P, False) + return (1/BR.absolute_degree()) * localht + + def canonical_height(self, F, **kwds): r""" - Evaluates the canonical height of ``self`` with respect to ``F``. Must be over `\ZZ` or `\QQ`. - Specify either the number of terms of the series to evaluate or, in dimension 1, the error bound - required. + Evaluates the (absolute) canonical height of ``self`` with respect to ``F``. Must be over number field + or order of a number field. Specify either the number of terms of the series to evaluate or + the error bound required. ALGORITHM: - The sum of the Green's function at the archimedean place and the places of bad reduction. + The sum of the Green's function at the archimedean places and the places of bad reduction. INPUT: - - ``P`` - a projective point + - ``F`` - a projective morphism kwds: @@ -920,10 +984,10 @@ def canonical_height(self,F, **kwds): EXAMPLES:: - sage: P.=ProjectiveSpace(ZZ,1) - sage: H=Hom(P,P) - sage: f=H([x^2+y^2,2*x*y]); - sage: Q=P(2,1) + sage: P. = ProjectiveSpace(ZZ,1) + sage: H = Hom(P,P) + sage: f = H([x^2+y^2,2*x*y]); + sage: Q = P(2,1) sage: f.canonical_height(f(Q)) 2.1965476757927038111992627081 sage: f.canonical_height(Q) @@ -931,38 +995,71 @@ def canonical_height(self,F, **kwds): Notice that preperiodic points may not be exactly 0. :: - sage: P.=ProjectiveSpace(QQ,1) - sage: H=Hom(P,P) - sage: f=H([x^2-29/16*y^2,y^2]); - sage: Q=P(5,4) - sage: f.canonical_height(Q,N=30) - 1.4989058602918874235863427216e-9 + sage: P. = ProjectiveSpace(QQ,1) + sage: H = Hom(P,P) + sage: f = H([x^2-29/16*y^2,y^2]); + sage: Q = P(5,4) + sage: f.canonical_height(Q, N=30) + 1.4989058602918874235833076226e-9 :: - sage: P.=ProjectiveSpace(QQ,2) - sage: X=P.subscheme(x^2-y^2); - sage: H=Hom(X,X) - sage: f=H([x^2,y^2,30*z^2]); - sage: Q=X([4,4,1]) - sage: f.canonical_height(Q,badprimes=[2,3,5],prec=200) + sage: P. = ProjectiveSpace(QQ,2) + sage: X = P.subscheme(x^2-y^2); + sage: H = Hom(X,X) + sage: f = H([x^2,y^2,30*z^2]); + sage: Q = X([4,4,1]) + sage: f.canonical_height(Q, badprimes=[2,3,5], prec=200) 2.7054056208276961889784303469356774912979228770208655455481 """ + bad_primes = kwds.pop("badprimes", None) + prec = kwds.get("prec", 100) + error_bound = kwds.get("error_bound", None) + K = FractionField(self.codomain().base_ring()) + + if not K in _NumberFields: + raise NotImplementedError("Must be over a NumberField or a NumberField Order") + + if bad_primes is None: + bad_primes = [] + for b in self: + if K == QQ: + bad_primes += b.denominator().prime_factors() + else: + bad_primes += b.denominator_ideal().prime_factors() + bad_primes += K(F.resultant()).support() + bad_primes = list(set(bad_primes)) + + emb = K.places(prec=prec) + num_places = len(emb) + len(bad_primes) + if not error_bound is None: + error_bound /= num_places + R = RealField(prec) + h = R(0) + + # Archimedean local heights + # :: WARNING: If places is fed the default Sage precision of 53 bits, + # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec) + # the function is_RealField does not identify RDF as real, so we test for that ourselves. + for v in emb: + if is_RealField(v.codomain()) or v.codomain() is RDF: + dv = R(1) + else: + dv = R(2) + h += dv*self.green_function(F, v, **kwds) #arch Green function - badprimes = kwds.pop("badprimes",None) - - if badprimes is None: - badprimes=F.primes_of_bad_reduction(0) - - h=self.green_function(F,0,**kwds) #arch Green function - for v in badprimes: - h+=self.green_function(F,v,**kwds) #non-arch Green functions - + # Non-Archimedean local heights + for v in bad_primes: + if K == QQ: + dv = R(1) + else: + dv = R(v.residue_class_degree() * v.absolute_ramification_index()) + h += dv * self.green_function(F, v, **kwds) #non-arch Green functions return h def global_height(self, prec=None): r""" - Returns the logarithmic height of the points. Must be over `\ZZ` or `\QQ`. + Returns the logarithmic height of the points. INPUT: @@ -995,16 +1092,82 @@ def global_height(self, prec=None): sage: A([3,5*w+1,1]).global_height(prec=100) 2.4181409534757389986565376694 - .. TODO:: - - p-adic heights - """ if self.domain().base_ring() in _NumberFields or is_NumberFieldOrder(self.domain().base_ring()): - return(max([self[i].global_height(prec) for i in range(self.codomain().ambient_space().dimension_relative()+1)])) + return(max([self[i].global_height(prec=prec) for i in range(self.codomain().ambient_space().dimension_relative()+1)])) else: - raise NotImplementedError("Must be over a Numberfield or a Numberfield Order") + raise TypeError("Must be over a Numberfield or a Numberfield Order") + + def local_height(self, v, prec=None): + r""" + Returns the maximum of the local height of the coordinates of ``self``. + + INPUT: + + - ``v`` -- a prime or prime ideal of the base ring + + - ``prec`` -- desired floating point precision (default: + default RealField precision). + + OUTPUT: + + - a real number + + EXAMPLES:: + + sage: P.=ProjectiveSpace(QQ,2) + sage: Q=P.point([4,4,1/150],False) + sage: Q.local_height(5) + 3.21887582486820 + + :: + + sage: P.=ProjectiveSpace(QQ,2) + sage: Q=P([4,1,30]) + sage: Q.local_height(2) + 0.693147180559945 + """ + K = FractionField(self.domain().base_ring()) + if K not in _NumberFields: + raise("Must be over a Numberfield or a Numberfield Order") + return max([K(c).local_height(v, prec=prec) for c in self]) + def local_height_arch(self, i, prec=None): + r""" + Returns the maximum of the local heights at the ``i``-th infinite place of ``self``. + + INPUT: + + - ``i`` -- an integer + + - ``prec`` -- desired floating point precision (default: + default RealField precision). + + OUTPUT: + + - a real number + + EXAMPLES:: + + sage: P.=ProjectiveSpace(QQ,2) + sage: Q = P.point([4,4,1/150], False) + sage: Q.local_height_arch(0) + 1.38629436111989 + + :: + + sage: P.=ProjectiveSpace(QuadraticField(5, 'w'),2) + sage: Q = P.point([4,1,30], False) + sage: Q.local_height_arch(1) + 3.401197381662155375413236691607 + """ + K = FractionField(self.domain().base_ring()) + if K not in _NumberFields: + raise("Must be over a Numberfield or a Numberfield Order") + if K == QQ: + return max([K(c).local_height_arch(prec=prec) for c in self]) + else: + return max([K(c).local_height_arch(i, prec=prec) for c in self]) def multiplier(self,f,n,check=True): r""" diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 408a5c36d3b..bb9038b4ff3 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -1004,16 +1004,16 @@ def __iter__(self): P = [ zero for _ in range(i) ] + [ R(1) ] + [ zero for _ in range(n-i) ] yield self(P) iters = [ iter(R) for _ in range(i) ] - for x in iters: x.next() # put at zero + for x in iters: next(x) # put at zero j = 0 while j < i: try: - P[j] = iters[j].next() + P[j] = next(iters[j]) yield self(P) j = 0 except StopIteration: iters[j] = iter(R) # reset - iters[j].next() # put at zero + next(iters[j]) # put at zero P[j] = zero j += 1 i -= 1 @@ -1069,17 +1069,17 @@ def rational_points_dictionary(self): D.update({self(P):index}) index+=1 iters = [ iter(R) for _ in range(i) ] - for x in iters: x.next() # put at zero + for x in iters: next(x) # put at zero j = 0 while j < i: try: - P[j] = iters[j].next() + P[j] = next(iters[j]) D.update({self(P):index}) index+=1 j = 0 except StopIteration: iters[j] = iter(R) # reset - iters[j].next() # put at zero + next(iters[j]) # put at zero P[j] = zero j += 1 i -= 1 diff --git a/src/sage/schemes/toric/divisor_class.pyx b/src/sage/schemes/toric/divisor_class.pyx index d27240b7492..8f32eab7935 100644 --- a/src/sage/schemes/toric/divisor_class.pyx +++ b/src/sage/schemes/toric/divisor_class.pyx @@ -56,8 +56,7 @@ divisor representing a divisor class:: #***************************************************************************** -include 'sage/ext/cdefs.pxi' # Needed for mpq* stuff -include 'sage/ext/stdsage.pxi' # Needed for PY_NEW +from sage.libs.gmp.mpq cimport * from sage.misc.all import latex from sage.modules.all import vector @@ -141,7 +140,7 @@ cdef class ToricRationalDivisorClass(Vector_rational_dense): cdef _new_c(self): cdef ToricRationalDivisorClass y - y = PY_NEW(ToricRationalDivisorClass) + y = ToricRationalDivisorClass.__new__(ToricRationalDivisorClass) y._init(self._degree, self._parent) return y @@ -332,7 +331,7 @@ def _ToricRationalDivisorClass_unpickle_v1(parent, entries, Divisor class [1, -2, 3, -4] """ cdef ToricRationalDivisorClass v - v = PY_NEW(ToricRationalDivisorClass) + v = ToricRationalDivisorClass.__new__(ToricRationalDivisorClass) v._init(degree, parent) cdef Rational z for i from 0 <= i < degree: diff --git a/src/sage/schemes/toric/homset.py b/src/sage/schemes/toric/homset.py index 5a892869196..f3a9cffe355 100644 --- a/src/sage/schemes/toric/homset.py +++ b/src/sage/schemes/toric/homset.py @@ -357,9 +357,9 @@ def _naive_enumerator(self, ring=None): sage: P123 = toric_varieties.P2_123(base_ring=GF(3)) sage: point_set = P123.point_set() - sage: iter(point_set._naive_enumerator()).next() + sage: next(iter(point_set._naive_enumerator())) (0, 0, 1) - sage: iter(point_set).next() + sage: next(iter(point_set)) [0 : 0 : 1] """ from sage.schemes.toric.points import \ @@ -536,9 +536,9 @@ def __iter__(self): sage: P123 = toric_varieties.P2_123(base_ring=GF(3)) sage: point_set = P123.point_set() - sage: iter(point_set.__iter__()).next() + sage: next(iter(point_set.__iter__())) [0 : 0 : 1] - sage: iter(point_set).next() # syntactic sugar + sage: next(iter(point_set)) # syntactic sugar [0 : 0 : 1] """ for pt in self._naive_enumerator(): diff --git a/src/sage/schemes/toric/points.py b/src/sage/schemes/toric/points.py index 5a911505143..03238c8ba1a 100644 --- a/src/sage/schemes/toric/points.py +++ b/src/sage/schemes/toric/points.py @@ -18,7 +18,7 @@ sage: point_set = P2.point_set() sage: point_set.cardinality() 13 - sage: iter(point_set).next() + sage: next(iter(point_set)) [0 : 0 : 1] sage: list(point_set)[0:5] [[0 : 0 : 1], [1 : 0 : 0], [0 : 1 : 0], [0 : 1 : 1], [0 : 1 : 2]] @@ -39,7 +39,7 @@ from copy import copy from sage.combinat.cartesian_product import CartesianProduct -from sage.misc.misc import powerset, prod +from sage.misc.all import powerset, prod from sage.misc.cachefunc import cached_method @@ -62,10 +62,10 @@ def __init__(self, fan, ring): sage: fan = toric_varieties.P2().fan() sage: n = InfinitePointEnumerator(fan, QQ) sage: ni = iter(n) - sage: [ni.next() for k in range(10)] - [(0, 1, 1), (1, 1, 1), (-1, 1, 1), (1/2, 1, 1), (-1/2, 1, 1), + sage: [next(ni) for k in range(10)] + [(0, 1, 1), (1, 1, 1), (-1, 1, 1), (1/2, 1, 1), (-1/2, 1, 1), (2, 1, 1), (-2, 1, 1), (1/3, 1, 1), (-1/3, 1, 1), (3, 1, 1)] - + sage: X = ToricVariety(Fan([], lattice=ZZ^0)) sage: X.point_set().cardinality() 1 @@ -91,7 +91,7 @@ def __iter__(self): sage: fan = toric_varieties.P2().fan() sage: n = InfinitePointEnumerator(fan, QQ) sage: ni = iter(n) - sage: [ni.next() for k in range(5)] + sage: [next(ni) for k in range(5)] [(0, 1, 1), (1, 1, 1), (-1, 1, 1), (1/2, 1, 1), (-1/2, 1, 1)] """ rays = self.fan().rays() + self.fan().virtual_rays() @@ -125,7 +125,7 @@ def __init__(self, fan, ring): sage: from sage.schemes.toric.points import NaiveFinitePointEnumerator sage: fan = toric_varieties.P2().fan() sage: n = NaiveFinitePointEnumerator(fan, GF(3)) - sage: iter(n).next() + sage: next(iter(n)) (0, 0, 1) """ assert ring.is_finite() diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 884ed104e99..44c8e2b14ee 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -95,7 +95,7 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): sage: U3.cardinality() 32 sage: it = iter(U3) - sage: [it.next(), it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [[1, 2], [2, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1]] sage: U3.unrank(18) [2, 4, 1, 3] @@ -109,7 +109,7 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): sage: U4.cardinality() +Infinity sage: it = iter(U4) - sage: [it.next(), it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] sage: U4.unrank(18) [2, 3, 1, 4] @@ -127,9 +127,9 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): sage: Ukeep = DisjointUnionEnumeratedSets( ... Family(range(4), Permutations), keepkey=True) sage: it = iter(Ukeep) - sage: [it.next() for i in range(6)] + sage: [next(it) for i in range(6)] [(0, []), (1, [1]), (2, [1, 2]), (2, [2, 1]), (3, [1, 2, 3]), (3, [1, 3, 2])] - sage: type(it.next()[1]) + sage: type(next(it)[1]) We now demonstrate the ``facade`` option:: @@ -137,9 +137,9 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): sage: UNoFacade = DisjointUnionEnumeratedSets( ... Family(range(4), Permutations), facade=False) sage: it = iter(UNoFacade) - sage: [it.next() for i in range(6)] + sage: [next(it) for i in range(6)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] - sage: el = it.next(); el + sage: el = next(it); el [2, 1, 3] sage: type(el) @@ -352,16 +352,16 @@ def __iter__(self): sage: U4 = DisjointUnionEnumeratedSets( ... Family(NonNegativeIntegers(), Permutations)) sage: it = iter(U4) - sage: [it.next(), it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] sage: U4 = DisjointUnionEnumeratedSets( ... Family(NonNegativeIntegers(), Permutations), ... keepkey=True, facade=False) sage: it = iter(U4) - sage: [it.next(), it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [(0, []), (1, [1]), (2, [1, 2]), (2, [2, 1]), (3, [1, 2, 3]), (3, [1, 3, 2])] - sage: el = it.next(); el.parent() == U4 + sage: el = next(it); el.parent() == U4 True sage: el.value == (3, Permutation([2,1,3])) True diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index 93f395bd537..90f3a4f437b 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -160,7 +160,7 @@ def Family(indices, function=None, hidden_keys=[], hidden_function=None, lazy=Fa sage: f[-5] -10 sage: i = iter(f) - sage: i.next(), i.next(), i.next(), i.next(), i.next() + sage: next(i), next(i), next(i), next(i), next(i) (0, 2, -2, 4, -4) Note that the ``lazy`` keyword parameter is only needed to force @@ -696,7 +696,7 @@ def __iter__(self): sage: from sage.sets.family import FiniteFamily sage: f = FiniteFamily({3: 'a'}) sage: i = iter(f) - sage: i.next() + sage: next(i) 'a' """ return iter(self.values()) diff --git a/src/sage/sets/finite_set_map_cy.pxd b/src/sage/sets/finite_set_map_cy.pxd index 7672d9cba2c..bacf1323570 100644 --- a/src/sage/sets/finite_set_map_cy.pxd +++ b/src/sage/sets/finite_set_map_cy.pxd @@ -29,8 +29,8 @@ cdef class FiniteSetMap_MN(ClonableIntArray): cdef class FiniteSetMap_Set(FiniteSetMap_MN): pass -cpdef FiniteSetMap_Set FiniteSetMap_Set_from_list(cls, Parent parent, list lst) -cpdef FiniteSetMap_Set FiniteSetMap_Set_from_dict(cls, Parent parent, dict d) +cpdef FiniteSetMap_Set FiniteSetMap_Set_from_list(type cls, Parent parent, list lst) +cpdef FiniteSetMap_Set FiniteSetMap_Set_from_dict(type cls, Parent parent, dict d) cdef class FiniteSetEndoMap_N(FiniteSetMap_MN): pass cdef class FiniteSetEndoMap_Set(FiniteSetMap_Set): pass diff --git a/src/sage/sets/finite_set_map_cy.pyx b/src/sage/sets/finite_set_map_cy.pyx index 705bddf9025..dc88de971fa 100644 --- a/src/sage/sets/finite_set_map_cy.pyx +++ b/src/sage/sets/finite_set_map_cy.pyx @@ -374,7 +374,8 @@ cdef class FiniteSetMap_MN(ClonableIntArray): [1, 0, 2] sage: el.check() """ - cdef FiniteSetMap_MN res = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + cdef FiniteSetMap_MN res = t.__new__(t) res._parent = resParent res._alloc_(self._len) for i in range(self._len): @@ -553,7 +554,7 @@ cdef class FiniteSetMap_Set(FiniteSetMap_MN): return "map: "+", ".join([("%s -> %s"%(i, self(i))) for i in self.domain()]) -cpdef FiniteSetMap_Set FiniteSetMap_Set_from_list(cls, Parent parent, list lst): +cpdef FiniteSetMap_Set FiniteSetMap_Set_from_list(type cls, Parent parent, list lst): """ Creates a ``FiniteSetMap`` from a list @@ -571,11 +572,11 @@ cpdef FiniteSetMap_Set FiniteSetMap_Set_from_list(cls, Parent parent, list lst): True """ cdef FiniteSetMap_MN res - res = PY_NEW(cls) + res = cls.__new__(cls) super(FiniteSetMap_MN, res).__init__(parent, lst) return res -cpdef FiniteSetMap_Set FiniteSetMap_Set_from_dict(cls, Parent parent, dict d): +cpdef FiniteSetMap_Set FiniteSetMap_Set_from_dict(type cls, Parent parent, dict d): """ Creates a ``FiniteSetMap`` from a dictionary @@ -593,7 +594,7 @@ cpdef FiniteSetMap_Set FiniteSetMap_Set_from_dict(cls, Parent parent, dict d): True """ cdef FiniteSetMap_Set res - res = PY_NEW(cls) + res = cls.__new__(cls) res.__init__(parent, d.__getitem__) return res diff --git a/src/sage/sets/integer_range.py b/src/sage/sets/integer_range.py index d6376144819..52152d2b9bf 100644 --- a/src/sage/sets/integer_range.py +++ b/src/sage/sets/integer_range.py @@ -94,7 +94,7 @@ class IntegerRange(UniqueRepresentation, Parent): sage: I.category() Category of facade infinite enumerated sets sage: p = iter(I) - sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) + sage: (next(p), next(p), next(p), next(p), next(p), next(p)) (54, 57, 60, 63, 66, 69) sage: I = IntegerRange(54,-Infinity,-3); I @@ -102,7 +102,7 @@ class IntegerRange(UniqueRepresentation, Parent): sage: I.category() Category of facade infinite enumerated sets sage: p = iter(I) - sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) + sage: (next(p), next(p), next(p), next(p), next(p), next(p)) (54, 51, 48, 45, 42, 39) When ``begin`` and ``end`` are both infinite, you will have to specify the @@ -120,7 +120,7 @@ class IntegerRange(UniqueRepresentation, Parent): sage: -15 in I False sage: p = iter(I) - sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) + sage: (next(p), next(p), next(p), next(p), next(p), next(p), next(p), next(p)) (-12, 25, -49, 62, -86, 99, -123, 136) It is also possible to use the argument ``middle_point`` for other cases, finite @@ -483,11 +483,11 @@ def __iter__(self): sage: I = IntegerRange(123,12,-4) sage: p = iter(I) - sage: [p.next() for i in range(8)] + sage: [next(p) for i in range(8)] [123, 119, 115, 111, 107, 103, 99, 95] sage: I = IntegerRange(-57,12,8) sage: p = iter(I) - sage: [p.next() for i in range(8)] + sage: [next(p) for i in range(8)] [-57, -49, -41, -33, -25, -17, -9, -1] """ n = self._begin @@ -633,12 +633,12 @@ def __iter__(self): sage: I = IntegerRange(-57,Infinity,8) sage: p = iter(I) - sage: [p.next() for i in range(8)] + sage: [next(p) for i in range(8)] [-57, -49, -41, -33, -25, -17, -9, -1] sage: I = IntegerRange(-112,-Infinity,-13) sage: p = iter(I) - sage: [p.next() for i in range(8)] + sage: [next(p) for i in range(8)] [-112, -125, -138, -151, -164, -177, -190, -203] """ n = self._begin @@ -789,11 +789,11 @@ def __iter__(self): sage: from sage.sets.integer_range import IntegerRangeFromMiddle sage: I = IntegerRangeFromMiddle(Infinity,-Infinity,-37,0) sage: p = iter(I) - sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) + sage: (next(p), next(p), next(p), next(p), next(p), next(p), next(p), next(p)) (0, -37, 37, -74, 74, -111, 111, -148) sage: I = IntegerRangeFromMiddle(-12,214,10,0) sage: p = iter(I) - sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) + sage: (next(p), next(p), next(p), next(p), next(p), next(p), next(p), next(p)) (0, 10, -10, 20, 30, 40, 50, 60) """ n = self._middle_point diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index 94eb479423f..78757ba9e21 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -36,7 +36,7 @@ class NonNegativeIntegers(UniqueRepresentation, Parent): sage: NN.element_class sage: it = iter(NN) - sage: [it.next(), it.next(), it.next(), it.next(), it.next()] + sage: [next(it), next(it), next(it), next(it), next(it)] [0, 1, 2, 3, 4] sage: NN.first() 0 @@ -166,7 +166,7 @@ def __iter__(self): sage: NN = NonNegativeIntegers() sage: g = iter(NN) - sage: g.next(), g.next(), g.next(), g.next() + sage: next(g), next(g), next(g), next(g) (0, 1, 2, 3) """ i = 0 diff --git a/src/sage/sets/positive_integers.py b/src/sage/sets/positive_integers.py index 4866299226a..21e87079410 100644 --- a/src/sage/sets/positive_integers.py +++ b/src/sage/sets/positive_integers.py @@ -37,7 +37,7 @@ class PositiveIntegers(IntegerRangeInfinite): ... NotImplementedError: infinite list sage: it = iter(PP) - sage: (it.next(), it.next(), it.next(), it.next(), it.next()) + sage: (next(it), next(it), next(it), next(it), next(it)) (1, 2, 3, 4, 5) sage: PP.first() 1 diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index e2a9b9b0ba1..5677eb76f07 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -302,17 +302,24 @@ def __cmp__(self, other): EXAMPLES:: - sage: I1 = RealSet.open_closed(1, 3)[0]; I1 - (1, 3] - sage: I2 = RealSet.open_closed(0, 5)[0]; I2 - (0, 5] - sage: cmp(I1, I2) - 1 - sage: sorted([I1, I2]) - [(0, 5], (1, 3]] + sage: I1 = RealSet.open_closed(1, 3)[0]; I1 + (1, 3] + sage: I2 = RealSet.open_closed(0, 5)[0]; I2 + (0, 5] + sage: cmp(I1, I2) + 1 + sage: sorted([I1, I2]) + [(0, 5], (1, 3]] + + TESTS: + + Check if a bug in sorting is fixed (:trac:`17714`):: + + sage: RealSet((0, 1),[1, 1],(1, 2)) + (0, 2) """ - return cmp([self._lower, self._lower_closed, self._upper, self._upper_closed], - [other._lower, other._lower_closed, other._upper, other._upper_closed]) + return cmp([self._lower, not self._lower_closed, self._upper, self._upper_closed], + [other._lower, not other._lower_closed, other._upper, other._upper_closed]) element_class = LazyFieldElement @@ -701,9 +708,9 @@ def __iter__(self): sage: s = RealSet(RealSet.open_closed(0,1), RealSet.closed_open(2,3)) sage: i = iter(s) - sage: i.next() + sage: next(i) (0, 1] - sage: i.next() + sage: next(i) [2, 3) """ return iter(self._intervals) diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index c5ad481d7b8..d1d505b4516 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -285,13 +285,13 @@ def __iter__(self): sage: X = Set(ZZ) sage: I = X.__iter__() - sage: I.next() + sage: next(I) 0 - sage: I.next() + sage: next(I) 1 - sage: I.next() + sage: next(I) -1 - sage: I.next() + sage: next(I) 2 """ return self.__object.__iter__() @@ -710,13 +710,13 @@ def __iter__(self): sage: S = Set(GF(19)) sage: I = iter(S) - sage: I.next() + sage: next(I) 0 - sage: I.next() + sage: next(I) 1 - sage: I.next() + sage: next(I) 2 - sage: I.next() + sage: next(I) 3 """ for x in self.set(): @@ -1275,7 +1275,7 @@ def __iter__(self): sage: X = Set(ZZ).intersection(Primes()) sage: I = X.__iter__() - sage: I.next() + sage: next(I) 2 """ for x in self._X: @@ -1383,15 +1383,15 @@ def __iter__(self): sage: X = Set(ZZ).difference(Primes()) sage: I = X.__iter__() - sage: I.next() + sage: next(I) 0 - sage: I.next() + sage: next(I) 1 - sage: I.next() + sage: next(I) -1 - sage: I.next() + sage: next(I) -2 - sage: I.next() + sage: next(I) -3 """ for x in self._X: @@ -1486,15 +1486,15 @@ def __iter__(self): sage: X = Set(ZZ).symmetric_difference(Primes()) sage: I = X.__iter__() - sage: I.next() + sage: next(I) 0 - sage: I.next() + sage: next(I) 1 - sage: I.next() + sage: next(I) -1 - sage: I.next() + sage: next(I) -2 - sage: I.next() + sage: next(I) -3 """ for x in self._X: diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index dbeed3067d7..6673eb42a31 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -128,13 +128,13 @@ class EnumeratedSetFromIterator(Parent): sage: E = EnumeratedSetFromIterator(count, args=(0,), category=InfiniteEnumeratedSets(), cache=True) sage: e1 = iter(E) sage: e2 = iter(E) - sage: e1.next(), e1.next() + sage: next(e1), next(e1) (0, 1) - sage: e2.next(), e2.next(), e2.next() + sage: next(e2), next(e2), next(e2) (0, 1, 2) - sage: e1.next(), e1.next() + sage: next(e1), next(e1) (2, 3) - sage: e2.next() + sage: next(e2) 3 The following warning is due to ``E`` being a facade parent. For more, @@ -229,7 +229,7 @@ def _repr_(self): i = iter(self) for _ in xrange(6): try: - l.append(i.next()) + l.append(next(i)) except StopIteration: break if len(l) < 6: @@ -299,15 +299,15 @@ def __eq__(self, other): i2 = iter(other) while True: try: - x = i1.next() + x = next(i1) except StopIteration: try: - i2.next() + next(i2) return False except StopIteration: return True try: - y = i2.next() + y = next(i2) except StopIteration: return False if x != y: @@ -346,10 +346,10 @@ def __iter__(self): sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) - sage: g1 = iter(E).next(); g1 + sage: g1 = next(iter(E)); g1 Graph on 8 vertices sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) - sage: g2 = iter(E).next(); g2 + sage: g2 = next(iter(E)); g2 Graph on 8 vertices sage: g1 == g2 True diff --git a/src/sage/stats/hmm/chmm.pyx b/src/sage/stats/hmm/chmm.pyx index f060cd24c4b..a76021f5719 100644 --- a/src/sage/stats/hmm/chmm.pyx +++ b/src/sage/stats/hmm/chmm.pyx @@ -1518,7 +1518,7 @@ def unpickle_gaussian_hmm_v1(A, B, pi, prob, n_out): sage: loads(dumps(m)) == m # indirect test True """ - cdef GaussianHiddenMarkovModel m = PY_NEW(GaussianHiddenMarkovModel) + cdef GaussianHiddenMarkovModel m = GaussianHiddenMarkovModel.__new__(GaussianHiddenMarkovModel) m.A = A m.B = B m.pi = pi @@ -1534,7 +1534,7 @@ def unpickle_gaussian_mixture_hmm_v1(A, B, pi, mixture): sage: loads(dumps(m)) == m # indirect test True """ - cdef GaussianMixtureHiddenMarkovModel m = PY_NEW(GaussianMixtureHiddenMarkovModel) + cdef GaussianMixtureHiddenMarkovModel m = GaussianMixtureHiddenMarkovModel.__new__(GaussianMixtureHiddenMarkovModel) m.A = A m.B = B m.pi = pi diff --git a/src/sage/stats/hmm/distributions.pyx b/src/sage/stats/hmm/distributions.pyx index 93f7bcf6557..838bc8cc687 100644 --- a/src/sage/stats/hmm/distributions.pyx +++ b/src/sage/stats/hmm/distributions.pyx @@ -523,7 +523,7 @@ def unpickle_gaussian_mixture_distribution_v1(TimeSeries c0, TimeSeries c1, sage: loads(dumps(P)) == P # indirect doctest True """ - cdef GaussianMixtureDistribution G = PY_NEW(GaussianMixtureDistribution) + cdef GaussianMixtureDistribution G = GaussianMixtureDistribution.__new__(GaussianMixtureDistribution) G.c0 = c0 G.c1 = c1 G.param = param diff --git a/src/sage/stats/hmm/hmm.pyx b/src/sage/stats/hmm/hmm.pyx index 330de6def77..c2106cb335a 100644 --- a/src/sage/stats/hmm/hmm.pyx +++ b/src/sage/stats/hmm/hmm.pyx @@ -1329,7 +1329,7 @@ def unpickle_discrete_hmm_v1(A, B, pi, n_out, emission_symbols, emission_symbols sage: loads(dumps(m)) == m # indirect test True """ - cdef DiscreteHiddenMarkovModel m = PY_NEW(DiscreteHiddenMarkovModel) + cdef DiscreteHiddenMarkovModel m = DiscreteHiddenMarkovModel.__new__(DiscreteHiddenMarkovModel) m.A = A m.B = B m.pi = pi diff --git a/src/sage/stats/intlist.pyx b/src/sage/stats/intlist.pyx index 42f5ac160c4..1789b41b2b8 100644 --- a/src/sage/stats/intlist.pyx +++ b/src/sage/stats/intlist.pyx @@ -495,7 +495,7 @@ cdef class IntList: sage: type(T) """ - cdef TimeSeries T = PY_NEW(TimeSeries) + cdef TimeSeries T = TimeSeries.__new__(TimeSeries) # We just reach into the data structure underlying T, since we # want this function to be *very* fast. T._length = self._length @@ -549,7 +549,7 @@ cdef IntList new_int_list(Py_ssize_t length): """ if length < 0: raise ValueError, "length must be nonnegative" - cdef IntList t = PY_NEW(IntList) + cdef IntList t = IntList.__new__(IntList) t._length = length t._values = sage_malloc(sizeof(int)*length) return t diff --git a/src/sage/structure/category_object.pxd b/src/sage/structure/category_object.pxd index 1b5fe055107..62e749f8b6d 100644 --- a/src/sage/structure/category_object.pxd +++ b/src/sage/structure/category_object.pxd @@ -1,23 +1,19 @@ -############################################################################### -# SAGE: System for Algebra and Geometry Experimentation +#***************************************************************************** # Copyright (C) 2006 William Stein -# Distributed under the terms of the GNU General Public License (GPL) -# The full text of the GPL is available at: +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -############################################################################### - -from cpython.object cimport * -include 'sage/ext/stdsage.pxi' +#***************************************************************************** from sage.structure.sage_object cimport SageObject from sage.structure.generators cimport Generators -# Want circular imports here to define _base as type Parent -# from sage.structure.parent cimport class Parent cpdef inline check_default_category(default_category, category) -cdef class CategoryObject(sage_object.SageObject): - +cdef class CategoryObject(SageObject): cdef _generators cdef _category cdef public _base diff --git a/src/sage/structure/category_object.pyx b/src/sage/structure/category_object.pyx index 2c90fa804d6..6ada6bc354f 100644 --- a/src/sage/structure/category_object.pyx +++ b/src/sage/structure/category_object.pyx @@ -46,8 +46,17 @@ This example illustrates generators for a free module over `\ZZ`. ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) """ -import generators -import sage_object +#***************************************************************************** +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +include 'sage/ext/stdsage.pxi' +cimport generators +cimport sage_object from sage.categories.category import Category from sage.structure.debug_options import debug @@ -83,9 +92,6 @@ def guess_category(obj): return None # don't want to risk importing stuff... cpdef inline check_default_category(default_category, category): - """ - - """ ## The resulting category is guaranteed to be ## a sub-category of the default. if category is None: @@ -624,35 +630,6 @@ cdef class CategoryObject(sage_object.SageObject): def base(self): return self._base - ################################################################################################# - # Automatic lookup of methods on the category. - ################################################################################################# - -# def __getattr__(self, name): -# """ -# Overriding the __getattr__ method allows one to define methods for objects in a particular -# category by writing a corresponding method on the category. -# -# In order to write a method called FOO that's automatically attached to a category object, -# write a method object_FOO on one of that object's categories. -# -# EXAMPLES: -# sage: G = DirichletGroup(18); G -# Group of Dirichlet characters of modulus 18 over Cyclotomic Field of order 6 and degree 2 -# sage: G.generator_orders() -# [1, 6] -# sage: G.category().object_generator_orders(G) -# [1, 6] -# """ -# if self._category is not None: -# attr = self._category.get_object_method(name) -# if attr is not None: -# if callable(attr): -# return FillFirstArg(attr, self) -# else: -# return attr -# return object.__getattribute__(self, name) - ############################################################################ # Homomorphism -- ############################################################################ @@ -923,17 +900,3 @@ class localvars: def __exit__(self, type, value, traceback): self._obj._temporarily_change_names(self._orig_names) - - -# This Cython class confuses the hell out of the Sphinx documentation parser -# (because __doc__ is defined but not set). And the only code that refers to it -# is commented out. So I'm commenting it out too. -- David Loeffler 2009-07-06 -#cdef class FillFirstArg: -# cdef object arg, f -# cdef public __doc__ -# def __init__(self, f, arg): -# self.arg = arg -# self.f = f -# self.__doc__ = f.__doc__ -# def __call__(self, *args, **kwds): -# return self.f(self.arg, *args, **kwds) diff --git a/src/sage/structure/coerce.pxi b/src/sage/structure/coerce.pxi index 6990f518c65..779c8715b18 100644 --- a/src/sage/structure/coerce.pxi +++ b/src/sage/structure/coerce.pxi @@ -1,78 +1,3 @@ -# These are shared inline functions. - -################################################################################# -# fast tests to verify no coercion is needed -################################################################################# - -cdef inline bint have_same_parent(left, right): - """ - Return nonzero true value if and only if left and right are - elements and have the same parent. - """ - # (We know at least one of the arguments is an Element. So if - # their types are *equal* (fast to check) then they are both - # Elements. Otherwise use the slower test via PY_TYPE_CHECK.) - if PY_TYPE(left) is PY_TYPE(right): - return (left)._parent is (right)._parent - - if PY_TYPE_CHECK(right, Element) and PY_TYPE_CHECK(left, Element): - return (left)._parent is (right)._parent - - return 0 - -cdef inline _verify_canonical_coercion_c(x, y): - if not have_same_parent(x,y): - raise RuntimeError, """There is a bug in the coercion code in SAGE. -Both x (=%s) and y (=%s) are supposed to have identical parents but they don't. -In fact, x has parent '%s' -whereas y has parent '%s'"""%(x,y,parent_c(x),parent_c(y)) - return x, y - -cdef inline bint have_same_base(Element x, Element y): - return x._parent._base is y._parent._base - -################################################################################# -# parent -################################################################################# -cdef inline parent_c(x): - if PY_TYPE_CHECK(x, Element): - return (x)._parent - elif hasattr(x, 'parent'): - return x.parent() - else: - return PY_TYPE(x) - -def parent(x): - return parent_c(x) - -################################################################################# -# operators -################################################################################# - -cdef add, sub, mul, div, iadd, isub, imul, idiv -from operator import add, sub, mul, div, iadd, isub, imul, idiv - -cdef inline inplace_op(op): - return operator.__dict__['i'+op.__name__] - -cdef inline no_inplace_op(op): - return operator.__dict__[op.__name__[1:]] - -################################################################################# -# errors -################################################################################# -cdef _coerce_op_symbols = {'mul':'*', 'add':'+', 'sub':'-', 'div':'/', 'imul': '*', 'iadd': '+', 'isub':'-', 'idiv':'/'} - -cdef inline arith_error_message(x, y, op): - try: - n = _coerce_op_symbols[op.__name__] - except KeyError: - n = op.__name__ - return "unsupported operand parent(s) for '%s': '%s' and '%s'"%(n, parent_c(x), parent_c(y)) - cdef enum: - # 3 references: handle, scope container, and arithmetic call stack + # Inplace optimizations disabled, see Trac #1038 inplace_threshold = 0 - - - diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx index 1d7cc4f8515..53c948b97b7 100644 --- a/src/sage/structure/coerce.pyx +++ b/src/sage/structure/coerce.pyx @@ -73,12 +73,13 @@ see the documentation for Parent. # http://www.gnu.org/licenses/ #***************************************************************************** - include "sage/ext/stdsage.pxi" from cpython.object cimport * -include "coerce.pxi" +cdef add, sub, mul, div, iadd, isub, imul, idiv import operator +operator_dict = operator.__dict__ +from operator import add, sub, mul, div, iadd, isub, imul, idiv from sage_object cimport SageObject from sage.categories.map cimport Map @@ -87,11 +88,15 @@ from sage.categories.morphism import IdentityMorphism from sage.categories.action import InverseAction, PrecomposedAction from parent cimport Set_PythonType from coerce_exceptions import CoercionException +from element cimport arith_error_message, parent_c import sys, traceback from coerce_actions import LeftModuleAction, RightModuleAction, IntegerMulAction +from sage.misc.lazy_import import LazyImport +parent = LazyImport('sage.structure.all', 'parent', deprecation=17533) + cpdef py_scalar_parent(py_type): """ Returns the Sage equivalent of the given python type, if one exists. @@ -131,7 +136,7 @@ cdef bint is_Integer(x): global _Integer if _Integer is None: from sage.rings.integer import Integer as _Integer - return PY_TYPE_CHECK_EXACT(x, _Integer) or PY_TYPE_CHECK_EXACT(x, int) + return type(x) is _Integer or type(x) is int cdef class CoercionModel_cache_maps(CoercionModel): """ @@ -385,7 +390,7 @@ cdef class CoercionModel_cache_maps(CoercionModel): return self._exception_stack - def explain(self, xp, yp, op=operator.mul, int verbosity=2): + def explain(self, xp, yp, op=mul, int verbosity=2): """ This function can be used to understand what coercions will happen for an arithmetic operation between xp and yp (which may be either @@ -665,7 +670,7 @@ cdef class CoercionModel_cache_maps(CoercionModel): cpdef Parent division_parent(self, Parent parent): r""" Deduces where the result of division in parent lies by calculating - the inverse of ``parent.one_element()`` or ``parent.an_element()``. + the inverse of ``parent.one()`` or ``parent.an_element()``. The result is cached. @@ -690,7 +695,7 @@ cdef class CoercionModel_cache_maps(CoercionModel): except KeyError: pass try: - ret = parent_c(~parent.one_element()) + ret = parent_c(~parent.one()) except Exception: self._record_exception() ret = parent_c(~parent.an_element()) @@ -972,13 +977,13 @@ cdef class CoercionModel_cache_maps(CoercionModel): return self.canonical_coercion(x, y) # Allow coercion of 0 even if no coercion from Z - if is_Integer(x) and not x and not PY_TYPE_CHECK_EXACT(yp, type): + if is_Integer(x) and not x and type(yp) is not type: try: return yp(0), y except Exception: self._record_exception() - if is_Integer(y) and not y and not PY_TYPE_CHECK_EXACT(xp, type): + if is_Integer(y) and not y and type(xp) is not type: try: return x, xp(0) except Exception: @@ -1396,7 +1401,7 @@ cdef class CoercionModel_cache_maps(CoercionModel): #print "found1", action return action - if PY_TYPE(R) == type: + if type(R) is type: sageR = py_scalar_parent(R) if sageR is not None: action = self.discover_action(sageR, S, op, s=s) @@ -1405,7 +1410,7 @@ cdef class CoercionModel_cache_maps(CoercionModel): action = PrecomposedAction(action, sageR._internal_coerce_map_from(R), None) return action - if PY_TYPE(S) == type: + if type(S) is type: sageS = py_scalar_parent(S) if sageS is not None: action = self.discover_action(R, sageS, op, r=r) @@ -1416,7 +1421,8 @@ cdef class CoercionModel_cache_maps(CoercionModel): if op.__name__[0] == 'i': try: - a = self.discover_action(R, S, no_inplace_op(op), r, s) + no_inplace_op = operator_dict[op.__name__[1:]] + a = self.discover_action(R, S, no_inplace_op, r, s) if a is not None: is_inverse = isinstance(a, InverseAction) if is_inverse: a = ~a diff --git a/src/sage/structure/coerce_actions.pyx b/src/sage/structure/coerce_actions.pyx index 15d639c5a8f..d3e5181e7df 100644 --- a/src/sage/structure/coerce_actions.pyx +++ b/src/sage/structure/coerce_actions.pyx @@ -15,6 +15,7 @@ include "sage/ext/stdsage.pxi" include "sage/ext/interrupt.pxi" from cpython.int cimport * from cpython.number cimport * +from sage.structure.element cimport parent_c include "coerce.pxi" from coerce_exceptions import CoercionException diff --git a/src/sage/structure/element.pxd b/src/sage/structure/element.pxd index 72804c08cb3..78f7a4c704a 100644 --- a/src/sage/structure/element.pxd +++ b/src/sage/structure/element.pxd @@ -1,15 +1,38 @@ - -# It is important to keep this line here, basically to trick Pyrex. -# If you remove this line then other modules that cimport element -# from other directories will fail. - -cimport sage.structure.sage_object -from sage.structure.parent cimport Parent - -cimport sage_object -import sage_object - -cdef class Element(sage_object.SageObject): +from sage_object cimport SageObject +from parent cimport Parent +from cpython.number cimport PyNumber_Check + +cdef inline parent_c(x): + if isinstance(x, Element): + return (x)._parent + # Fast check for "number" types, including int and float + if PyNumber_Check(x): + return type(x) + try: + p = x.parent + except AttributeError: + return type(x) + else: + return p() + +cdef inline bint have_same_parent_c(left, right): + """ + Return ``True`` if and only if ``left`` and ``right`` have the + same parent. + """ + # We know at least one of the arguments is an Element. So if + # their types are *equal* (fast to check) then they are both + # Elements. Otherwise use the slower test via isinstance(). + if type(left) is type(right): + return (left)._parent is (right)._parent + if isinstance(right, Element) and isinstance(left, Element): + return (left)._parent is (right)._parent + return False + + +cdef str arith_error_message(x, y, op) + +cdef class Element(SageObject): cdef Parent _parent cdef _richcmp_c_impl(left, Element right, int op) cdef int _cmp_c_impl(left, Element right) except -2 @@ -104,8 +127,11 @@ cdef class InfinityElement(RingElement): cdef class Vector(ModuleElement): cdef Py_ssize_t _degree - # Returns the dot product, using the simple metric $e_i \cdot e_j = \delta_{ij}$. - cpdef Element _dot_product_(Vector left, Vector right) # override, call if parents the same + # Return the dot product using the simple metric + # $e_i \cdot e_j = \delta_{ij}$. The first assumes that the parents + # are equal, both assume that the degrees are equal. + cpdef Element _dot_product_(Vector left, Vector right) + cpdef Element _dot_product_coerce_(Vector left, Vector right) cpdef Vector _pairwise_product_(Vector left, Vector right) # override, call if parents the same diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 7138f68e2a8..07acf0f930b 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -62,7 +62,7 @@ Elements typically define a method ``_new_c``, e.g., cdef _new_c(self, defining data): cdef FreeModuleElement_generic_dense x - x = PY_NEW(FreeModuleElement_generic_dense) + x = FreeModuleElement_generic_dense.__new__(FreeModuleElement_generic_dense) x._parent = self._parent x._entries = v @@ -154,14 +154,6 @@ be accessible from the calling function after this operation. implementation will get called. """ - -cdef extern from *: - ctypedef struct RefPyObject "PyObject": - int ob_refcnt - - - - ################################################################## # Generic element, so all this functionality must be defined # by any element. Derived class must call __init__ @@ -170,10 +162,14 @@ cdef extern from *: include "sage/ext/cdefs.pxi" include "sage/ext/stdsage.pxi" include "sage/ext/python.pxi" +include "coerce.pxi" -import operator, types +from cpython.ref cimport PyObject + +import types import sys -import traceback +cdef add, sub, mul, div, iadd, isub, imul, idiv +from operator import add, sub, mul, div, iadd, isub, imul, idiv import sage.misc.sageinspect as sageinspect @@ -219,6 +215,111 @@ def py_scalar_to_element(py): else: raise TypeError("Not a scalar") + +def parent(x): + """ + Return the parent of the element ``x``. + + Usually, this means the mathematical object of which ``x`` is an + element. + + INPUT: + + - ``x`` -- an element + + OUTPUT: + + - if ``x`` is a Sage :class:`Element`, return ``x.parent()``. + + - if ``x`` has a ``parent`` method and ``x`` does not have an + ``__int__`` or ``__float__`` method, return ``x.parent()``. + + - otherwise, return ``type(x)``. + + .. SEEALSO:: + + `Parents, Conversion and Coercion `_ + Section in the Sage Tutorial + + EXAMPLES:: + + sage: a = 42 + sage: parent(a) + Integer Ring + sage: b = 42/1 + sage: parent(b) + Rational Field + sage: c = 42.0 + sage: parent(c) + Real Field with 53 bits of precision + + Some more complicated examples:: + + sage: x = Partition([3,2,1,1,1]) + sage: parent(x) + Partitions + sage: v = vector(RDF, [1,2,3]) + sage: parent(v) + Vector space of dimension 3 over Real Double Field + + The following are not considered to be elements, so the type is + returned:: + + sage: d = int(42) # Python int + sage: parent(d) + + sage: L = range(10) + sage: parent(L) + + """ + return parent_c(x) + +def have_same_parent(left, right): + """ + Return ``True`` if and only if ``left`` and ``right`` have the + same parent. + + .. WARNING:: + + This function assumes that at least one of the arguments is a + Sage :class:`Element`. When in doubt, use the slower + ``parent(left) is parent(right)`` instead. + + EXAMPLES:: + + sage: from sage.structure.element import have_same_parent + sage: have_same_parent(1, 3) + True + sage: have_same_parent(1, 1/2) + False + sage: have_same_parent(gap(1), gap(1/2)) + True + + These have different types but the same parent:: + + sage: a = RLF(2) + sage: b = exp(a) + sage: type(a) + + sage: type(b) + + sage: have_same_parent(a, b) + True + """ + return have_same_parent_c(left, right) + + +cdef dict _coerce_op_symbols = {'mul':'*', 'add':'+', 'sub':'-', 'div':'/', 'imul': '*', 'iadd': '+', 'isub':'-', 'idiv':'/'} + +cdef str arith_error_message(x, y, op): + name = op.__name__ + try: + name = _coerce_op_symbols[name] + except KeyError: + pass + return "unsupported operand parent(s) for '%s': '%s' and '%s'"%(name, parent_c(x), parent_c(y)) + + def is_Element(x): """ Return ``True`` if x is of type Element. @@ -233,7 +334,7 @@ def is_Element(x): """ return IS_INSTANCE(x, Element) -cdef class Element(sage_object.SageObject): +cdef class Element(SageObject): """ Generic element of a structure. All other types of elements (RingElement, ModuleElement, etc) derive from this type. @@ -533,7 +634,7 @@ cdef class Element(sage_object.SageObject): """ from sage.categories.objects import Objects tester = self._tester(**options) - sage_object.SageObject._test_category(self, tester = tester) + SageObject._test_category(self, tester = tester) category = self.category() # Tests that self inherits methods from the categories if not is_extension_type(self.__class__): @@ -828,7 +929,7 @@ cdef class Element(sage_object.SageObject): sage: (v+w).__nonzero__() False """ - return self != self._parent.zero_element() + return self != self._parent.zero() def is_zero(self): """ @@ -853,7 +954,7 @@ cdef class Element(sage_object.SageObject): """ global coercion_model cdef int r - if not have_same_parent(left, right): + if not have_same_parent_c(left, right): if left is None or left is Ellipsis: return -1 elif right is None or right is Ellipsis: @@ -887,7 +988,7 @@ cdef class Element(sage_object.SageObject): """ global coercion_model cdef int r - if not have_same_parent(left, right): + if not have_same_parent_c(left, right): if left is None or left is Ellipsis: return _rich_to_bool(op, -1) elif right is None or right is Ellipsis: @@ -1249,11 +1350,11 @@ cdef class ModuleElement(Element): # (We know at least one of the arguments is a ModuleElement. So if # their types are *equal* (fast to check) then they are both # ModuleElements. Otherwise use the slower test via PY_TYPE_CHECK.) - if have_same_parent(left, right): + if have_same_parent_c(left, right): # If we hold the only references to this object, we can # safely mutate it. NOTE the threshold is different by one # for __add__ and __iadd__. - if (left).ob_refcnt < inplace_threshold: + if (left).ob_refcnt < inplace_threshold: return (left)._iadd_(right) else: return (left)._add_(right) @@ -1265,8 +1366,8 @@ cdef class ModuleElement(Element): raise TypeError(arith_error_message(left, right, add)) def __iadd__(ModuleElement self, right): - if have_same_parent(self, right): - if (self).ob_refcnt <= inplace_threshold: + if have_same_parent_c(self, right): + if (self).ob_refcnt <= inplace_threshold: return self._iadd_(right) else: return self._add_(right) @@ -1286,8 +1387,8 @@ cdef class ModuleElement(Element): Top-level subtraction operator for ModuleElements. See extensive documentation at the top of element.pyx. """ - if have_same_parent(left, right): - if (left).ob_refcnt < inplace_threshold: + if have_same_parent_c(left, right): + if (left).ob_refcnt < inplace_threshold: return (left)._isub_(right) else: return (left)._sub_(right) @@ -1300,8 +1401,8 @@ cdef class ModuleElement(Element): return left._add_(-right) def __isub__(ModuleElement self, right): - if have_same_parent(self, right): - if (self).ob_refcnt <= inplace_threshold: + if have_same_parent_c(self, right): + if (self).ob_refcnt <= inplace_threshold: return self._isub_(right) else: return self._sub_(right) @@ -1340,14 +1441,14 @@ cdef class ModuleElement(Element): return (left)._mul_long(PyInt_AS_LONG(right)) if PyInt_CheckExact(left): return (right)._mul_long(PyInt_AS_LONG(left)) - if have_same_parent(left, right): + if have_same_parent_c(left, right): raise TypeError(arith_error_message(left, right, mul)) # Always do this global coercion_model return coercion_model.bin_op(left, right, mul) def __imul__(left, right): - if have_same_parent(left, right): + if have_same_parent_c(left, right): raise TypeError # Always do this global coercion_model @@ -1432,7 +1533,7 @@ cdef class MonoidElement(Element): See extensive documentation at the top of element.pyx. """ global coercion_model - if have_same_parent(left, right): + if have_same_parent_c(left, right): return (left)._mul_(right) try: return coercion_model.bin_op(left, right, mul) @@ -1490,7 +1591,7 @@ cdef class MonoidElement(Element): raise ValueError("negative number of powers requested") elif n == 0: return [] - x = self._parent.one_element() + x = self._parent.one() l = [x] for i in xrange(n - 1): x = x * self @@ -1552,7 +1653,7 @@ cdef class MultiplicativeGroupElement(MonoidElement): raise ArithmeticError("addition not defined in a multiplicative group") def __div__(left, right): - if have_same_parent(left, right): + if have_same_parent_c(left, right): return left._div_(right) global coercion_model return coercion_model.bin_op(left, right, div) @@ -1565,9 +1666,12 @@ cdef class MultiplicativeGroupElement(MonoidElement): return self * ~right def __invert__(self): + r""" + Return the inverse of ``self``. + """ if self.is_one(): return self - return 1/self + return self.parent().one()/self def is_RingElement(x): @@ -1579,7 +1683,7 @@ def is_RingElement(x): cdef class RingElement(ModuleElement): ################################################## def is_one(self): - return self == self._parent.one_element() + return self == self._parent.one() ################################## # Fast long add/sub path. @@ -1591,8 +1695,8 @@ cdef class RingElement(ModuleElement): See extensive documentation at the top of element.pyx. """ - if have_same_parent(left, right): - if (left).ob_refcnt < inplace_threshold: + if have_same_parent_c(left, right): + if (left).ob_refcnt < inplace_threshold: return (left)._iadd_(right) else: return (left)._add_(right) @@ -1615,8 +1719,8 @@ cdef class RingElement(ModuleElement): See extensive documentation at the top of element.pyx. """ cdef long n - if have_same_parent(left, right): - if (left).ob_refcnt < inplace_threshold: + if have_same_parent_c(left, right): + if (left).ob_refcnt < inplace_threshold: return (left)._isub_(right) else: return (left)._sub_(right) @@ -1751,8 +1855,8 @@ cdef class RingElement(ModuleElement): # (We know at least one of the arguments is a RingElement. So if their # types are *equal* (fast to check) then they are both RingElements. # Otherwise use the slower test via PY_TYPE_CHECK.) - if have_same_parent(left, right): - if (left).ob_refcnt < inplace_threshold: + if have_same_parent_c(left, right): + if (left).ob_refcnt < inplace_threshold: return (left)._imul_(right) else: return (left)._mul_(right) @@ -1770,8 +1874,8 @@ cdef class RingElement(ModuleElement): raise TypeError(arith_error_message(self, right, mul)) def __imul__(left, right): - if have_same_parent(left, right): - if (left).ob_refcnt <= inplace_threshold: + if have_same_parent_c(left, right): + if (left).ob_refcnt <= inplace_threshold: return (left)._imul_(right) else: return (left)._mul_(right) @@ -1864,7 +1968,7 @@ cdef class RingElement(ModuleElement): raise ValueError("negative number of powers requested") elif n == 0: return [] - x = self._parent.one_element() + x = self._parent.one() l = [x] for i in xrange(n - 1): x = x * self @@ -1886,8 +1990,8 @@ cdef class RingElement(ModuleElement): Top-level multiplication operator for ring elements. See extensive documentation at the top of element.pyx. """ - if have_same_parent(self, right): - if (self).ob_refcnt < inplace_threshold: + if have_same_parent_c(self, right): + if (self).ob_refcnt < inplace_threshold: return (self)._idiv_(right) else: return (self)._div_(right) @@ -1912,8 +2016,8 @@ cdef class RingElement(ModuleElement): Top-level division operator for ring elements. See extensive documentation at the top of element.pyx. """ - if have_same_parent(self, right): - if (self).ob_refcnt <= inplace_threshold: + if have_same_parent_c(self, right): + if (self).ob_refcnt <= inplace_threshold: return (self)._idiv_(right) else: return (self)._div_(right) @@ -2139,7 +2243,7 @@ cdef class CommutativeRingElement(RingElement): """ #Check if the parents are the same: - if have_same_parent(self, x): + if have_same_parent_c(self, x): # First we test some generic conditions: try: if x.is_zero(): @@ -2429,7 +2533,7 @@ cdef class Vector(ModuleElement): raise NotImplementedError def __imul__(left, right): - if have_same_parent(left, right): + if have_same_parent_c(left, right): return (left)._dot_product_(right) # Always do this global coercion_model @@ -2596,13 +2700,16 @@ cdef class Vector(ModuleElement): TypeError: unsupported operand parent(s) for '*': 'Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Rational Field' and 'Univariate Polynomial Ring in y over Rational Field' """ - if have_same_parent(left, right): + if have_same_parent_c(left, right): return (left)._dot_product_(right) # Always do this global coercion_model return coercion_model.bin_op(left, right, mul) cpdef Element _dot_product_(Vector left, Vector right): + return left._dot_product_coerce_(right) + + cpdef Element _dot_product_coerce_(Vector left, Vector right): raise TypeError(arith_error_message(left, right, mul)) cpdef Vector _pairwise_product_(Vector left, Vector right): @@ -2675,7 +2782,7 @@ cdef class Matrix(ModuleElement): raise NotImplementedError def __imul__(left, right): - if have_same_parent(left, right): + if have_same_parent_c(left, right): return (left)._matrix_times_matrix_(right) else: global coercion_model @@ -2862,7 +2969,7 @@ cdef class Matrix(ModuleElement): [33 36] [39 42] [45 48]] """ - if have_same_parent(left, right): + if have_same_parent_c(left, right): return (left)._matrix_times_matrix_(right) else: global coercion_model @@ -2918,9 +3025,9 @@ cdef class Matrix(ModuleElement): [ (-t^3 + t^2 - t - 6)/(t^5 - 3*t) (t^4 + 2*t^3 + t^2 - t - 2)/(t^5 - 3*t)] """ cdef Matrix rightinv - if have_same_parent(left, right): + if have_same_parent_c(left, right): rightinv = ~right - if have_same_parent(left,rightinv): + if have_same_parent_c(left,rightinv): return (left)._matrix_times_matrix_(rightinv) else: return ((left.change_ring(rightinv.parent().base_ring())))._matrix_times_matrix_(rightinv) @@ -3101,7 +3208,7 @@ cdef class FieldElement(CommutativeRingElement): sage: R. = QQ[] sage: S. = R.quo(y^2 + 1) sage: S.is_field = lambda : False - sage: F = Frac(S); u = F.one_element() + sage: F = Frac(S); u = F.one() sage: u.quo_rem(u) (1, 0) """ @@ -3186,8 +3293,6 @@ cdef class PlusInfinityElement(InfinityElement): cdef class MinusInfinityElement(InfinityElement): pass -include "coerce.pxi" - ################################################################################# # @@ -3401,7 +3506,7 @@ cdef class NamedBinopMethod: self._func(x, **kwds) else: x, y = self._self, x - if not have_same_parent(x, y): + if not have_same_parent_c(x, y): old_x = x x,y = coercion_model.canonical_coercion(x, y) if old_x is x: diff --git a/src/sage/structure/graphics_file.py b/src/sage/structure/graphics_file.py index 96e5ff4ecfd..aa0a897b39d 100644 --- a/src/sage/structure/graphics_file.py +++ b/src/sage/structure/graphics_file.py @@ -204,7 +204,11 @@ def sagenb_embedding(self): """ from sage.misc.temporary_file import graphics_filename ext = "." + Mime.extension(self.mime()) - self.save_as(graphics_filename(ext=ext)) + fn = graphics_filename(ext=ext) + self.save_as(fn) + # Client-server sagenb requires this to be world-readable. + # See Trac #17755. + os.chmod(fn, 0o644) def graphics_from_save(save_function, preferred_mime_types, diff --git a/src/sage/structure/list_clone.pyx b/src/sage/structure/list_clone.pyx index 4b550d32264..6385d6d3866 100644 --- a/src/sage/structure/list_clone.pyx +++ b/src/sage/structure/list_clone.pyx @@ -888,8 +888,8 @@ cdef class ClonableArray(ClonableElement): 2 """ cdef ClonableArray res - #res = type(self).__new__(type(self), self._parent) - res = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + res = t.__new__(t) res._parent = self._parent res._list = self._list[:] if HAS_DICTIONARY(self): @@ -984,7 +984,7 @@ def _make_array_clone(clas, parent, list, needs_check, is_immutable, dic): 2 """ cdef ClonableArray res - res = PY_NEW(clas) + res = clas.__new__(clas) res._parent = parent res._list = list res._needs_check = needs_check @@ -1673,7 +1673,8 @@ cdef class ClonableIntArray(ClonableElement): 2 """ cdef ClonableIntArray res - res = PY_NEW_SAME_TYPE(self) + cdef type t = type(self) + res = t.__new__(t) res._parent = self._parent if self: res._alloc_(self._len) @@ -1774,7 +1775,7 @@ def _make_int_array_clone(clas, parent, lst, needs_check, is_immutable, dic): 2 """ cdef ClonableIntArray res - res = PY_NEW(clas) + res = clas.__new__(clas) ClonableIntArray.__init__(res, parent, lst, needs_check, is_immutable) if dic is not None: res.__dict__ = dic diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 1403325faff..a723c87178e 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -94,7 +94,7 @@ This came up in some subtle bug once:: """ -cimport element +from element cimport parent_c cimport sage.categories.morphism as morphism cimport sage.categories.map as map from sage.structure.debug_options import debug @@ -115,22 +115,6 @@ from sage.structure.misc cimport AttributeErrorMessage cdef AttributeErrorMessage dummy_error_message = AttributeErrorMessage(None, '') dummy_attribute_error = AttributeError(dummy_error_message) -# TODO: define this once? - -cdef object elt_parent = None - -cdef inline parent_c(x): - if PY_TYPE_CHECK(x, element.Element): - return (x)._parent -# elif hasattr(x, 'parent'): -# return x.parent() -# else: -# return PY_TYPE(x) - else: - try: - return x.parent() - except AttributeError: - return PY_TYPE(x) cdef _record_exception(): from element import get_coercion_model @@ -141,7 +125,7 @@ cdef bint is_Integer(x): global _Integer if _Integer is None: from sage.rings.integer import Integer as _Integer - return PY_TYPE_CHECK_EXACT(x, _Integer) or PY_TYPE_CHECK_EXACT(x, int) + return type(x) is _Integer or type(x) is int # for override testing cdef extern from "descrobject.h": @@ -818,6 +802,7 @@ cdef class Parent(category_object.CategoryObject): pass running ._test_eq() . . . pass running ._test_euclidean_degree() . . . pass + running ._test_gcd_vs_xgcd() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_one() . . . pass running ._test_pickling() . . . pass @@ -886,6 +871,7 @@ cdef class Parent(category_object.CategoryObject): _test_enumerated_set_iter_list _test_eq _test_euclidean_degree + _test_gcd_vs_xgcd _test_not_implemented_methods _test_one _test_pickling @@ -2479,9 +2465,9 @@ cdef class Parent(category_object.CategoryObject): else: raise TypeError("_coerce_map_from_ must return None, a boolean, a callable, or an explicit Map (called on %s, got %s)" % (type(self), type(user_provided_mor))) - if (PY_TYPE_CHECK_EXACT(mor, DefaultConvertMap) or - PY_TYPE_CHECK_EXACT(mor, DefaultConvertMap_unique) or - PY_TYPE_CHECK_EXACT(mor, NamedConvertMap)) and not mor._force_use: + if (type(mor) is DefaultConvertMap or + type(mor) is DefaultConvertMap_unique or + type(mor) is NamedConvertMap) and not mor._force_use: # If there is something better in the list, try to return that instead # This is so, for example, _coerce_map_from_ can return True but still # take advantage of the _populate_coercion_lists_ data. diff --git a/src/sage/structure/sage_object.pyx b/src/sage/structure/sage_object.pyx index 73148793bd0..a5506b7723e 100644 --- a/src/sage/structure/sage_object.pyx +++ b/src/sage/structure/sage_object.pyx @@ -10,16 +10,16 @@ from sage.misc.sage_unittest import TestSuite sys_modules = sys.modules +from sage.misc.lazy_import import LazyImport +have_same_parent = LazyImport('sage.structure.element', 'have_same_parent', deprecation=17533) + # change to import zlib to use zlib instead; but this # slows down loading any data stored in the other format import zlib; comp = zlib import bz2; comp_other = bz2 -base=None cdef process(s): - if base is not None and not os.path.isabs(s): - s = os.path.join(base,s) if s[-5:] != '.sobj': return s + '.sobj' else: @@ -306,7 +306,15 @@ cdef class SageObject: version of Sage it was created. This only works on Python classes that derive from SageObject. + + TESTS:: + + sage: v = DiGraph().version() + doctest:... DeprecationWarning: version() is deprecated. + See http://trac.sagemath.org/2536 for details. """ + from sage.misc.superseded import deprecation + deprecation(2536, 'version() is deprecated.') try: return self.__version except AttributeError: @@ -371,25 +379,18 @@ cdef class SageObject: reload. The database directory is ``$HOME/.sage/db`` + + TESTS:: + + sage: SageObject().db("Test") + doctest:... DeprecationWarning: db() is deprecated. + See http://trac.sagemath.org/2536 for details. """ - #if name is None: - # name = self._db_name() + from sage.misc.superseded import deprecation + deprecation(2536, 'db() is deprecated.') from sage.misc.all import SAGE_DB return self.dump('%s/%s'%(SAGE_DB,name), compress=compress) -## def _db_name(self): -## t = str(type(self)).split()[-1][1:-2] -## try: -## d = str(self._defining_params_()) -## except AttributeError: -## d = str(self) -## d = '_'.join(d.split()) -## from sage.misc.all import SAGE_DB -## if not os.path.exists('%s/%s'%(SAGE_DB, t)): -## os.makedirs(t) -## return '%s/%s'%(t, d) - - ############################################################################# # Category theory / structure ############################################################################# @@ -831,52 +832,19 @@ cdef class SageObject: from sage.interfaces.gp import gp return self._interface_init_(gp) - -###################################################### -# A python-accessible version of the one in coerce.pxi -# Where should it be? - -def have_same_parent(self, other): - """ - EXAMPLES:: - - sage: from sage.structure.sage_object import have_same_parent - sage: have_same_parent(1, 3) - True - sage: have_same_parent(1, 1/2) - False - sage: have_same_parent(gap(1), gap(1/2)) - True - """ - from sage.structure.coerce import parent - return parent(self) == parent(other) - ################################################################## def load(*filename, compress=True, verbose=True): r""" Load Sage object from the file with name filename, which will have an ``.sobj`` extension added if it doesn't have one. Or, if the input - is a filename ending in ``.py``, ``.pyx``, or ``.sage``, load that - file into the current running session. If the filename ends in - ``.f`` or ``.f90``, it is compiled as Fortran code and loaded. + is a filename ending in ``.py``, ``.pyx``, ``.sage``, ``.spyx``, + ``.f``, ``.f90`` or ``.m``, load that file into the current running + session. Loaded files are not loaded into their own namespace, i.e., this is much more like Python's ``execfile`` than Python's ``import``. - .. NOTE:: - - There is also a special Sage command (that is not - available in Python) called load that you use by typing - - :: - - sage: load filename.sage # not tested - - The documentation below is not for that command. The - documentation for load is almost identical to that for attach. - Type attach? for help on attach. - This function also loads a ``.sobj`` file over a network by specifying the full URL. (Setting ``verbose = False`` suppresses the loading progress indicator.) @@ -920,14 +888,15 @@ def load(*filename, compress=True, verbose=True): """ import sage.repl.load if len(filename) != 1: - v = [load(file, compress=True, verbose=True) for file in filename] - ret = False + v = [load(file, compress=compress, verbose=verbose) for file in filename] + # Return v if one of the filenames refers to an object and not + # a loadable filename. for file in filename: if not sage.repl.load.is_loadable_filename(file): - ret = True - return v if ret else None - else: - filename = filename[0] + return v + return + + filename = filename[0] if sage.repl.load.is_loadable_filename(filename): sage.repl.load.load(filename, globals()) @@ -939,11 +908,6 @@ def load(*filename, compress=True, verbose=True): from sage.misc.remote_file import get_remote_file filename = get_remote_file(filename, verbose=verbose) tmpfile_flag = True - elif lower.endswith('.f') or lower.endswith('.f90'): - from sage.misc.inline_fortran import fortran - with open(filename) as f: - fortran(f.read(), globals()) - return else: tmpfile_flag = False filename = process(filename) @@ -965,7 +929,7 @@ def load(*filename, compress=True, verbose=True): def save(obj, filename=None, compress=True, **kwds): """ Save ``obj`` to the file with name ``filename``, which will have an - ``.sobj`` extension added if it doesn't have one, or if ``obj`` + ``.sobj`` extension added if it doesn't have one and if ``obj`` doesn't have its own ``save()`` method, like e.g. Python tuples. For image objects and the like (which have their own ``save()`` method), @@ -1014,10 +978,8 @@ def save(obj, filename=None, compress=True, **kwds): # Add '.sobj' if the filename currently has no extension # and also if the object doesn't have its own save() method (#11577) # since we otherwise assume below it is an image object: - if (os.path.splitext(filename)[1] == '' - or (os.path.splitext(filename)[1] != '.sobj' - and not hasattr(obj,"save"))): - filename += '.sobj' + if not os.path.splitext(filename)[1] or not hasattr(obj, "save"): + filename = process(filename) if filename.endswith('.sobj'): try: @@ -1504,7 +1466,7 @@ def unpickle_all(dir = None, debug=False, run_test_suite=False): """ if dir is None: pickle_jar=True - from sage.misc.misc import SAGE_EXTCODE + from sage.env import SAGE_EXTCODE dir = os.path.join(SAGE_EXTCODE,'pickle_jar','pickle_jar.tar.bz2') else: pickle_jar=False @@ -1554,4 +1516,3 @@ def unpickle_all(dir = None, debug=False, run_test_suite=False): print "Failed to unpickle %s objects."%j if debug: return tracebacks - diff --git a/src/sage/structure/sequence.py b/src/sage/structure/sequence.py index 36b53430efc..f98746c294e 100644 --- a/src/sage/structure/sequence.py +++ b/src/sage/structure/sequence.py @@ -284,21 +284,17 @@ def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=Non if universe is None: # no type errors raised. universe = coerce.parent(x[len(x)-1]) + from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.pbori import BooleanMonomialMonoid from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.quotient_ring import is_QuotientRing - from sage.rings.polynomial.pbori import BooleanMonomialMonoid - if is_MPolynomialRing(universe) or \ - (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())) or \ - isinstance(universe, BooleanMonomialMonoid): - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence - try: - return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) - except (TypeError,AttributeError): - return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types) + if is_MPolynomialRing(universe) or isinstance(universe, BooleanMonomialMonoid) or (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())): + return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) else: return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types) + class Sequence_generic(sage.structure.sage_object.SageObject, list): """ A mutable list of elements with a common guaranteed universe, diff --git a/src/sage/structure/wrapper_parent.pxd b/src/sage/structure/wrapper_parent.pxd deleted file mode 100644 index 3000808b21f..00000000000 --- a/src/sage/structure/wrapper_parent.pxd +++ /dev/null @@ -1,12 +0,0 @@ -from sage.structure.parent cimport Parent -from sage.categories.morphism cimport Morphism -from sage.structure.element cimport AlgebraElement, Element, ModuleElement, RingElement - -cdef class WrapperParent_model0(Parent): - cdef Parent R - -cdef class WrapperParent_model1(Parent): - cdef Parent R - -cdef class WrapperElement(AlgebraElement): - cdef Element val diff --git a/src/sage/structure/wrapper_parent.pyx b/src/sage/structure/wrapper_parent.pyx deleted file mode 100644 index 95c8ee6296a..00000000000 --- a/src/sage/structure/wrapper_parent.pyx +++ /dev/null @@ -1,196 +0,0 @@ -""" -This module provides a general class that wraps other parents and element types. - -The purpose of this functionality is to be able to add morphisms and actions to the coercion system that interact with objects that are otherwise unique. For example, one would use wrappers to implement: -0. Residue Fields where one has a fast implementation for the arithmetic of the quotient, for example $O_K / p O_K$ for $K$ a number field, $O_K$ its maximal order and $p$ a prime of $O_K$. This residue field includes a coercion map from $O_K$. -1. Completions at a places of number fields. There is a morphism added that maps to the completed ring, which is represented as a finite extension of $\QQ_p$ -2. G-sets for groups acting on an object that would otherwise be unique. - -There are three options for implementing such a wrapper: -Option 0: WrapperParent_model0 - With this option, one inherits from the class WrapperParent_model0. Elements are not wrapped, but instead merely have their parents changed to the wrapping parent. This will work fine for most parent and element types, but can break when parents and elements are either highly optimized or implemented strangely. In particularly, the following are failure modes for this option: - a) If the parent caches elements (as in IntegerMod_int), then the elements in that cache will point to the wrong parent. Thus the sum of two elements of the wrapper could be an element of the wrapped object, which is undesirable. - b) If the parent is written in Cython, more work must be done, which is not necessarily possible. See FiniteField_givaro for an example where option 0 just fails (because various methods in that class assume that the parent is of type FiniteField_givaro). - This option should generally be fast because there are no wrappers around elements. It should also not be all that difficult to implement. - When inheriting from this class, you should do the following: - a) Check to ensure that your element's _make_new_with_parent_c correctly returns an element with parent set to the given argument (default behavior is to set parent and return self). This would not work in IntegerMod_int for example, because self.__modulus.table would still be wrong. - b) Make sure that your elements don't call cdefed functions or access cdefed attributes of the parent. If they do, you need to duplicate that behavior in your subclass of the wrapper. - c) Override __call__ - d) Pass in the correct morphisms/actions to the __init__ method of WrapperParent_model0. This may involve writing a custom Morphism extension. - e) Write any functions that you want in addition to the functions of the wrapped parent or to replace the wrapped parents method. - f) Update this list to reflect any lessons you've learned. - -Option 1: WrapperParent_model1 - With this option, one wraps both the parent and the element. On the downside, there will be a speed penalty to arithmetic. On the plus side, this method should work for classes that fail option 0. It should also be easier to work with. - When using this option, you should do the following: - a) Write any morphisms that you need in order to make the desired coercion work. Construct a WrapperParent_model1 with the appropriate arguments. - b) Update this list to reflect any lessons you've learned. - -Option 2: Write your own custom. - When you want speed but can't use option 1. See sage/rings/finite_rings/residue_field.pyx for examples (ResidueFiniteField_prime_modn, ResidueFiniteField_givaro and ResidueFiniteField_pari_ffelt) - -AUTHORS: - -- David Roe (2007-10-3) -""" - -#***************************************************************************** -# Copyright (C) 2007 David Roe -# William Stein -# -# Distributed under the terms of the GNU General Public License (GPL) -# -# http://www.gnu.org/licenses/ -#***************************************************************************** - -include "sage/ext/cdefs.pxi" -include "sage/ext/stdsage.pxi" - -import copy -import inspect -from sage.categories.all import Objects -from sage.categories.homset import Hom -from sage.rings.ring import Ring -from sage.categories.morphism import CallMorphism - -cdef class StealMorphism(Morphism): - """ - Represents a morphism S -> R that just sets the parent of x to R. - """ - def _repr_type(self): - return "Steal" - - cpdef Element _call_(self, x): - """ - Applies this morphism to the element x. - - NB: make sure the function _make_new_with_parent_c changes all of the state of the element to make it behave correctly with self.codomain() as a parent. - """ - y = copy.copy(x) - return (y)._make_new_with_parent_c(self.codomain()) - -cdef class WrapperParent_model0(Parent): - """ - This class is designed to wrap around unique parents to provide facility for different coercions, actions and embeddings. - - NB: See the comments at the top of the module for advantages and disadvantages of this class. - """ - def __init__(self, R, cat = None, coerce_from = [], actions = [], embeddings = []): - self.R = R - if cat is None: - cat = Objects() - stealS = StealMorphism(Hom(R, self, cat)) - stealR = StealMorphism(Hom(self, R, cat)) - # need to modify actions - Parent.__init__(self, R.base(), [stealS * f for f in coerce_from], actions, [f * stealR for f in embeddings]) - - def __call__(self, x): - """ - This call method needs to basically create a copy and then change appropriate fields such as parent so that the element behaves correctly as an element in self. - """ - raise NotImplementedError - - def trait_names(self): - """ - This function is here to provide tab completion for this parent. - """ - return [e[0] for e in inspect.getmembers(self.R)] - - def __getattr__(self, name): - """ - Transparently passes calls to methods and attributes of self down to the wrapped ring. - - Note that this doesn't work for cdefed methods and attributes, so if you parent is Cythoned you need to deal with such specially. - """ - try: - return self.R.__getattribute__(name) - except AttributeError: - return Parent.__getattribute__(name) - -cdef class WrapperParent_model1(Parent): - """ - """ - def __init__(self, R, cat = None, coerce_from = [], actions = [], embeddings = []): - self.R = R - if cat is None: - cat = Objects() - stealS = CallMorphism(Hom(R, self, cat)) - stealR = CallMorphism(Hom(self, R, cat)) - # need to modify actions - Parent.__init__(self, R.base(), [stealS * f for f in coerce_from], actions, [f * stealR for f in embeddings]) - - def __call__(self, x): - """ - Creates an element of self from x. - - NB: You need to override this if you subclass the WrapperElement class. - """ - return WrapperElement(self, x) - - def trait_names(self): - """ - This function is here to provide tab completion for this parent. - """ - return [e[0] for e in inspect.getmembers(self.R)] - - def __getattr__(self, name): - """ - Transparently passes calls to methods and attributes of self down to the wrapped ring. - - Note that this doesn't work for cdefed methods and attributes, so if you parent is Cythoned you need to deal with such specially. - """ - try: - return self.R.__getattribute__(name) - except AttributeError: - return Parent.__getattribute__(name) - -cdef class WrapperElement(AlgebraElement): - """ - Should work for Elements, ModuleElements, RingElements and AlgebraElements - """ - def __init__(self, parent, x): - self.val = x - Element.__init__(parent, x) - - def trait_names(self): - """ - This function is here to provide tab completion for this parent. - """ - return [e[0] for e in inspect.getmembers(self.val)] - - def __getattr__(self, name): - """ - Transparently passes calls to methods and attributes of self down to the wrapped ring. - - Note that this doesn't work for cdefed methods and attributes, so if you parent is Cythoned you need to deal with such specially. - """ - try: - return self.val.__getattribute__(name) - except AttributeError: - return AlgebraElement.__getattribute__(name) - - cdef _richcmp_c_impl(left, Element right, int op): - return (left.val)._richcmp_c(right, op) - cdef int _cmp_c_impl(left, Element right) except -2: - return (left.val)._cmp_c(right) - cdef base_extend_c_impl(self, Parent R): - return (self.val).base_extend_c(R) - cpdef ModuleElement _add_(self, ModuleElement right): - return self.val + (right).val - cpdef ModuleElement _sub_(self, ModuleElement right): - return self.val - (right).val - cpdef ModuleElement _neg_(self): - return -self.val - cpdef ModuleElement _lmul_(self, RingElement right): - return self.val * right - cpdef ModuleElement _rmul_(self, RingElement left): - return left * self.val - cdef RingElement coerce_to_base_ring(self, x): - if PY_TYPE_CHECK(self.val, RingElement): - return (self.val).coerce_to_base_ring(x) - else: - raise TypeError, "self is not actually a RingElement" - cpdef RingElement _mul_(self, RingElement right): - return self.val * (right).val - cpdef RingElement _div_(self, RingElement right): - return self.val / (right).val - diff --git a/src/sage/symbolic/constants_c.pyx b/src/sage/symbolic/constants_c.pyx index 2796591f696..d730cc21bc8 100644 --- a/src/sage/symbolic/constants_c.pyx +++ b/src/sage/symbolic/constants_c.pyx @@ -230,7 +230,7 @@ cdef class E(Expression): [0 e] """ global exp_one - exp_one = SR.one_element().exp() + exp_one = SR.one().exp() Expression.__init__(self, SR, exp_one) def __pow__(left, right, dummy): diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index c807c0a8d02..77aea5ad9df 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -2162,6 +2162,22 @@ cdef class Expression(CommutativeRingElement): sage: assert( SR(oo) >= SR(-oo) ) sage: assert( SR(oo) != SR(-oo) ) sage: assert( sqrt(2)*oo != I*oo ) + + The expression may be zero with integers but is not + when in the complex domain (:trac:`15571`):: + + sage: a,x = var('a,x') + sage: assume(a, 'integer') + sage: assume(x, 'integer') + sage: expr = a^(4*x) - (a^4)^x + sage: expr.is_zero() + True + sage: forget() + sage: assume(a, 'complex') + sage: assume(x, 'complex') + sage: expr.is_zero() + False + sage: forget() """ if self.is_relational(): # constants are wrappers around Sage objects, compare directly @@ -2223,7 +2239,7 @@ cdef class Expression(CommutativeRingElement): if self_is_zero: return False else: - return not bool(self == self._parent.zero_element()) + return not bool(self == self._parent.zero()) def test_relation(self, int ntests=20, domain=None, proof=True): """ @@ -5253,6 +5269,14 @@ cdef class Expression(CommutativeRingElement): 1 + (y + 1)*x + ((y + 1)^2)*x^2 + Order(x^3) sage: s.coefficients(x, sparse=False) [1, y + 1, (y + 1)^2] + + We can find coefficients of symbolic functions, :trac:`12255`:: + + sage: g = function('g', var('t')) + sage: f = 3*g + g**2 + t + sage: f.coefficients(g) + [[t, 0], [3, 1], [1, 2]] + """ if x is None: x = self.default_variable() @@ -8184,10 +8208,11 @@ cdef class Expression(CommutativeRingElement): def simplify_full(self): """ - Apply simplify_factorial, simplify_trig, simplify_rational, - simplify_log, and again simplify_rational to self (in that order). + Apply :meth:`simplify_factorial`, :meth:`simplify_rectform`, + :meth:`simplify_trig`, :meth:`simplify_rational`, and + then :meth:`expand_sum` to self (in that order). - ALIAS: simplify_full and full_simplify are the same. + ALIAS: ``simplify_full`` and ``full_simplify`` are the same. EXAMPLES:: @@ -8261,6 +8286,7 @@ cdef class Expression(CommutativeRingElement): x = x.simplify_rectform() x = x.simplify_trig() x = x.simplify_rational() + x = x.expand_sum() return x full_simplify = simplify_full @@ -8732,6 +8758,53 @@ cdef class Expression(CommutativeRingElement): factorial_simplify = simplify_factorial + def expand_sum(self): + r""" + For every symbolic sum in the given expression, try to expand it, + symbolically or numerically. + + While symbolic sum expressions with constant limits are evaluated + immediately on the command line, unevaluated sums of this kind can + result from, e.g., substitution of limit variables. + + INPUT: + + - ``self`` - symbolic expression + + EXAMPLES:: + + sage: (k,n) = var('k,n') + sage: ex = sum(abs(-k*k+n),k,1,n)(n=8); ex + sum(abs(-k^2 + 8), k, 1, 8) + sage: ex.expand_sum() + 162 + sage: f(x,k) = sum((2/n)*(sin(n*x)*(-1)^(n+1)), n, 1, k) + sage: f(x,2) + -2*sum((-1)^n*sin(n*x)/n, n, 1, 2) + sage: f(x,2).expand_sum() + -sin(2*x) + 2*sin(x) + + We can use this to do floating-point approximation as well:: + + sage: (k,n) = var('k,n') + sage: f(n)=sum(sqrt(abs(-k*k+n)),k,1,n) + sage: f(n=8) + sum(sqrt(abs(-k^2 + 8)), k, 1, 8) + sage: f(8).expand_sum() + sqrt(41) + sqrt(17) + 2*sqrt(14) + 3*sqrt(7) + 2*sqrt(2) + 3 + sage: f(8).expand_sum().n() + 31.7752256945384 + + See :trac:`9424` for making the following no longer raise + an error:: + + sage: f(8).n() + Traceback (most recent call last): + ... + TypeError: cannot evaluate symbolic expression numerically + """ + return self.parent()(self._maxima_().simplify_sum()) + def canonicalize_radical(self): r""" Choose a canonical branch of the given expression. The square @@ -10067,7 +10140,7 @@ cdef class Expression(CommutativeRingElement): sage: a.solve(t) [] sage: b = a.canonicalize_radical(); b - -23040*(-2.0*e^(1800*t) + 25.0*e^(900*t) - 32.0)*e^(-2400*t) + -23040.0*(-2.0*e^(1800*t) + 25.0*e^(900*t) - 32.0)*e^(-2400*t) sage: b.solve(t) [] sage: b.solve(t, to_poly_solve=True) @@ -10484,7 +10557,7 @@ cdef class Expression(CommutativeRingElement): -a/(q - 1) A divergent geometric series. Do not forget - to forget your assumptions:: + to `forget` your assumptions:: sage: forget() sage: assume(q > 1) @@ -10508,17 +10581,47 @@ cdef class Expression(CommutativeRingElement): sage: (binomial(n,k)*x^k).sum(k, 0, n, algorithm = 'maple') # optional - maple (x + 1)^n + .. note:: + + #. Sage can currently only understand a subset of the output of Maxima, Maple and + Mathematica, so even if the chosen backend can perform the summation the + result might not be convertable into a usable Sage expression. + + TESTS: + Check that the sum in :trac:`10682` is done right:: sage: sum(binomial(n,k)*k^2, k, 2, n) 1/4*(n^2 + n)*2^n - n - .. note:: + This sum used to give a wrong result (:trac:`9635`) but + now gives correct results with all relevant assumptions:: - #. Sage can currently only understand a subset of the output of Maxima, Maple and - Mathematica, so even if the chosen backend can perform the summation the - result might not be convertable into a Sage expression. + sage: (n,k,j)=var('n,k,j') + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) + -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) + sage: assume(j>-1) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) + 1 + sage: forget() + sage: assume(n>=j) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) + -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) + sage: forget() + sage: assume(j==-1) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) + 1 + sage: forget() + sage: assume(j<-1) + sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) + -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) + sage: forget() + Check that :trac:`16176` is fixed:: + + sage: n = var('n') + sage: sum(log(1-1/n^2),n,2,oo) + -log(2) """ from sage.calculus.calculus import symbolic_sum return symbolic_sum(self, *args, **kwds) @@ -10771,6 +10874,73 @@ cdef class Expression(CommutativeRingElement): raise TypeError("this expression must be a relation") return self / x + def implicit_derivative(self, Y, X, n=1): + """ + Return the n'th derivative of Y with respect to X given implicitly by this expression. + + INPUT: + + - ``Y`` - The dependent variable of the implicit expression. + + - ``X`` - The independent variable with respect to which the derivative is taken. + + + - ``n`` - (default : 1) the order of the derivative. + + EXAMPLES:: + + sage: var('x, y') + (x, y) + sage: f = cos(x)*sin(y) + sage: f.implicit_derivative(y, x) + sin(x)*sin(y)/(cos(x)*cos(y)) + sage: g = x*y^2 + sage: g.implicit_derivative(y, x, 3) + -1/4*(y + 2*y/x)/x^2 + 1/4*(2*y^2/x - y^2/x^2)/(x*y) - 3/4*y/x^3 + + It is an error to not include an independent variable term + in the expression:: + + sage: (cos(x)*sin(x)).implicit_derivative(y, x) + Traceback (most recent call last): + ... + ValueError: Expression cos(x)*sin(x) contains no y terms + + + TESTS:: + + sage: var('x,y') # check that the pynac registry is not polluted + (x, y) + sage: psr = copy(sage.symbolic.ring.pynac_symbol_registry) + sage: (x^6*y^5).implicit_derivative(y, x, 3) + -792/125*y/x^3 + 12/25*(15*x^4*y^5 + 28*x^3*y^5)/(x^6*y^4) - 36/125*(20*x^5*y^4 + 43*x^4*y^4)/(x^7*y^3) + sage: psr == sage.symbolic.ring.pynac_symbol_registry + True + """ + from sage.symbolic.ring import SR + from sage.symbolic.function_factory import SymbolicFunction + + if not self.has(Y): + raise ValueError, "Expression {} contains no {} terms".format(self, Y) + x = SR.symbol() + yy = SR.symbol() + y = SymbolicFunction('y', 1)(x) + f = SymbolicFunction('f', 2)(x, yy) + Fx = f.diff(x) + Fy = f.diff(yy) + G = -(Fx/Fy) + G = G.subs({yy: y}) + di = {y.diff(x): -self.diff(X)/self.diff(Y)} + R = G + S = G.diff(x, n - 1) + for i in range(n + 1): + di[y.diff(x, i + 1).subs({x: x})] = R + S = S.subs(di) + R = G.diff(x, i) + for j in range(n + 1 - i): + di[f.diff(x, i, yy, j).subs({x: x, yy: y})] = self.diff(X, i, Y, j) + S = S.subs(di) + return S cdef dict dynamic_class_cache = {} cdef get_dynamic_class_for_function(unsigned serial): @@ -10870,16 +11040,17 @@ cdef get_dynamic_class_for_function(unsigned serial): return cls cdef Expression new_Expression_from_GEx(parent, GEx juice): + cdef type cls cdef Expression nex cdef unsigned serial if is_exactly_a_function(juice): # if the function defines any dynamic methods these are made # available through a dynamic class - cls = get_dynamic_class_for_function(ex_to_function(juice).get_serial()) + cls = get_dynamic_class_for_function(ex_to_function(juice).get_serial()) else: cls = Expression - nex = PY_NEW(cls) + nex = cls.__new__(cls) GEx_construct_ex(&nex._gobj, juice) nex._parent = parent return nex @@ -10936,7 +11107,7 @@ cdef inline ExpressionIterator new_ExpIter_from_Expression(Expression ex): # The const_iterator in GiNaC just keeps an integer index to the current # subexpression. We do the same here, to avoid the trouble of having to # mess with C++ class constructors/destructors. - cdef ExpressionIterator m = PY_NEW(ExpressionIterator) + cdef ExpressionIterator m = ExpressionIterator.__new__(ExpressionIterator) m._ex = ex m._ind = 0 m._len = ex._gobj.nops() diff --git a/src/sage/symbolic/expression_conversions.py b/src/sage/symbolic/expression_conversions.py index 29cac928efc..64b4e1bc6a5 100644 --- a/src/sage/symbolic/expression_conversions.py +++ b/src/sage/symbolic/expression_conversions.py @@ -268,7 +268,7 @@ def get_fake_div(self, ex): d = FakeExpression(d, _operator.mul) if len(n) == 0: - return FakeExpression([SR.one_element(), d], _operator.div) + return FakeExpression([SR.one(), d], _operator.div) elif len(n) == 1: n = n[0] else: diff --git a/src/sage/symbolic/function.pxd b/src/sage/symbolic/function.pxd index bed8de3c8eb..c61aab9d9b3 100644 --- a/src/sage/symbolic/function.pxd +++ b/src/sage/symbolic/function.pxd @@ -1,21 +1,6 @@ from sage.structure.sage_object cimport SageObject -from sage.structure.element cimport Element - include "sage/ext/stdsage.pxi" -# In many applications, such as plotting, these functions are called many times -# repeatedly. This method is slightly faster than sage.structure.coerce.parent -# The only difference is the PyNumber_Check clause. -from cpython.number cimport * -cdef inline parent_c(x): - if PY_TYPE_CHECK(x, Element): - return (x)._parent - elif PyNumber_Check(x): - return PY_TYPE(x) - elif hasattr(x, 'parent'): - return x.parent() - return PY_TYPE(x) - cdef class Function(SageObject): cdef unsigned int _serial cdef int _nargs diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 53616f7098b..fdda0284632 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -17,6 +17,7 @@ from ginac cimport * from sage.rings.integer cimport smallInteger from sage.structure.sage_object cimport SageObject +from sage.structure.element cimport Element, parent_c from expression cimport new_Expression_from_GEx, Expression from ring import SR diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 600b91da2c5..c090982bfcb 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -68,3 +68,47 @@ def mma_free_integrator(expression, v, a=None, b=None): return ans except TypeError: raise ValueError("Unable to parse: %s" % mexpr) + + +def fricas_integrator(expression, v, a=None, b=None): + """ + Integration using FriCAS + + EXAMPLES:: + + sage: from sage.symbolic.integration.external import fricas_integrator # optional - fricas + sage: fricas_integrator(sin(x), x) # optional - fricas + -cos(x) + sage: fricas_integrator(cos(x), x) # optional - fricas + sin(x) + sage: fricas_integrator(1/(x^2-2), x, 0, 1) # optional - fricas + 1/4*(log(3*sqrt(2) - 4) - log(sqrt(2)))*sqrt(2) + sage: fricas_integrator(1/(x^2+6), x, -oo, oo) # optional - fricas + 1/6*pi*sqrt(6) + """ + if not isinstance(expression, Expression): + expression = SR(expression) + if a is None: + result = expression._fricas_().integrate(v) + else: + import sage.rings.infinity + if a == sage.rings.infinity.PlusInfinity(): + a = "%plusInfinity" + elif a == sage.rings.infinity.MinusInfinity(): + a = "%minusInfinity" + if b == sage.rings.infinity.PlusInfinity(): + b = "%plusInfinity" + elif b == sage.rings.infinity.MinusInfinity(): + b = "%minusInfinity" + + result = expression._fricas_().integrate("{}={}..{}".format(v, a, b)) + locals = {str(v): v for v in expression.variables()} + if str(result) == "potentialPole": + raise ValueError("The integrand has a potential pole" + " in the integration interval") + parsed_result = result.unparsed_input_form() + import sage.misc.sage_eval + try: + return sage.misc.sage_eval.sage_eval(parsed_result, locals=locals) + except: + raise ValueError("Unable to parse: {}".format(parsed_result)) diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py index 8a5af7eae80..9919f784071 100644 --- a/src/sage/symbolic/integration/integral.py +++ b/src/sage/symbolic/integration/integral.py @@ -27,6 +27,7 @@ available_integrators['maxima'] = external.maxima_integrator available_integrators['sympy'] = external.sympy_integrator available_integrators['mathematica_free'] = external.mma_free_integrator +available_integrators['fricas'] = external.fricas_integrator ###################################################### # @@ -344,6 +345,8 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): - 'mathematica_free' - use http://integrals.wolfram.com/ + - 'fricas' - use FriCAS (the optional fricas spkg has to be installed) + To prevent automatic evaluation use the ``hold`` argument. EXAMPLES:: @@ -518,6 +521,28 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): sage: integral(e^(-x^2),(x, 0, 0.1)) 0.05623145800914245*sqrt(pi) + An example of an integral that fricas can integrate, but the + default integrator cannot:: + + sage: f(x) = sqrt(x+sqrt(1+x^2))/x + sage: integrate(f(x), x, algorithm="fricas") # optional - fricas + 2*sqrt(x + sqrt(x^2 + 1)) + log(sqrt(x + sqrt(x^2 + 1)) - 1) + - log(sqrt(x + sqrt(x^2 + 1)) + 1) - 2*arctan(sqrt(x + sqrt(x^2 + 1))) + + The following definite integral is not found with the + default integrator:: + + sage: f(x) = (x^4 - 3*x^2 + 6) / (x^6 - 5*x^4 + 5*x^2 + 4) + sage: integrate(f(x), x, 1, 2) + integrate((x^4 - 3*x^2 + 6)/(x^6 - 5*x^4 + 5*x^2 + 4), x, 1, 2) + + Both fricas and sympy give the correct result:: + + sage: integrate(f(x), x, 1, 2, algorithm="fricas") # optional - fricas + -1/2*pi + arctan(1/2) + arctan(2) + arctan(5) + arctan(8) + sage: integrate(f(x), x, 1, 2, algorithm="sympy") + -1/2*pi + arctan(8) + arctan(5) + arctan(2) + arctan(1/2) + ALIASES: integral() and integrate() are the same. EXAMPLES: @@ -718,6 +743,11 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): 48481/1247400*pi 193359161/6227020800*pi 5799919/227026800*pi + + Check that :trac:`12628` is fixed:: + + sage: integrate(1/(sqrt(x)*((1+sqrt(x))^2)),x,1,9) + 1/2 """ expression, v, a, b = _normalize_integral_input(expression, v, a, b) if algorithm is not None: diff --git a/src/sage/symbolic/pynac.pyx b/src/sage/symbolic/pynac.pyx index 99cccf66a26..9815c5d5e0b 100644 --- a/src/sage/symbolic/pynac.pyx +++ b/src/sage/symbolic/pynac.pyx @@ -27,7 +27,7 @@ include "sage/gsl/gsl_sf_result.pxi" include "sage/gsl/gsl_gamma.pxi" -from sage.structure.element import Element +from sage.structure.element cimport Element, parent_c from sage.rings.integer_ring import ZZ from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational @@ -38,7 +38,7 @@ from sage.rings.all import CC from sage.symbolic.expression cimport Expression, new_Expression_from_GEx from sage.symbolic.substitution_map cimport SubstitutionMap, new_SubstitutionMap_from_GExMap from sage.symbolic.function import get_sfunction_from_serial -from sage.symbolic.function cimport Function, parent_c +from sage.symbolic.function cimport Function from sage.symbolic.constants_c cimport PynacConstant import ring @@ -60,7 +60,7 @@ cdef public object ex_to_pyExpression(GEx juice): Used to pass parameters to custom power and series functions. """ cdef Expression nex - nex = PY_NEW(Expression) + nex = Expression.__new__(Expression) GEx_construct_ex(&nex._gobj, juice) nex._parent = ring.SR return nex @@ -317,7 +317,7 @@ cdef public stdstring* py_repr(object o, int level) except +: t = s # Python complexes are always printed with parentheses # we try to avoid double parantheses - if not PY_TYPE_CHECK_EXACT(o, complex) and \ + if type(o) is not complex and \ (' ' in t or '/' in t or '+' in t or '-' in t or '*' in t \ or '^' in t): s = '(%s)'%s @@ -728,8 +728,6 @@ cdef public unsigned py_get_serial_for_new_sfunction(stdstring &s, # Modular helpers ################################################################# -from sage.structure.element cimport Element - cdef public int py_get_parent_char(object o) except -1: if isinstance(o, Element): return (o)._parent.characteristic() @@ -743,9 +741,9 @@ cdef public int py_get_parent_char(object o) except -1: from sage.rings.rational cimport rational_power_parts cdef public object py_rational_power_parts(object base, object exp) except +: - if not PY_TYPE_CHECK_EXACT(base, Rational): + if type(base) is not Rational: base = Rational(base) - if not PY_TYPE_CHECK_EXACT(exp, Rational): + if type(exp) is not Rational: exp = Rational(exp) res= rational_power_parts(base, exp) return res + (bool(res[0] == 1),) @@ -827,7 +825,7 @@ cdef public object py_gcd(object n, object k) except +: return k return n.gcd(k) - if PY_TYPE_CHECK_EXACT(n, Rational) and PY_TYPE_CHECK_EXACT(k, Rational): + if type(n) is Rational and type(k) is Rational: return n.content(k) try: return sage.rings.arith.gcd(n,k) @@ -883,10 +881,10 @@ cdef public object py_real(object x) except +: sage: py_real(complex(2,2)) 2.0 """ - if PY_TYPE_CHECK_EXACT(x, float) or PY_TYPE_CHECK_EXACT(x, int) or \ - PY_TYPE_CHECK_EXACT(x, long): + if type(x) is float or type(x) is int or \ + type(x) is long: return x - elif PY_TYPE_CHECK_EXACT(x, complex): + elif type(x) is complex: return x.real try: @@ -940,9 +938,9 @@ cdef public object py_imag(object x) except +: sage: py_imag(complex(2,2)) 2.0 """ - if PY_TYPE_CHECK_EXACT(x, float): + if type(x) is float: return float(0) - if PY_TYPE_CHECK_EXACT(x, complex): + if type(x) is complex: return x.imag try: return x.imag() @@ -979,8 +977,8 @@ cdef public object py_conjugate(object x) except +: return x # assume is real since it doesn't have an imag attribute. cdef public bint py_is_rational(object x) except +: - return PY_TYPE_CHECK_EXACT(x, Rational) or \ - PY_TYPE_CHECK_EXACT(x, Integer) or\ + return type(x) is Rational or \ + type(x) is Integer or\ IS_INSTANCE(x, int) or IS_INSTANCE(x, long) cdef public bint py_is_equal(object x, object y) except +: @@ -1076,7 +1074,7 @@ def py_is_crational_for_doctest(x): cdef public bint py_is_real(object a) except +: if PyInt_CheckExact(a) or PY_TYPE_CHECK(a, Integer) or\ - PyLong_CheckExact(a) or PY_TYPE_CHECK_EXACT(a, float): + PyLong_CheckExact(a) or type(a) is float: return True return py_imag(a) == 0 @@ -1258,9 +1256,9 @@ cdef public object py_tgamma(object x) except +: sage: py_tgamma(1/2) 1.77245385090552 """ - if PY_TYPE_CHECK_EXACT(x, int) or PY_TYPE_CHECK_EXACT(x, long): + if type(x) is int or type(x) is long: x = float(x) - if PY_TYPE_CHECK_EXACT(x, float): + if type(x) is float: return sage_tgammal(x) # try / except blocks are faster than @@ -1488,7 +1486,7 @@ cdef public object py_exp(object x) except +: sage: py_exp(QQbar(I)) 0.540302305868140 + 0.841470984807897*I """ - if PY_TYPE_CHECK_EXACT(x, float): + if type(x) is float: return math.exp(x) try: return x.exp() @@ -1545,9 +1543,9 @@ cdef public object py_log(object x) except +: """ cdef gsl_complex res cdef double real, imag - if PY_TYPE_CHECK_EXACT(x, int) or PY_TYPE_CHECK_EXACT(x, long): + if type(x) is int or type(x) is long: x = float(x) - if PY_TYPE_CHECK_EXACT(x, float): + if type(x) is float: if (x) > 0: return sage_logl(x) elif x < 0: @@ -1555,7 +1553,7 @@ cdef public object py_log(object x) except +: return PyComplex_FromDoubles(res.dat[0], res.dat[1]) else: return float('-inf') - elif PY_TYPE_CHECK_EXACT(x, complex): + elif type(x) is complex: real = PyComplex_RealAsDouble(x) imag = PyComplex_ImagAsDouble(x) if real == 0 and imag == 0: @@ -1678,7 +1676,7 @@ cdef public object py_sinh(object x) except +: cdef public object py_cosh(object x) except +: - if PY_TYPE_CHECK_EXACT(x, float): + if type(x) is float: return math.cosh(x) try: return x.cosh() @@ -1737,11 +1735,11 @@ cdef public object py_lgamma(object x) except +: """ cdef gsl_sf_result lnr, arg cdef gsl_complex res - if PY_TYPE_CHECK_EXACT(x, int) or PY_TYPE_CHECK_EXACT(x, long): + if type(x) is int or type(x) is long: x = float(x) - if PY_TYPE_CHECK_EXACT(x, float): + if type(x) is float: return sage_lgammal(x) - elif PY_TYPE_CHECK_EXACT(x, complex): + elif type(x) is complex: gsl_sf_lngamma_complex_e(PyComplex_RealAsDouble(x),PyComplex_ImagAsDouble(x), &lnr, &arg) res = gsl_complex_polar(lnr.val, arg.val) return PyComplex_FromDoubles(res.dat[0], res.dat[1]) diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index 13b9318afce..d883c622d91 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -572,7 +572,7 @@ cdef class SymbolicRing(CommutativeRing): else: # initialize a new symbol # Construct expression - e = PY_NEW(Expression) + e = Expression.__new__(Expression) e._parent = SR if name is None: # Check if we need a temporary anonymous new symbol diff --git a/src/sage/symbolic/substitution_map.pyx b/src/sage/symbolic/substitution_map.pyx index b122688e236..7b266d10b44 100644 --- a/src/sage/symbolic/substitution_map.pyx +++ b/src/sage/symbolic/substitution_map.pyx @@ -85,7 +85,7 @@ cdef SubstitutionMap new_SubstitutionMap_from_GExMap(const GExMap& smap): SubsMap """ cdef SubstitutionMap result - result = PY_NEW(SubstitutionMap) + result = SubstitutionMap.__new__(SubstitutionMap) GEx_construct_exmap(&result._gmapobj, smap) return result diff --git a/src/sage/tests/book_stein_ent.py b/src/sage/tests/book_stein_ent.py index 900e7bd13c3..e134c662d35 100644 --- a/src/sage/tests/book_stein_ent.py +++ b/src/sage/tests/book_stein_ent.py @@ -392,46 +392,42 @@ 86 # Several of the examples below had to be changed due to improved -# behavior of the continued_fraction function #8017. +# behavior of the continued_fraction function #8017 and #14567. sage: continued_fraction(17/23) -[0, 1, 2, 1, 5] +[0; 1, 2, 1, 5] sage: reset('e') sage: continued_fraction(e) -[2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1] -sage: continued_fraction(e, bits=21) +[2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, ...] +sage: continued_fraction_list(e, bits=21) [2, 1, 2, 1, 1, 4, 1, 1, 6] -sage: continued_fraction(e, bits=30) +sage: continued_fraction_list(e, bits=30) [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8] sage: a = continued_fraction(17/23); a -[0, 1, 2, 1, 5] +[0; 1, 2, 1, 5] sage: a.value() 17/23 sage: b = continued_fraction(6/23); b -[0, 3, 1, 5] -sage: a + b -[1] -sage: c = continued_fraction(pi,bits=35); c -[3, 7, 15, 1, 292, 1] -sage: c.convergents() -[3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215] +[0; 3, 1, 5] sage: c = continued_fraction(pi); c -[3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14] -sage: for n in range(-1, len(c)): -... print c.pn(n)*c.qn(n-1) - c.qn(n)*c.pn(n-1), +[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, ...] +sage: [c.convergent(i) for i in xrange(5)] +[3, 22/7, 333/106, 355/113, 103993/33102] +sage: for n in range(-1, 13): +....: print c.p(n)*c.q(n-1) - c.q(n)*c.p(n-1), 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 -sage: for n in range(len(c)): -... print c.pn(n)*c.qn(n-2) - c.qn(n)*c.pn(n-2), +sage: for n in range(13): +....: print c.p(n)*c.q(n-2) - c.q(n)*c.p(n-2), 3 -7 15 -1 292 -1 1 -1 2 -1 3 -1 14 sage: c = continued_fraction([1,2,3,4,5]) sage: c.convergents() [1, 3/2, 10/7, 43/30, 225/157] -sage: [c.pn(n) for n in range(len(c))] +sage: [c.p(n) for n in range(len(c))] [1, 3, 10, 43, 225] -sage: [c.qn(n) for n in range(len(c))] +sage: [c.q(n) for n in range(len(c))] [1, 2, 7, 30, 157] sage: c = continued_fraction([1,1,1,1,1,1,1,1]) -sage: v = [(i, c.pn(i)/c.qn(i)) for i in range(len(c))] +sage: v = [(i, c.p(i)/c.q(i)) for i in range(len(c))] sage: P = point(v, rgbcolor=(0,0,1), pointsize=40) sage: L = line(v, rgbcolor=(0.5,0.5,0.5)) sage: L2 = line([(0,c.value()),(len(c)-1,c.value())], \ @@ -441,18 +437,18 @@ ... x = (1 + sqrt(RealField(bits)(5))) / 2 ... return continued_fraction(x) sage: cf(10) -[1, 1, 1, 1, 1, 1, 1] +[1; 1, 1, 1, 1, 1, 1, 2] sage: cf(30) -[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +[1; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2] sage: cf(50) -[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + [1; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2] sage: def cf_sqrt_d(d, bits): ... x = sqrt(RealField(bits)(d)) ... return continued_fraction(x) sage: cf_sqrt_d(389,50) -[19, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 2] +[19; 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38] sage: cf_sqrt_d(389,100) -[19, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1] +[19; 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 2] sage: def newton_root(f, iterates=2, x0=0, prec=53): ... x = RealField(prec)(x0) ... R = PolynomialRing(ZZ,'x') @@ -465,9 +461,9 @@ sage: a = newton_root(3847*x^2 - 14808904*x + 36527265); a 2.46815700480740 sage: cf = continued_fraction(a); cf -[2, 2, 7, 2, 1, 5, 1, 1, 1, 1, 1, 1, 103, 8, 1, 2, 3] +[2; 2, 7, 2, 1, 5, 1, 1, 1, 1, 1, 1, 103, 8, 1, 2, 3, 2] sage: c = cf[:12]; c -[2, 2, 7, 2, 1, 5, 1, 1, 1, 1, 1, 1] +[2; 2, 7, 2, 1, 5, 1, 1, 1, 1, 2] sage: c.value() 9495/3847 sage: def sum_of_two_squares_naive(n): diff --git a/src/sage/tests/book_stein_modform.py b/src/sage/tests/book_stein_modform.py index 4aec68ada6f..730cd854210 100644 --- a/src/sage/tests/book_stein_modform.py +++ b/src/sage/tests/book_stein_modform.py @@ -67,7 +67,7 @@ sage: S.integral_basis() # basis over ZZ. ({-1/8, 0}, {-1/9, 0}) sage: set_modsym_print_mode ('manin') # set it back -sage: convergents(4/7) +sage: continued_fraction(4/7).convergents() [0, 1, 1/2, 4/7] sage: M = ModularSymbols(2,2) sage: M diff --git a/src/sage/tests/french_book/nonlinear_doctest.py b/src/sage/tests/french_book/nonlinear_doctest.py index d61bba5cf20..cb175085117 100644 --- a/src/sage/tests/french_book/nonlinear_doctest.py +++ b/src/sage/tests/french_book/nonlinear_doctest.py @@ -241,11 +241,11 @@ sage: a, b (-3.14159265358979, 3.14159265358979) sage: bisection = intervalgen(f, phi, a, b) - sage: bisection.next() + sage: next(bisection) -3.14159265358979 - sage: bisection.next() + sage: next(bisection) 3.14159265358979 - sage: bisection.next() + sage: next(bisection) 0.000000000000000 Sage example in ./nonlinear.tex, line 805:: @@ -257,10 +257,10 @@ ....: assert isinstance(series, GeneratorType) ....: assert isinstance(check, FunctionType) ....: niter = 2 - ....: v, w = series.next(), series.next() + ....: v, w = next(series), next(series) ....: while (niter <= maxit): ....: niter += 1 - ....: u, v, w = v, w, series.next() + ....: u, v, w = v, w, next(series) ....: if check(u, v, w, prec): ....: print 'After {0} iterations: {1}'.format(niter, w) ....: return @@ -285,7 +285,7 @@ sage: g = plot(f, a, b, rgbcolor='blue') sage: phi(s, t) = t - f(t) * (s - t) / (f(s) - f(t)) sage: falsepos = intervalgen(f, phi, a, b) - sage: u, v, w = falsepos.next(), falsepos.next(), falsepos.next() + sage: u, v, w = next(falsepos), next(falsepos), next(falsepos) sage: niter = 3 sage: while niter < 9: ....: g += line([(u, 0), (u, f(u))], rgbcolor='red', @@ -298,7 +298,7 @@ ....: u, v = u, w ....: else: ....: u, v = w, v - ....: w = falsepos.next() + ....: w = next(falsepos) ....: niter += 1 Sage example in ./nonlinear.tex, line 942:: @@ -319,7 +319,7 @@ sage: g = plot(f, a, b, rgbcolor='blue') sage: phi(s, t) = t - f(t) * (s - t) / (f(s) - f(t)) sage: falsepos = intervalgen(f, phi, a, b) - sage: u, v, w = falsepos.next(), falsepos.next(), falsepos.next() + sage: u, v, w = next(falsepos), next(falsepos), next(falsepos) sage: niter = 3 sage: while niter < 7: ....: g += line([(u, 0), (u, f(u))], rgbcolor='red', @@ -332,7 +332,7 @@ ....: u, v = u, w ....: else: ....: u, v = w, v - ....: w = falsepos.next() + ....: w = next(falsepos) ....: niter += 1 Sage example in ./nonlinear.tex, line 1025:: @@ -359,14 +359,14 @@ sage: generator = newtongen(f, a) sage: g = plot(f, a, b, rgbcolor='blue') - sage: u, v = generator.next(), generator.next() + sage: u, v = next(generator), next(generator) sage: niter = 2 sage: while niter < 6: ....: g += point((u, 0), rgbcolor='red') ....: g += line([(u, 0), (u, f(u))], rgbcolor='red', ....: linestyle=':') ....: g += line([(u, f(u)), (v, 0)], rgbcolor='red') - ....: u, v = v, generator.next() + ....: u, v = v, next(generator) ....: niter += 1 Sage example in ./nonlinear.tex, line 1109:: @@ -395,14 +395,14 @@ sage: g = plot(f, a, b, rgbcolor='blue') sage: sequence = secantgen(f, a) - sage: u, v = sequence.next(), sequence.next() + sage: u, v = next(sequence), next(sequence) sage: niter = 2 sage: while niter < 6: ....: g += point((u, 0), rgbcolor='red') ....: g += line([(u, 0), (u, f(u))], rgbcolor='red', ....: linestyle=':') ....: g += line([(u, f(u)), (v, 0)], rgbcolor='red') - ....: u, v = v, sequence.next() + ....: u, v = v, next(sequence) ....: niter += 1 Sage example in ./nonlinear.tex, line 1198:: @@ -448,10 +448,10 @@ ....: assert isinstance(sequence, GeneratorType) ....: values = deque(maxlen=3) ....: for i in range(3): - ....: values.append(sequence.next()) + ....: values.append(next(sequence)) ....: yield values[i] ....: while 1: - ....: values.append(sequence.next()) + ....: values.append(next(sequence)) ....: u, v, w = values ....: yield u - (v - u)^2 / (w - 2 * v + u) @@ -484,9 +484,9 @@ sage: a, b = pi/2, pi sage: generator = newtongen(f, a) - sage: generator.next() + sage: next(generator) 1/2*pi - sage: generator.next() + sage: next(generator) 1/2*pi - (e^(1/2*pi) - 10)*e^(-1/2*pi) """ diff --git a/src/sage/version.py b/src/sage/version.py index e5498a0a7b3..6af99d7ad07 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,4 +1,4 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '6.5.beta6' -date = '2015-01-24' +version = '6.6.beta0' +date = '2015-02-18'